Astro Styling
Scoped CSS, global styles, design tokens, and how Catppuccin theming works.
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.
| Level | Scope | Where | When to Use |
|---|---|---|---|
| Scoped | One component | <style> in .astro file | Component-specific styles |
| Global | Entire site | Imported .css file | Design tokens, typography, resets |
| Inline | One element | style="" attribute | Rare, 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:
---import '../styles/global.css'; // applies to every page---krowdev’s global.css contains:
- CSS custom properties (design tokens) — Catppuccin color values
- Reset — box-sizing, margins
- Typography — heading sizes, paragraph max-width, link styles
- Code blocks — syntax highlighting integration
- Tables — border, padding, hover states
- 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); }CSS custom properties are like constants in a Python config file:
BG_COLOR = "#1e1e2e"TEXT_COLOR = "#cdd6f4"ACCENT_COLOR = "#cba6f7"
# usage.pyfrom config import BG_COLORset_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.
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:
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; }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
- Open
src/styles/global.css - Find the line
--accent: var(--ctp-mauve); - Change it to
--accent: var(--ctp-blue); - Run
npm run devand see every accent (links, buttons, highlights, badges) turn blue - 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
- Astro Docs, Styles and CSS
- MDN, CSS custom properties
- Catppuccin, Palette spec