starlight-theme · git:20261002.e6369ee · 2026-10-02 · sha256 f9203444a212c328
starlight-theme git:20261002.e6369eeA
Immutable. This exact content never changes and is served at /api/v1/blob/f9203444a212c328.
---
name: starlight-theme
description: Create and apply custom themes to an Astro Starlight documentation site. Use when customizing colors, typography, or spacing via CSS custom properties, using the Tailwind CSS integration, applying light/dark mode variants, or loading custom fonts.
---
# Starlight Theming
Starlight exposes its entire visual design through CSS custom properties. Override any variable to change colors, typography, and layout — with or without Tailwind.
## When to Use
- Changing the color palette (accent color, grays, backgrounds)
- Swapping fonts or adjusting text sizes
- Applying a consistent brand identity
- Integrating Tailwind CSS into a Starlight project
## When Not to Use
- Replacing entire UI sections (header, footer, sidebar) — use `starlight-custom-component` instead
- Per-page layout changes without global theming intent
## Philosophy
**Starlight styles live in CSS cascade layers. Unlayered CSS always wins.**
- **CSS custom properties are the API.** Set `--sl-*` variables on `:root` to change every element that reads them. See [css-variables-reference.md](./references/css-variables-reference.md) for the full list.
- **Cascade layers determine priority.** Any CSS you add without an `@layer` block is unlayered and automatically takes precedence over Starlight's named layers.
- **Tailwind requires different wiring.** The `@astrojs/starlight-tailwind` compatibility package must be imported before Tailwind's own CSS or Starlight's styles break.
## Approach 1: Custom CSS File
**Step 1 — Create the file:**
```css
/* src/styles/custom.css */
:root {
--sl-color-accent-low: #1a1a4e;
--sl-color-accent: #3d52d5;
--sl-color-accent-high: #b4bffe;
--sl-font: 'Inter', sans-serif;
--sl-content-width: 50rem;
}
:root[data-theme='dark'] {
--sl-color-bg: #0f172a;
}
```
**Step 2 — Register in `astro.config.mjs`:**
```js
starlight({
customCss: ['./src/styles/custom.css'],
})
```
## Approach 2: Tailwind CSS Integration
```bash
npx astro add tailwind
npm install @astrojs/starlight-tailwind
```
Replace `src/styles/global.css` with:
```css
@layer base, starlight, theme, components, utilities;
@import '@astrojs/starlight-tailwind';
@import 'tailwindcss/theme.css' layer(theme);
@import 'tailwindcss/utilities.css' layer(utilities);
@theme {
--font-sans: 'Inter';
--color-accent-500: var(--color-indigo-500);
/* Map full accent and gray scales — see references for complete example */
}
```
Update `astro.config.mjs`:
```js
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
integrations: [starlight({ customCss: ['./src/styles/global.css'] })],
vite: { plugins: [tailwindcss()] },
});
```
See [css-variables-reference.md](./references/css-variables-reference.md) for the full Tailwind `@theme` color scale mapping.
## Anti-Patterns
### NEVER override Starlight styles without the `customCss` array
**WHY:** CSS files not registered in `customCss` are excluded from the Starlight build. **Consequence:** Styles are silently ignored.
**BAD:** Add a `<style>` block in a layout component.
**GOOD:** Register a CSS file in `customCss` in `astro.config.mjs`.
### NEVER add raw Tailwind imports without the compatibility layer
**WHY:** Tailwind's Preflight reset conflicts with Starlight's base styles. **Consequence:** Visual regressions, broken dark mode toggle.
**BAD:** Import `tailwindcss` without `@astrojs/starlight-tailwind` first.
**GOOD:** `@import '@astrojs/starlight-tailwind'` before Tailwind imports.
### NEVER use `.dark` class selectors for dark mode
**WHY:** Starlight uses `data-theme="dark"` on `<html>`, not a `.dark` class. **Consequence:** Dark mode styles never activate.
**BAD:** `.dark:bg-gray-900` (never matches in Starlight)
**GOOD** (plain CSS):
```css
:root[data-theme='dark'] { --sl-color-bg: #0f172a; }
```
Use `dark:` Tailwind variants only after installing `@astrojs/starlight-tailwind`.
### NEVER mix `--sl-*` variables with Tailwind `@theme` overrides
**WHY:** The two systems map to each other through `@astrojs/starlight-tailwind`. Setting both creates conflicting sources of truth. **Consequence:** Colors partially apply or behave differently in light vs. dark mode.
**BAD:** Set `--sl-color-accent` in CSS while also defining `--color-accent-*` in `@theme`.
**GOOD:** Choose one approach and apply all overrides through it.
### NEVER forget `font-display: swap` in custom `@font-face`
**WHY:** Without it, browsers may block rendering until the font downloads. **Consequence:** Flash of invisible text (FOIT) on slower connections.
**BAD:** `@font-face { font-family: 'X'; src: url('...'); }`
**GOOD:** Add `font-display: swap;` to every `@font-face`.
### NEVER wrap your overrides in a named layer that Starlight's layers outrank
**WHY:** Unlayered CSS always takes precedence over Starlight's named layers; a lower-priority layer can lose to Starlight's own rules. **Consequence:** Overrides silently lose.
**BAD:** `@layer starlight { :root { --sl-color-accent: #3d52d5; } }`
**GOOD:** Put the `:root` overrides in plain CSS with no `@layer` block.
### NEVER drop the layer order declaration in the Tailwind setup
**WHY:** `@layer base, starlight, theme, components, utilities;` fixes the cascade between Tailwind and Starlight. **Consequence:** Utilities and Starlight styles override each other unpredictably.
**BAD:** Start `global.css` with the Tailwind imports only.
**GOOD:** Start `global.css` with the `@layer` order line, then the imports.
### NEVER set a single accent variable and expect a full palette
**WHY:** Accent colours are a low, mid and high set. **Consequence:** Backgrounds, links and highlights mismatch in light and dark mode.
**BAD:** `:root { --sl-color-accent: #3d52d5; }` alone.
**GOOD:** Set `--sl-color-accent-low`, `--sl-color-accent` and `--sl-color-accent-high` together.
### NEVER use this skill to replace UI sections such as header, footer or sidebar
**WHY:** Replacing markup needs component overrides, which CSS variables cannot do. **Consequence:** Fragile selectors that break on Starlight updates.
**BAD:** Hide the sidebar with CSS and rebuild it by hand.
**GOOD:** Use `starlight-custom-component` to override the component.
## References
| Topic | Reference | When to Use |
| --- | --- | --- |
| CSS variables | [CSS Variables Reference](./references/css-variables-reference.md) | Looking up `--sl-*` variables and the Tailwind `@theme` scale mapping |
| Styling guide | [CSS & Styling Guide](https://starlight.astro.build/guides/css-and-tailwind/) | Learning the official theming flow |
| Source variables | [Starlight CSS variables (props.css)](https://github.com/withastro/starlight/blob/main/packages/starlight/style/props.css) | Checking the full variable list |
| Colour editor | [Color Theme Editor](https://starlight.astro.build/guides/css-and-tailwind/#theming) | Generating accent and gray scales |
| Fonts | [Fontsource](https://fontsource.org/) | Self-hosting custom fonts |