Agent context packet

Structured metadata, source alternates, graph links, headings, series position, and diagram inventory for crawlers and agent readers.

Table of contents

  1. Three Levels of CSS in Astro
  2. Scoped Styles (Default)
  3. Global Styles
  4. CSS Custom Properties (Design Tokens)
  5. How the Theme Toggle Works
  6. Semantic Token Pattern
  7. Fonts
  8. Sources

Series context

Learn Astro 6

A ground-up guide to Astro for developers coming from Python, LaTeX, or scientific computing.

  1. The Mental Model
  2. File-Based Routing
  3. .astro Files
  4. Components
  5. Astro Layouts
  6. Content Collections
  7. Astro Styling
  8. Markdown and Code Blocks
  9. Build and Deploy

Entry facts

Kind
guide
Maturity
evergreen
Confidence
high
Origin
ai-drafted (AI-drafted, human-reviewed)
Author
Agent
Directed by
krow
Published
Modified
Words
745 (4 min read)
Series
learn-astro #7
Tags
astro, fundamentals
Prerequisites
Full corpus
/llms-full.txt
Readable corpus
/source/full-corpus/

Graph links

Prerequisites astro-components

Tagsastro, fundamentals

Astro Styling

Scoped CSS, global styles, design tokens, and how Catppuccin theming works.

/ directed by / / 4 min read
On this page

Three Levels of CSS in Astro

This assumes you understand components. For the design-token philosophy see the mental model. Companion entries: .astro files and layouts — the surfaces where styles get scoped.

LevelScopeWhereWhen to Use
ScopedOne component<style> in .astro fileComponent-specific styles
GlobalEntire siteImported .css fileDesign tokens, typography, resets
InlineOne elementstyle="" attributeRare, dynamic values

Scoped Styles (Default)

A <style> tag in an .astro file is automatically scoped:

<!-- Component A -->
<h1>Title A</h1>
<style>
h1 { color: red; } /* Only affects THIS h1 */
</style>
<!-- Component B -->
<h1>Title B</h1>
<style>
h1 { color: blue; } /* Only affects THIS h1 */
</style>

No conflicts. Astro adds data attributes behind the scenes to isolate selectors. You write simple CSS, Astro handles namespacing.

Global Styles

For site-wide styles (fonts, colors, resets), import a CSS file in a layout:

src/layouts/Base.astro
---
import '../styles/global.css'; // applies to every page
---

krowdev’s global.css contains:

  1. CSS custom properties (design tokens) — Catppuccin color values
  2. Reset — box-sizing, margins
  3. Typography — heading sizes, paragraph max-width, link styles
  4. Code blocks — syntax highlighting integration
  5. Tables — border, padding, hover states
  6. Interactive elements — callout boxes, challenge blocks (used in this course)

CSS Custom Properties (Design Tokens)

Custom properties are variables that CSS can reference. krowdev uses them for theming:

[data-theme='dark'] {
--bg: #1e1e2e; /* Catppuccin Mocha base */
--text: #cdd6f4; /* Catppuccin Mocha text */
--accent: #cba6f7; /* Catppuccin Mocha mauve */
}
[data-theme='light'] {
--bg: #eff1f5; /* Catppuccin Latte base */
--text: #4c4f69; /* Catppuccin Latte text */
--accent: #8839ef; /* Catppuccin Latte mauve */
}

Then everything references these variables:

body { background: var(--bg); color: var(--text); }
a { color: var(--accent); }
Analogy

CSS custom properties are like constants in a Python config file:

config.py
BG_COLOR = "#1e1e2e"
TEXT_COLOR = "#cdd6f4"
ACCENT_COLOR = "#cba6f7"
# usage.py
from config import BG_COLOR
set_background(BG_COLOR)

Change the config, everything updates. Same idea — change --accent and every link, button, and highlight changes.

How the Theme Toggle Works

The toggle script (in ThemeToggle.astro) does one thing:

// Toggle data-theme attribute on <html>
const next = current === 'dark' ? 'light' : 'dark';
document.documentElement.setAttribute('data-theme', next);
localStorage.setItem('theme', next);

The CSS selector [data-theme='dark'] or [data-theme='light'] activates the right set of variables. Everything repaints instantly — no page reload.

Key Insight

The theme toggle is the only JavaScript on the site. Everything else — fonts, colors, layout — is pure CSS. The is:inline script in Base.astro’s <head> sets the theme before first paint to prevent a flash of wrong colors.

Semantic Token Pattern

krowdev uses a two-layer token system:

Layer 1: Raw palette Layer 2: Semantic aliases
--ctp-base: #1e1e2e → --bg: var(--ctp-base)
--ctp-mauve: #cba6f7 → --accent: var(--ctp-mauve)
--ctp-blue: #89b4fa → --link: var(--ctp-blue)

Why two layers? If you later want --accent to be blue instead of mauve, you change one line. Everything using --accent updates. The raw palette stays stable.

Fonts

Astro 6’s Fonts API downloads fonts at build time and creates CSS variables:

astro.config.mjs
fonts: [
{
name: 'Inter',
cssVariable: '--font-body', // use this in CSS
provider: fontProviders.fontsource(),
weights: [400, 500, 600, 700],
},
]

Then in CSS:

html { font-family: var(--font-body), system-ui, sans-serif; }
code { font-family: var(--font-mono), monospace; }
Analogy

fontsource is like conda install for fonts. The files are downloaded at build time, bundled into your dist/, and served locally. No runtime dependency on Google’s CDN. GDPR-friendly.

Challenge: Change the accent color
  1. Open src/styles/global.css
  2. Find the line --accent: var(--ctp-mauve);
  3. Change it to --accent: var(--ctp-blue);
  4. Run npm run dev and see every accent (links, buttons, highlights, badges) turn blue
  5. Change it back to mauve when you’re done

This demonstrates the power of the token system — one variable controls the entire color story.

Sources

Diagram

Drag to pan · scroll or pinch to zoom · Esc to close