Astro design system reference

Astro + vanilla CSSLiving referenceUpdated July 22, 2026

Overview

This page documents the design system implemented across the site. The CSS custom properties, components, and layout patterns shown here are the source of truth; the page renders and explains what is already in production.

It is intended as a personal reference and may later be shared with interviewers or hiring managers as a portfolio artifact.

Open the component lab

The component lab provides an interactive environment for developing and testing components in isolation, with live previews and accessibility testing.

Design Principles

Performance firstStatic output, minimal JavaScript, no global bundles for page-specific features.
Minimal JavaScriptPrefer Astro, HTML, and CSS before adding client-side behavior.
Semantic HTMLNative elements before ARIA; correct heading order; one h1 per page.
AccessibilityKeyboard, visible focus, contrast, reduced motion, and touch targets.
Fluid responsive designclamp() tokens for type and spacing; mobile-first breakpoints.
Content-first layoutReadable measure, generous whitespace, clear visual hierarchy.

Typography

Headings use var(--font-headers); body copy usesvar(--font-copy); monospace elements usevar(--font-mono).

Visual scale

Heading 1
Heading 2
Heading 3
Heading 4
Heading 5
Body text with a sample link and inline code.
Small text for meta, captions, and labels.

Token usage

TokenMobileDesktopLine height
--type-size-h132 px64 px--line-height-h1
--type-size-h226 px45 px--line-height-h2
--type-size-h322 px32 px--line-height-h3
--type-size-h418 px24 px--line-height-h4
--type-size-h516 px19 px--line-height-h5
--type-size-large18 px22 px--line-height-body
--type-size-body16 px18 px--line-height-body
--type-size-small13 px15 px--line-height-body

Content samples

Blockquotes use a left border and slightly larger text. This is how a pull quote or emphasized statement appears.
/* Example token usage */
.card {
  padding: var(--space-component);
  background: var(--color-card-bg);
  border-radius: var(--radius-lg);
}

Color Tokens

The default theme is dark. A light theme is applied via[data-theme="light"] or system preference.

Core palette

--bg-mainPage backgroundDark: #0b1020 / Light: #f8fafc
--bg-surfaceCards, header, code blocksDark: #111a2e / Light: #ffffff
--bg-surface-elevatedElevated surfaces, hover statesDark: #18243a / Light: #e8eef7
--text-primaryHeadings, primary textDark: #f8fafc / Light: #0f172a
--text-secondaryBody text, descriptionsDark: #cbd5e1 / Light: #334155
--text-mutedMeta, captions, labelsDark: #94a3b8 / Light: #475569
--brand-primaryLinks, actions, focusDark: #5ea8ff / Light: #005fcc
--brand-accentLink hover, success statesDark: #38d9a9 / Light: #007a5a
--brand-highlightHighlights, marksDark: #ffb86b / Light: #a14b00
--border-mainCard borders, dividersDark: #26344d / Light: #cbd5e1
--border-mutedHeader border, subtle separatorsDark: #1a2638 / Light: #e2e8f0
--border-controlForm input bordersDark: #52627a / Light: #64748b

Semantic roles

TokenUsageSource
--color-linkDefault links--brand-primary
--color-link-hoverHovered links--brand-accent
--color-actionButtons, CTAs--brand-primary
--color-action-hoverButton hover#3d8ee0
--color-focusFocus outlines--color-link
--color-successSuccess states--brand-accent
--color-card-bgCard backgrounds--bg-surface
--color-card-bg-elevatedElevated card backgrounds--bg-surface-elevated
--color-card-borderCard borders--border-main

Spacing Scale

Spacing is derived from the fluid rhythm token var(--rhythm)(≈ 26 px on mobile, ≈ 33 px on desktop).

--space-xscalc(var(--rhythm) * 0.5)13 px → 17 px
--space-smcalc(var(--rhythm) * 0.75)20 px → 25 px
--space-mdvar(--rhythm)26 px → 33 px
--space-lgcalc(var(--rhythm) * 1.5)40 px → 50 px
--space-xlcalc(var(--rhythm) * 2)53 px → 66 px
--space-sectioncalc(var(--rhythm) * 2.5)66 px → 83 px
--space-layoutcalc(var(--rhythm) * 3)79 px → 99 px

Layout Rails

Reading width and page width are intentionally separate. Prose stays narrow for readability, while pages and wide components can use more viewport space.

.rail--prose68ch — readable measure
.rail--page72rem — default page max
.rail--wide80rem — wide layouts

Components

Navigation

src/components/HeaderLink.astro

src/styles/components.css

← Back to portfolio

PaginationNav

src/components/PaginationNav.astro

Content

Card

src/components/Card.astro

Designing with tokens

How CSS custom properties shape typography, spacing, color, and layout across the site.

Eric Carlisle2 min read

AstroCSSAccessibility

Tag / Chip

src/styles/components.css

Astrostatic chip

TagFilterBar

src/components/TagFilterBar.astro

Callout

src/styles/components.css

Callout title — highlighted information or notes.

Interaction

Integrations

ShareStrip

src/components/ShareStrip.astro

Search UI

src/pages/search.astro, src/styles/pagefind.css

Pagefind injects its markup at runtime; the site restyles it with project tokens. The internals are not rebuilt here.

Contact form fields

src/pages/contact.astro

Content Patterns

Article intro

A large lede paragraph uses var(--type-size-large) to set up an article or section.

Metadata row

Eric Carlisle3 min read

Tag list

AstroCSSAccessibility

Accessibility Notes

  • Skip link — keyboard users can jump to main content.
  • Focus states — visible dashed outline with offset.
  • Touch targets — minimum 44px for buttons and icon links.
  • Color contrast — palettes are chosen for both dark and light modes.
  • Semantic HTML — native elements before ARIA.
  • Reduced motion — transitions and animations respect user preference.

Known Gaps & Follow-ups

ItemNote
Header heightMeasured at runtime by JavaScript; the CSS fallback is 4.5rem.
Pagefind search UIThird-party markup restyled by src/styles/pagefind.css.
Portfolio case-study gridPage-local 1.6fr / 0.8fr sizing in src/pages/portfolio.astro.
Homepage role textOne-off letter-spacing on the homepage hero role; not tokenized.
Page-specific animationsScroll-driven header behavior and card entrance motion are scoped to specific pages.

Implementation Notes

  • This page widens the default content rail to--layout-rail-wide while keeping prose paragraphs at the readable --layout-rail-prose measure.
  • --header-height is measured and set by JavaScript; the CSS fallback is 4.5rem.
  • Pagefind search UI is third-party markup restyled bysrc/styles/pagefind.css.
  • Some page-specific styles use local sizing not yet captured by shared tokens.
  • This page is intentionally omitted from the main navigation and usesnoindex, follow metadata.