What You Are Learning
This tutorial teaches how to customize the look and feel of an Astro Starlight site without immediately replacing Starlight's built-in components.
You will learn how to:
- Add a custom CSS file to a Starlight project.
- Change colors using Starlight CSS variables.
- Adjust typography, spacing, and content width.
- Style homepage cards, lesson cards, callouts, and world bible panels.
- Handle light mode and dark mode safely.
- Know when CSS is enough and when component overrides are needed.
The Big Idea
Starlight already provides a complete documentation design system: layout, sidebar, search, typography, content width, code blocks, headings, colors, dark mode, and page structure.
The safest customization path is:
Start with default Starlight
↓
Add custom CSS
↓
Adjust theme variables
↓
Add custom utility classes
↓
Create reusable components
↓
Override built-in components only when necessary
Do not jump directly to component overrides for basic visual changes. Most theme changes should start with CSS.
Where Custom Styling Lives
Create a custom CSS file inside the src/ folder:
src/styles/custom.css
Then register it in astro.config.mjs using Starlight's customCss option.
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
export default defineConfig({
integrations: [
starlight({
title: 'My Starlight Site',
customCss: ['./src/styles/custom.css'],
}),
],
});
This keeps custom design work in one predictable place.
Why Use customCss Instead of Random Style Tags?
A Starlight site can grow into dozens or hundreds of pages. If each page has its own random styles, the site becomes difficult to maintain.
| Approach | Result |
|---|---|
| One custom CSS file | Consistent, maintainable styling. |
| Inline styles on many pages | Hard to update and easy to break. |
| Component-level styles | Good for reusable components. |
| Component overrides | Powerful, but heavier and more fragile. |
Basic Custom CSS Starter
Create:
src/styles/custom.css
Add a safe starter stylesheet:
:root {
--sl-content-width: 52rem;
}
.hero-note {
border: 1px solid var(--sl-color-gray-5);
border-radius: 0.75rem;
padding: 1rem;
background: var(--sl-color-bg-nav);
}
.card-grid {
display: grid;
gap: 1rem;
grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
}
.card {
border: 1px solid var(--sl-color-gray-5);
border-radius: 0.75rem;
padding: 1rem;
background: var(--sl-color-bg-nav);
}
This gives you a starting point for card layouts, callouts, and homepage sections.
Understanding Starlight CSS Variables
Starlight exposes many design values as CSS custom properties, also called CSS variables. These variables control things like colors, text sizes, spacing, and layout width.
A CSS variable looks like this:
--sl-content-width: 52rem;
You can use a CSS variable like this:
max-width: var(--sl-content-width);
CSS variables are useful because they let you customize Starlight without rewriting the whole theme.
Change the Main Content Width
For tutorial and worldbuilding pages, you may want slightly wider content than the default.
:root {
--sl-content-width: 56rem;
}
Use this carefully. If the text column is too wide, reading becomes harder. A good content width usually supports comfortable reading, not maximum screen usage.
Change Typography Size
You can adjust Starlight typography variables. For example:
:root {
--sl-text-5xl: 3.25rem;
--sl-text-4xl: 2.5rem;
--sl-text-3xl: 2rem;
}
Use moderate changes. Very large headings can make documentation feel less readable, especially on smaller screens.
Theme Colors
Starlight uses color variables for its interface and accents. A common safe customization is changing the accent colors.
:root {
--sl-color-accent-low: #e0f2fe;
--sl-color-accent: #0284c7;
--sl-color-accent-high: #0c4a6e;
}
The general pattern is:
accent-low: soft background or subtle emphasis.accent: main accent color.accent-high: stronger contrast color.
Dark Mode Colors
Starlight supports light and dark themes. If you customize colors, check both modes.
You can target dark mode using Starlight's dark theme selector:
:root[data-theme='dark'] {
--sl-color-accent-low: #082f49;
--sl-color-accent: #38bdf8;
--sl-color-accent-high: #e0f2fe;
}
The same color that works well in light mode may be too bright or too low-contrast in dark mode.
Light Mode Colors
You can also target light mode directly:
:root[data-theme='light'] {
--sl-color-accent-low: #e0f2fe;
--sl-color-accent: #0284c7;
--sl-color-accent-high: #0c4a6e;
}
When possible, test your site with the Starlight theme switcher to confirm that both appearances are readable.
Color Safety Checklist
When changing colors, check:
- Links are still easy to identify.
- Text has enough contrast against backgrounds.
- Code blocks remain readable.
- Sidebar text remains readable.
- Focus outlines are still visible.
- Dark mode is not too bright.
- Light mode is not too washed out.
Custom Homepage Cards
Homepage cards are useful for tutorial paths, world bible categories, and documentation sections.
Markdown or MDX page content:
<div class="home-card-grid">
<article class="home-card">
<h2>Beginner Lessons</h2>
<p>Start with Astro, Starlight, Markdown, and YAML.</p>
<a href="/lessons/beginner/">Start beginner lessons</a>
</article>
<article class="home-card">
<h2>World Bible Setup</h2>
<p>Create regions, factions, characters, locations, and timelines.</p>
<a href="/worldbuilding/">Build a world bible</a>
</article>
</div>
Custom CSS:
.home-card-grid {
display: grid;
gap: 1rem;
grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
margin-block: 2rem;
}
.home-card {
border: 1px solid var(--sl-color-gray-5);
border-radius: 1rem;
padding: 1.25rem;
background: var(--sl-color-bg-nav);
}
.home-card h2 {
margin-top: 0;
}
Lesson Callout Styling
Callouts are useful for explanations, warnings, reminders, and analogies.
.lesson-callout {
border-inline-start: 0.35rem solid var(--sl-color-accent);
border-radius: 0.75rem;
padding: 1rem;
background: var(--sl-color-accent-low);
color: var(--sl-color-accent-high);
}
.lesson-callout h2,
.lesson-callout h3 {
margin-top: 0;
}
Usage in Markdown or MDX:
<aside class="lesson-callout">
<h2>Remember</h2>
<p>Markdown is for writing. MDX is for writing plus components.</p>
</aside>
World Bible Panel Styling
For worldbuilding pages, use panels for fast reference information.
.world-panel {
border: 1px solid var(--sl-color-gray-5);
border-radius: 1rem;
padding: 1rem;
background: linear-gradient(
180deg,
var(--sl-color-bg-nav),
var(--sl-color-bg)
);
}
.world-panel dl {
display: grid;
gap: 0.5rem;
}
.world-panel dt {
font-weight: 700;
}
.world-panel dd {
margin: 0;
}
Usage:
<aside class="world-panel">
<h2>Region Summary</h2>
<dl>
<dt>Region</dt>
<dd>Austral Confluence</dd>
<dt>Magic Level</dt>
<dd>High</dd>
<dt>Technology Level</dt>
<dd>Variable</dd>
</dl>
</aside>
RPG Character Stat Block Styling
For character sheets, create a stat grid.
.stat-grid {
display: grid;
gap: 0.75rem;
grid-template-columns: repeat(auto-fit, minmax(6rem, 1fr));
}
.stat-box {
border: 1px solid var(--sl-color-gray-5);
border-radius: 0.75rem;
padding: 0.75rem;
text-align: center;
background: var(--sl-color-bg-nav);
}
.stat-box strong {
display: block;
font-size: 1.5rem;
}
Usage:
<div class="stat-grid">
<div class="stat-box"><strong>14</strong>DEX</div>
<div class="stat-box"><strong>16</strong>INT</div>
<div class="stat-box"><strong>18</strong>CHA</div>
</div>
Style Code Blocks Carefully
Starlight already styles code blocks well. Avoid heavy customization unless needed.
A light touch is safer:
pre {
border-radius: 0.75rem;
}
Avoid changing code block text color, background color, or syntax highlighting colors unless you test carefully in both light and dark mode.
Custom Link Styles
Links should be easy to see. You can make content links slightly stronger:
.sl-markdown-content a {
text-underline-offset: 0.2em;
}
.sl-markdown-content a:hover {
text-decoration-thickness: 0.15em;
}
Do not remove underlines from body links unless another clear visual signal remains.
Spacing Improvements
For long tutorial pages, spacing helps readability.
.sl-markdown-content section,
.sl-markdown-content .tutorial-section {
margin-block: 2rem;
}
.sl-markdown-content h2 {
margin-top: 2.5rem;
}
Use spacing to separate ideas. Avoid making pages feel cramped.
Using CSS Classes in Markdown
Markdown supports regular HTML. You can add custom classes where needed.
<div class="lesson-callout">
<h2>Key Idea</h2>
<p>Use CSS variables first before overriding Starlight components.</p>
</div>
This is useful for simple visual blocks. If the pattern appears often, consider making a reusable Astro component.
When to Make a Component Instead
Use a component when a styled pattern needs repeated structure.
| Situation | Best Choice |
|---|---|
| One custom box on one page | HTML plus CSS class |
| Same callout appears across many pages | Reusable Astro component |
| Need props like title, type, icon, or status | Reusable Astro component |
| Need to change Starlight's header or sidebar | Component override |
Custom Fonts
Starlight uses system fonts by default, which is fast and reliable. Custom fonts can make a site feel more branded, but they add maintenance and performance concerns.
If you add a font package, register it through customCss along with your stylesheet:
starlight({
title: 'My Starlight Site',
customCss: [
'@fontsource/inter',
'./src/styles/custom.css',
],
})
Then use the font in CSS:
:root {
--sl-font: 'Inter', system-ui, sans-serif;
}
Do not overuse decorative fonts in documentation. Readability matters more than flair.
Using Tailwind CSS
Starlight can be used with Tailwind CSS, but for many documentation sites, normal CSS is simpler and less fragile.
Use Tailwind if:
- Your project already uses Tailwind.
- You are building many custom components.
- You are comfortable with Tailwind conventions.
Use regular CSS if:
- You mainly need theme colors, spacing, cards, and callouts.
- You want the simplest possible customization path.
- You are building a mostly Markdown documentation site.
Safe Theme Customization Example
Here is a complete starter custom.css file:
:root {
--sl-content-width: 54rem;
--sl-color-accent-low: #e0f2fe;
--sl-color-accent: #0284c7;
--sl-color-accent-high: #0c4a6e;
}
:root[data-theme='dark'] {
--sl-color-accent-low: #082f49;
--sl-color-accent: #38bdf8;
--sl-color-accent-high: #e0f2fe;
}
.home-card-grid {
display: grid;
gap: 1rem;
grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
margin-block: 2rem;
}
.home-card,
.lesson-card,
.world-panel {
border: 1px solid var(--sl-color-gray-5);
border-radius: 1rem;
padding: 1rem;
background: var(--sl-color-bg-nav);
}
.lesson-callout {
border-inline-start: 0.35rem solid var(--sl-color-accent);
border-radius: 0.75rem;
padding: 1rem;
background: var(--sl-color-accent-low);
color: var(--sl-color-accent-high);
}
.stat-grid {
display: grid;
gap: 0.75rem;
grid-template-columns: repeat(auto-fit, minmax(6rem, 1fr));
}
.stat-box {
border: 1px solid var(--sl-color-gray-5);
border-radius: 0.75rem;
padding: 0.75rem;
text-align: center;
background: var(--sl-color-bg-nav);
}
Testing Your Styling
Run the development server:
npm run dev
Then check:
- Homepage layout.
- Normal documentation pages.
- Long tutorial pages.
- Code blocks.
- Sidebar readability.
- Mobile layout.
- Light mode.
- Dark mode.
Then run:
npm run build
npm run preview
Preview the built version before deploying.
Common Styling Mistakes
Changing too much too early
Start small. Change the accent color, content width, and a few custom card styles first.
Ignoring dark mode
A color that looks good in light mode may be unreadable in dark mode.
Overriding Starlight internals unnecessarily
If a CSS variable or simple class works, use that before replacing components.
Using low-contrast backgrounds
Documentation must be readable. Avoid dark text on dark backgrounds or bright text on bright backgrounds.
Making content too wide
Wide layouts can look impressive, but long lines are harder to read.
When CSS Is Not Enough
Use component overrides only when you need to change the structure or behavior of a built-in Starlight component.
| Goal | Use CSS? | Use Override? |
|---|---|---|
| Change accent colors | Yes | No |
| Make content column wider | Yes | No |
| Add card styles | Yes | No |
| Replace the header layout | Maybe | Yes |
| Add custom content to every page footer | Maybe | Often yes |
| Change sidebar behavior | Maybe | Often yes |
Mini Project: Create a Custom Theme Layer
- Create
src/styles/custom.css. - Add content width and accent color variables.
- Add dark mode accent colors.
- Add homepage card styles.
- Add a lesson callout style.
- Register the file with
customCss. - Add a card grid to your homepage.
- Add a callout to one lesson page.
- Test light mode and dark mode.
- Run
npm run build.
Cheat Sheet
| Need | Use |
|---|---|
| Add site-wide CSS | customCss |
| Change content width | --sl-content-width |
| Change accent colors | --sl-color-accent |
| Target dark mode | :root[data-theme='dark'] |
| Target light mode | :root[data-theme='light'] |
| Style homepage cards | Custom classes in Markdown/MDX |
| Repeat a styled pattern | Astro component |
| Change built-in layout structure | Component override |
Simple Rule of Thumb
Use CSS variables for theme changes.
Use custom classes for cards and callouts.
Use components for repeated visual patterns.
Use component overrides only for structural changes.
Always test light mode, dark mode, mobile, and build output.
What to Learn Next
- Asset management for images, maps, and downloads.
- Custom MDX components for card grids and callouts.
- Component overrides for headers, footers, and page structure.
- Content collection indexes with styled cards.
- Mermaid diagrams in Astro/Starlight.
- Deployment testing for styled Starlight sites.