Design System

Plain CSS design system for principles.design. No preprocessors, no build tools — CSS custom properties and modern CSS only.

Live Documentation

The design system page at /design-system/ uses Jekyll includes to render component previews. This keeps the documentation in sync with the actual components automatically — when a component changes, the preview updates too.

Components support a preview parameter to disable interactive elements:

{% include footer.html preview=true %}

When preview=true:

  • Form inputs and buttons are disabled
  • Form submission is prevented
  • Required validation is skipped

Architecture

_includes/css/
  tokens.css              Design tokens (colors, scale, spacing)
  reset.css               Modern CSS reset
  typography.css          Typographic scale and vertical rhythm
  layout.css              Grid system and content areas
  components/
    navigation.css        Site navigation and active states
    tile.css              Example cards and grid/list views
    forms.css             Search, subscribe, filters
    footer.css            Site footer and credits
    misc.css              Links, sorting, menus, decorations
    docs.css              Design system documentation page
  utilities.css           Spacing, visibility, accessibility helpers

assets/css/
  site.css                Jekyll-processed entry point (concatenates all includes)

Design Tokens

Colors

Token Value Usage
--color-primary #f7d708 Yellow — brand, highlights, CTAs
--color-primary-light #fdf7ce Light yellow — subtle backgrounds
--color-secondary #0015dd Blue — hover states, accents
--color-text #333 Body text, headings, borders
--color-text-muted #666 Secondary text
--color-text-subtle #999 Tertiary text, captions
--color-border #e6e6e6 Borders, dividers
--color-surface #fff Page background
--color-surface-alt #f5f5f5 Alternate backgrounds
--color-surface-dark #2c2c2c Dark footer background
--color-text-light #f0f0f0 Off-white text on dark backgrounds
--color-success #388E3C Success states, confirmations
--color-error #d32f2f Error states, warnings

Typography

Font: Inter (variable, self-hosted) - Live on production

Font stack: 'Inter', system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif

Font file: Inter-Variable.woff2 (291KB) - Full character set with variable weight support

Root size: 19px

Scale (rem):

Token Size Computed Usage
--step-0 1rem 19px Body text, h4
--step-1 1.3158rem 25px Large body text
--step-2 1.6316rem 31px h3 (desktop), h2 (mobile)
--step-3 2.6316rem 50px h2 (desktop), h1 (mobile)
--step-4 4.2105rem 80px h1 (desktop)

The scale steps down one level on mobile (below 920px). For example, h2 uses --step-2 on mobile and --step-3 on desktop.

Vertical Rhythm

All vertical spacing is based on a single baseline unit:

--baseline: 1.5263rem (29px)

This is one line of body text (19px × 1.5263). All margins, padding, and spacing should be whole multiples of this unit.

Spacing scale

Token Multiple Computed
--space-4xs 0.125× ~3.6px
--space-3xs 0.25× ~7.3px
--space-2xs 0.375× ~10.9px
--space-xs 0.5× ~14.5px
--space-s 0.75× ~21.7px
--space-m 29px
--space-l 1.5× ~43.4px
--space-xl 58px
--space-2xl 87px
--space-3xl 116px

Transitions

Token Value Usage
--transition-fast 0.2s ease-in-out Hover states, micro-interactions
--transition-slow 0.3s ease-in-out Background changes, larger state changes

Rule: Heading margins always snap to whole baseline units. Body text (p, ul, ol) has margin-bottom: var(--baseline).

Heading rhythm

Element Mobile Desktop
h1 1 baseline top, 1 bottom 1 baseline top, 2 bottom
h2 1 baseline top, 0 bottom 1 baseline top, 1 bottom
h3 1 baseline top, 0 bottom 1 baseline top, 0 bottom
h4 1 baseline top, 0 bottom 1 baseline top, 0 bottom

Measure

Body text has a maximum width of 40rem (~65–75 characters) for optimal readability.

Layout

12-column CSS grid with a maximum width of 1080px and 85% viewport width.

Breakpoints

Name Value Usage
Small 400px Minor mobile adjustments
Medium 700px Two-column layouts, form changes
Large 920px Typography scale steps up, three-column tiles
Extra large 1100px Navigation switches to horizontal bar

Grid classes

Class Span (mobile) Span (desktop)
.full 12 12
.two-up 12 6
.two-thirds 12 8
.three-up 6 3
.info-block 12 8
aside 12 4

Utilities

Class Effect
.mtn margin-top: 0
.mbn margin-bottom: 0
.mbm margin-bottom: 0.6rem
.pbn padding-bottom: 0
.lhs line-height: 1.4
.bold font-weight: bold
.tdn text-decoration: none
.sr-only Visually hidden, accessible to screen readers

Usage

Adding a new component

  1. Create a new file in _includes/css/components/
  2. Add {% include css/components/yourfile.css %} to both assets/css/site.css and _includes/css.html
  3. Use tokens for all values — never hardcode colors, spacing, or font sizes

CSS loading strategy

CSS source files live in _includes/css/ so Jekyll’s {% include %} tag can find them. Loading is handled in _includes/css.html and switches automatically based on environment:

Development (default)

bundle exec jekyll serve
# or
./scripts/dev.sh
  • jekyll.environment defaults to "development"
  • Loads assets/css/site.css via a <link> tag
  • site.css is a Jekyll-processed file (has front matter) that concatenates all CSS via {% include %}
  • Supports live reload — edit a CSS file, Jekyll rebuilds automatically
  • Single HTTP request — one concatenated file

Production (GitHub Pages)

  • GitHub Pages sets JEKYLL_ENV=production automatically
  • _includes/css.html uses {% include %} to concatenate all CSS files into a single inline <style> block
  • Zero HTTP requests for CSS — everything is embedded in the HTML
  • No render-blocking external stylesheets

Testing production mode locally

JEKYLL_ENV=production bundle exec jekyll serve

Adding a new CSS file

When you add a new CSS file, it must be registered in two places:

  1. assets/css/site.css — add a {% include css/components/yourfile.css %} line (for development)
  2. _includes/css.html — add a {% include css/components/yourfile.css %} line inside the <style> block (for production)

Current file load order

tokens.css              → Design tokens (custom properties)
reset.css               → Modern CSS reset
typography.css          → Typographic scale and vertical rhythm
layout.css              → Grid system and content areas
components/navigation.css
components/tile.css
components/forms.css
components/footer.css
components/misc.css
components/docs.css
utilities.css           → Spacing, visibility helpers (loaded last to ensure overrides)

Order matters: tokens must load first (other files reference them), utilities must load last (they need to override component styles).

Live documentation

The design system is documented at /design-system/ — a Jekyll page that renders all tokens, typography specimens, spacing scales, and component examples using the actual CSS. This page stays in sync automatically because it uses the same tokens and classes as the rest of the site.

Source: _pages/design-system.html CSS: _includes/css/components/docs.css

Migration notes

This system replaces the previous Ruby Sass setup (_sass/ directory). The _sass/ directory is retained as reference but is no longer compiled or used. The Sass config has been removed from _config.yml.