Skills for setting up and customizing Astro Starlight documentation sites, covering project setup, custom theming, and component overrides.
77
96%
Does it follow best practices?
Impact
—
No eval scenarios have been run
Passed
No known issues
Starlight exposes its entire visual design through CSS custom properties. Override any variable to change colors, typography, and layout — with or without Tailwind.
starlight-custom-component insteadStarlight styles live in CSS cascade layers. Unlayered CSS always wins.
--sl-* variables on :root to change every element that reads them. See css-variables-reference.md for the full list.@layer block is unlayered and automatically takes precedence over Starlight's named layers.@astrojs/starlight-tailwind compatibility package must be imported before Tailwind's own CSS or Starlight's styles break.Step 1 — Create the file:
/* 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:
starlight({
customCss: ['./src/styles/custom.css'],
})npx astro add tailwind
npm install @astrojs/starlight-tailwindReplace src/styles/global.css with:
@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:
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
integrations: [starlight({ customCss: ['./src/styles/global.css'] })],
vite: { plugins: [tailwindcss()] },
});See css-variables-reference.md for the full Tailwind @theme color scale mapping.
customCss arrayWHY: CSS files not registered in customCss are excluded from the Starlight build.
BAD: Add a <style> block in a layout component.
GOOD: Register a CSS file in customCss in astro.config.mjs.
Consequence: Styles are silently ignored.
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.
.dark class selectors for dark modeWHY: 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):
:root[data-theme='dark'] { --sl-color-bg: #0f172a; }Use dark: Tailwind variants only after installing @astrojs/starlight-tailwind.
--sl-* variables with Tailwind @theme overridesWHY: The two systems map to each other through @astrojs/starlight-tailwind. Setting both creates conflicting sources of truth.
BAD: Set --sl-color-accent in CSS while also defining --color-accent-* in @theme.
GOOD: Choose one approach and apply all overrides through it.
Consequence: Colors partially apply or behave differently in light vs. dark mode.
font-display: swap in custom @font-faceWHY: Without it, browsers may block rendering until the font downloads.
BAD: @font-face { font-family: 'X'; src: url('...'); }
GOOD: Add font-display: swap; to every @font-face.
Consequence: Flash of invisible text (FOIT) on slower connections.