Change the Look in One File
Color, spacing, and type for the whole theme live in one tokens file. Edit it, refresh, done.
If you want a different look for your site, start in one file:
src/styles/tokens.css
The core colors, spacing steps, and type scale live there. Components and pages read those variables first, while specialized surfaces such as code highlighting keep a small local palette. Change the core variables and most of the site follows.
Change the accent color#
Find --color-blue near the top. There are three copies:
- Light mode under
:root - Dark mode inside the
prefers-color-scheme: darkmedia query - Forced dark via
[data-theme='dark']
Edit all three. The starter uses the same variable name across modes so components do not need to know which mode they are in.
Scroll dark turns on here#
This sample post has the optional scroll dark effect enabled. Keep scrolling through this color example and the page will switch to dark mode. Add or remove focusEffect: 'scroll-dark' in a post’s frontmatter to turn it on or off for that post; the trigger point is theme-defined, not section-specific.
:root { --color-blue: #197ca8; /* light mode */}
[data-theme='dark'] { --color-blue: #74c7dc; /* dark mode */}Rule of thumb: a darker shade for light mode (passes contrast on white) and a lighter shade for dark mode (passes contrast on near-black). The starter’s pair is a good starting point; push the hue without changing that contrast relationship.
Change spacing#
The scale uses a 4-point grid:
--space-1: 0.25rem; /* 4pt */--space-2: 0.5rem;--space-3: 0.75rem;--space-4: 1rem;--space-6: 1.5rem;--space-8: 2rem;Components reference var(--space-4), not raw 1rem. Doubling --space-4 would double every “one unit” gap across the site, which is rarely what you want. Instead, change one or two specific steps.
Common edits:
- Tighter prose: lower
--space-6and--space-8. - Roomier headings: raise
--space-10and--space-12.
Change the type scale#
Astro Tone follows a quiet type scale at 16px base:
--text-large-title: 2.125rem; /* page hero */--text-title-1: 1.75rem; /* featured */--text-title-2: 1.375rem; /* section heading */--text-headline: 1.0625rem; /* list titles */--text-body: 1.0625rem; /* body */--text-callout: 1rem; /* descriptions */--text-footnote: 0.8125rem; /* dates, captions */For a more compact theme, scale every step down by ~10%:
--text-large-title: 1.875rem;--text-title-1: 1.5rem;--text-title-2: 1.25rem;Post title sizes use clamp() directly in src/styles/layouts/blog-post.css. Edit there if you want a different scaling curve at wide widths.
Verify in dark mode#
Click the theme toggle in the header. Every text and surface color should still pass contrast.
Three places to check:
- Custom shadows. Light-mode shadows use
rgba(0, 0, 0, …). Dark-mode shadows need to be stronger, or near-black, to be visible at all. - Hard-coded colors. Grep the codebase for
#andrgb(outsidetokens.css,src/config/expressive-code.ts, andsrc/styles/code.css. The code block palette is intentionally separate; everything else should usually read from tokens. - Images. Photos that read on white can disappear on near-black. Use a subtle separator or a tinted background for prose images if needed.
Replace the font stack#
The starter uses a system font stack by default. That keeps the first render fast and avoids bundling font license surface into the template.
To add a brand font:
- Drop your
.woff2file intosrc/assets/fonts/. - Add an
@font-faceblock near the top oftokens.css. - Put the font family first in
--font-sans. - Add a preload in
src/components/BaseHead.astroonly if the font is critical to the first viewport.
If the new font is variable, keep font-weight: 100 900 or the range it supports. If it is static, list only the weights you actually use.
When a token is not enough#
Sometimes a single component needs a value the system does not have. Two options:
- Local CSS variable. Define
--feed-date-columninside the component’s scoped style block. The PostFeed already does this for its layout columns. - New token. If more than one component would use it, add a new token to
tokens.cssand use it everywhere.
Prefer local variables for one-off layout values. Prefer new tokens for anything that touches color, spacing, type, or motion.
What does not belong in tokens#
The token file is for visual primitives. It is not for:
- Copy strings — those live in
src/ui.tsandastro-theme-config.ts. - Route paths.
- Feature flags.
If a value answers “what does this look like?”, it is a token. If it answers “what does this say?” or “where does it go?”, it is config.