Starlight Styling and Theme Customization Tutorial

A practical guide to safely customizing the visual design of an Astro Starlight site with custom CSS, theme variables, colors, typography, spacing, cards, dark mode, and layout adjustments.

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:

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:

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:

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:

Use regular CSS if:

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:

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

  1. Create src/styles/custom.css.
  2. Add content width and accent color variables.
  3. Add dark mode accent colors.
  4. Add homepage card styles.
  5. Add a lesson callout style.
  6. Register the file with customCss.
  7. Add a card grid to your homepage.
  8. Add a callout to one lesson page.
  9. Test light mode and dark mode.
  10. 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