Style Guide

Single-page visual overview of every Grant.is design token, component, shortcode, and layout element. A complete reference for typography, spacing, and colors.

Dev controls ⇧ H

Display

Layout

Auto-shuffles every 30s; tap to reshuffle.

Export & Presets


Overview

Ordered from tokens → primitives → patterns → stress tests. Every block is live production markup.

Use the controls above to toggle theme, shuffle the playground, seed/preset layouts, copy tokens, or show the baseline grid.

Layout Playground

Shuffle/preset/seed playground used by the layout controls to verify dense grid behaviors.

Hero
CTA
Gallery row
Quote
Card
Stat
Article preview
Meta
Form

Shuffle or apply presets to see grid density changes; seed locks deterministic order.

Color Tokens

All colors are WCAG 2.2 AA+ compliant with tested contrast ratios.

Primary Palette

--color-primary-50
--color-primary-100
--color-primary-150
--color-primary-200
--color-primary-250
--color-primary-300
--color-primary-350
--color-primary-400
--color-primary-450
--color-primary-500
--color-primary-550
--color-primary-600
--color-primary-650
--color-primary-700
--color-primary-750
--color-primary-800
--color-primary-850
--color-primary-900
--color-primary-950

Secondary Palette

--color-secondary-50
--color-secondary-100
--color-secondary-150
--color-secondary-200
--color-secondary-250
--color-secondary-300
--color-secondary-350
--color-secondary-400
--color-secondary-450
--color-secondary-500
--color-secondary-550
--color-secondary-600
--color-secondary-650
--color-secondary-700
--color-secondary-750
--color-secondary-800
--color-secondary-850
--color-secondary-900
--color-secondary-950

Semantic Colors

--color-success WCAG AA compliant
--color-warning WCAG AA compliant
--color-error WCAG AA compliant
--color-info WCAG AA compliant

Neutral Colors

--color-white
--color-black
--color-gray-50
--color-gray-100
--color-gray-200
--color-gray-300
--color-gray-400
--color-gray-500
--color-gray-600
--color-gray-700
--color-gray-800
--color-gray-900

Text Colors

Aa
--color-text-primary
Aa
--color-text-secondary
Aa
--color-text-muted
Aa
--color-text-inverse

Link Colors

--color-link
--color-link-hover
--color-link-visited

Background Colors

--color-bg-primary
--color-bg-secondary
--color-bg-tertiary

Border Colors

--color-border
--color-border-hover
--color-border-focus

Typography

Fluid typography using clamp() for responsive scaling.

Camera specs example: f/1.2 → f/11 to demonstrate glyph replacements.

Font Families

Sans Serif: The quick brown fox jumps over the lazy dog

--font-sans

Serif: The quick brown fox jumps over the lazy dog

--font-serif

Monospace: The quick brown fox jumps over the lazy dog

--font-mono

Type Scale

XS

--text-xs

SM

--text-sm

BASE

--text-base

LG

--text-lg

XL

--text-xl

2XL

--text-2xl

3XL

--text-3xl

4XL

--text-4xl

5XL

--text-5xl

Font Weights

Thin

--font-thin

Light

--font-light

Normal

--font-normal

Medium

--font-medium

Semibold

--font-semibold

Bold

--font-bold

Extrabold

--font-extrabold

Black

--font-black

Line Heights

None: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

--leading-none

Tight: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

--leading-tight

Snug: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

--leading-snug

Normal: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

--leading-normal

Relaxed: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

--leading-relaxed

Loose: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

--leading-loose

Heading Examples

Heading 1: The quick brown fox

Heading 2: The quick brown fox

Heading 3: The quick brown fox

Heading 4: The quick brown fox

Heading 5: The quick brown fox
Heading 6: The quick brown fox

Spacing Scale

Consistent spacing scale based on rem units.

Base Scale

--space-0
--space-0-5
--space-1
--space-1-5
--space-2
--space-2-5
--space-3
--space-3-5
--space-4
--space-5
--space-6
--space-7
--space-8
--space-9
--space-10
--space-12
--space-16
--space-20
--space-24
--space-32
--space-40
--space-48
--space-64
--space-80
--space-96

Semantic Spacing

--space-xs
--space-sm
--space-md
--space-lg
--space-xl
--space-2xl
--space-3xl
--space-4xl
--space-5xl

Semantic Scales

Swappable mathematical progressions for sizing, radius, and duration. Apply .scale-fib or .scale-phi to any container to change the underlying values.

Size Progression Comparison

The same semantic tokens (--size-xs--size-xl) resolve to different values based on the active progression. Now supporting 8 mathematical progressions:

Linear

Predictable: 8, 12, 16, 24, 32px

xs
sm
md
lg
xl
2xl

Fibonacci

Natural: 8, 13, 21, 34, 55px

xs
sm
md
lg
xl
2xl

Golden Ratio (φ)

Dramatic: 6, 10, 16, 26, 42px

xs
sm
md
lg
xl
2xl

Modular (1.25×)

Major third: 10, 12, 16, 20, 25px

xs
sm
md
lg
xl
2xl

Perfect Fourth (1.333×)

Musical: 9, 12, 16, 21, 28px

xs
sm
md
lg
xl
2xl

Augmented Fourth (1.414×)

Tritone: 8, 11, 16, 22, 32px

xs
sm
md
lg
xl
2xl

Minor Second (1.067×)

Subtle: 14, 15, 16, 17, 18px

xs
sm
md
lg
xl
2xl

Major Second (1.125×)

Gentle: 13, 14, 16, 18, 20px

xs
sm
md
lg
xl
2xl

Radius Progression

Linear

xs
sm
md
lg
xl
2xl

Fibonacci

xs
sm
md
lg
xl
2xl

Golden Ratio (φ)

xs
sm
md
lg
xl
2xl

Modular (1.25×)

xs
sm
md
lg
xl
2xl

Perfect Fourth (1.333×)

xs
sm
md
lg
xl
2xl

Augmented Fourth (1.414×)

xs
sm
md
lg
xl
2xl

Minor Second (1.067×)

xs
sm
md
lg
xl
2xl

Major Second (1.125×)

xs
sm
md
lg
xl
2xl

Usage

/* Default: linear progression */
.card { padding: var(--size-md); border-radius: var(--radius-lg); }

/* Switch entire site to Fibonacci */
html { @extend .scale-fib; }
/* Or: */
<html class="scale-fib">

/* Switch a single component */
.hero.scale-phi { /* φ-based sizing within hero only */ }

/* Data attribute alternative */
<div data-scale="fib">...</div>

Usage

/* Default: linear progression */
          Visited
          Portfolio · visited
        
Default Link
Hover Link
Focus Link
Visited Link
<a href="#">Regular link</a>
<a href="#" class="visited-link">Visited link</a>
<a href="#" class="external-link">External link</a>
<a href="#" class="demo-hover">Hover me</a>
<a href="#" class="demo-focus">Focus me with Tab key</a>

Icon Tokens

arrow-right
arrow-left
arrow-up
arrow-down
plus
minus
check
close
play
pause
stop
rewind
fast-forward
refresh
repeat
shuffle
search
heart
star
sun
moon
cloud
calendar
clock
bell
camera
image
video
mic
volume
mute
chat
mail
phone
map-pin
location
navigation
tag
bookmark
link
external
lock
unlock
settings
filter
sliders
list
grid
home
user
users
upload
download
share
rss
github
twitter
instagram
linkedin
youtube
dribbble
behance
slack
zap
<span class="icon-token icon-token--copy">copy</span>

Code Blocks

Inline code: const example = "code";

// Block code
function example() {
  console.log("Hello, World!");
  return true;
}

Blockquote

This is a blockquote. It can contain multiple paragraphs and represents quoted text from another source.

— Author Name

Lists

Unordered List

  • First item
  • Second item
  • Third item
    • Nested item 1
    • Nested item 2

Ordered List

  1. First item
  2. Second item
  3. Third item
    1. Nested item 1
    2. Nested item 2

Callouts & Shortcodes

Important note banner for high-signal announcements.
“Design is how it works — every element here is from the actual site styles.”
— Grant

How do we keep this site fast?


A: Plain HTML, hand-rolled CSS tokens, and zero frameworks.


Expandable / collapse pattern

Use for interview footnotes, gear lists, or any optional context. Works with <details> or the collapse shortcode.

<div class="importantNote">Important note banner</div>
<figure class="quote">...</figure>
<div class="qa">...</div>
<details>
  <summary>Expandable / collapse pattern</summary>
  <p>Hidden content</p>
</details>

Actions & Inputs

Buttons and form controls with live state grid.

Buttons

Solid · default
Solid · hover
Solid · focus
Solid · active
Ghost · default
Ghost · hover
Ghost · focus
Ghost · active
<button class="btn">Default Button</button>
<button class="btn btn-primary">Primary Button</button>
<button class="btn" disabled>Disabled Button</button>

Form Controls

Input · default
Input · hover
Input · focus
Input · error Error: please fix
Select · default
Select · focus
Checkbox · default
Checkbox · focus

Identity & Media

Avatars, enhanced images, and gallery treatments.

Avatars & Profile Treatments

Profile small
Profile medium
Gradient ring avatar
Experimental hover avatar

Tokens

--avatar-size-sm · --avatar-size-md · --avatar-size-lg
--avatar-ring-width · --avatar-ring-color · --avatar-ring-exp
Stacked avatar 1
Stacked avatar 2

Stack spacing offsets + ring swap for mixed identities.

<div class="avatar avatar--lg avatar--interactive">
  <img src="/images/profile.jpg" alt="Profile"/>
</div>
<div class="avatar-stack">...</div>

Media & Galleries

Enhanced image demo
Enhanced markdown image with EXIF overlay + lightbox trigger.
<figure class="enhanced-markdown-image">...</figure>
<section class="photo-grid" data-gallery>
  <figure class="gallery-card">
    <img data-gallery-image data-src="/images/profile.jpg" src="/images/profile.jpg" alt="Portrait" />
  </figure>
</section>

Data & Layout

Tables and cards for structured content.

Tables

Header 1Header 2Header 3
Row 1, Col 1Row 1, Col 2Row 1, Col 3
Row 2, Col 1Row 2, Col 2Row 2, Col 3
Row 3, Col 1Row 3, Col 2Row 3, Col 3

Scrollable table (narrow view)

FeatureStatusNotesExtra
Long headingOKWraps to next line when narrowExtra cell
Second rowPendingDemonstrates horizontal scrollMore text to force width

Stacked (mobile-first) table

LabelValueMeta
Alpha123Wraps to test stacking
Beta456More details here

Article Cards

Portrait cover

Standard Post Entry

Card used on lists / archives. Auto line-clamps and supports covers.

Oct 15, 2025 · 4 min read

Featured / First Entry

First card variant with larger type for the most recent story.

Draft state preview
<article class="post-entry">
  <div class="entry-cover"><img src="/images/profile.jpg" alt="" /></div>
  <header class="entry-header"><h2>Title</h2></header>
  <section class="entry-content"><p>Summary...</p></section>
  <footer class="entry-footer">Meta text</footer>
</article>

Meta & CTAs

Reading progress, share rail, and subscribe CTA.

Reading progress 68%
<div class="post-progress" style="--progress: 68%">...</div>
<div class="post-utilities-grid">
  <section class="post-utilities post-utilities__share">...</section>
  <section class="post-utilities post-utilities__subscribe">...</section>
</div>

Utilities & Overlays

Window chrome, overflow handling, and debug hooks.

Virtual Window & Quicklook

Static window demo

Use helper window.grantIs.openQuicklookNearest() to quicklook the nearest image. Drag the titlebar to move and resize from the corner grip.

<div class="ui-window ui-window--embed">
  <div class="ui-window__titlebar">
    <button class="ui-window__control" aria-label="Close">✕</button>
    <div class="ui-window__title">Static window demo</div>
  </div>
  <div class="ui-window__body">...</div>
</div>

Overflow & Wrap

Horizontal overflow sample

https://example.com/this/is/a/very/long/path/that/should/overflow/and/show/custom/scrollbar/indicators

Long word wrap

AntidisestablishmentarianismSupercalifragilisticexpialidociousHipopotomonstrosesquipedaliophobia

Margin Annotations

Side labels for paragraphs, figures, and Q/A blocks — matching live article behavior.

This paragraph shows the default counter in the right gutter.

The next paragraph increments the counter automatically.

Camera on tripod
Figure labels use <figure> + <figcaption>.

How do Q/A labels render?

A: They use the shared counter and align in the gutter.

.post-content {
  position: relative;
  padding-inline-end: var(--space-12);
}
.post-content > p::before { counter-increment: section; content: counter(section); }
.post-content > figure::before { counter-increment: image; content: 'fig. ' counter(image); }
.qa-question::before { counter-increment: q; content: 'Q' counter(q); }
  • Add right padding to leave room for gutter labels.
  • Use figure/figcaption for media; labels only attach to media.
  • Reset counters per block when needed: counter-reset: section q a image;
  • Avoid clipping parents (no overflow: hidden) so labels stay visible.

Debug & Test Controls

Utility buttons to exercise global helpers: quicklook, layout shuffle, baseline grid, toast.

// Programmatic helpers
window.grantIs.openQuicklookNearest?.();
window.dispatchEvent(new CustomEvent('notify', { detail: 'Hello!' }));

Accessibility

WCAG 2.1 AA compliant design system.

Contrast Ratios

Text on White Background

Primary text: 12.63:1 (AAA)

Secondary text: 7.04:1 (AAA)

Muted text: 4.69:1 (AA)

Semantic Colors

Success: 4.54:1 (AA)

Warning: 4.52:1 (AA)

Error: 5.74:1 (AA)

Info: 4.58:1 (AA)

Focus States

Focus me with Tab key

Screen Reader Support

  • All images have descriptive alt text
  • Landmark regions properly labeled (header, main, footer)
  • Skip to main content link available
  • Semantic HTML elements used throughout
  • ARIA labels provided where needed

Reduced Motion

All animations respect prefers-reduced-motion media query:

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

Usage Guidelines

CSS Architecture

This design system uses CSS Cascade Layers for predictable specificity:

@layer foundation, base, layout, components, utilities, overrides;
  • foundation - Design tokens, resets, and normalization
  • base - Base HTML element styles
  • layout - Page structure and grid systems
  • components - Reusable UI components
  • utilities - Helper classes
  • overrides - Final overrides (use sparingly)

Token Usage

Always use design tokens instead of hard-coded values:

Good

.element {
  color: var(--color-text-primary);
  padding: var(--space-4);
  font-size: var(--text-lg);
}

Bad

.element {
  color: #111827;
  padding: 1rem;
  font-size: 1.125rem;
}

Responsive Design

Typography uses fluid scaling with clamp(), but use breakpoints for layout:

/* Mobile-first approach */
.container {
  padding: var(--space-4);
}

@media (min-width: 768px) {
  .container {
    padding: var(--space-8);
  }
}

@media (min-width: 1024px) {
  .container {
    padding: var(--space-12);
  }
}

Live Stress Tests

Full-fat markdown blocks that intentionally mix nesting, RTL, code fences, and form density to catch regressions.

Live content sandbox

These are the raw markdown blocks we keep at the bottom of the page to stress the system. The curated demos above show the canonical components; this sandbox mixes them together to catch regressions.

What’s covered here

  • Shortcodes and mixed media in a single flow
  • Stress tests: deep nesting, long links, long code lines, RTL text
  • Dense form layout used for copy/paste QA
  • Oversized tables and code fence zoo

Stress Test: Typography & Lists

Paragraph with inline code const slug = "this-should-wrap-properly"; and a very long unbroken URL to check overflow: https://example.com/this/is/a/very/long/path/that/should/wrap/without/pushing/the/layout/off/the/screen/when/viewed/on/small/viewports.

  1. Ordered list level 1
    1. Level 2 item with bold and italic
      1. Level 3 item with inline-code and a link.
        • Mixed bullet under an ordered list to test stacking.

Blockquote with bold, a link to Grant.is, and enough text to wrap across multiple lines to catch spacing regressions.

Table & Definition List

ColumnDescriptionNotes
shortNormal length cellok
wideThis cell is intentionally very very very very very very very long to force wrapping and check table overflow without horizontal scrolling.wrap please
Term
Definition body with a second sentence to verify spacing.

Code fences (long lines)

// Long line should wrap within the content width without forcing horizontal scrollbars.
const megaLine = 'abcdefghijklmnopqrstuvwxyz0123456789'.repeat(6);
function renderHeavyNesting(node = { a: { b: { c: { d: { e: 'end' } } } } }) {
  return JSON.stringify(node);
}

<div class="nested"><span>Inline HTML preview</span></div>

Media & Shortcodes

Note / Collapse / QA / Quote

Important note banner for regression checks.

Expandable details (should animate without layout shift)Hidden content reveals here. It must not change surrounding spacing when toggled.

How do we keep this site fast?


Plain HTML, hand-rolled CSS tokens, zero frameworks, and aggressive caches.


Design is how it works — keep the styleguide honest.

— Grant 🔗

Images (odd sizes)

Landscape sample Square sample

Forms & Inputs

This dense form exists for regression/stress; the canonical states live in “Actions & Inputs” above.


Stress Test: Deep Nesting & RTL

  • Level 1
    • Level 2 with code and bold
      • Level 3 with long link
        • Level 4 with 🍣🍜🍕 emojis
هذا مقطع عربي قصير لاختبار دعم الاتجاه من اليمين إلى اليسار داخل نفس الفقرة مع نص إنجليزي مجاور.

Overflow & Wrapping

Unbroken string: supercalifragilisticexpialidocioussupercalifragilisticexpialidocioussupercalifragilisticexpialidocious (should wrap or break without blowing layout).

# very long command
tar -cvzf backup-$(date +%Y-%m-%d-%H-%M-%S).tar.gz /var/www/example-site --exclude=node_modules --exclude=.git --warning=no-file-changed --blocking-factor=256

Huge Table

Col 1Col 2Col 3Col 4Col 5Col 6Col 7Col 8
12345678
A very long cell that should wrap gracefully without forcing horizontal scrollβγδεζηθ
Row threewithmixeddataandemojis 🚀✨🔥pluslinks Grant
Final rowshortshortshortshortshortshortshort

Code Fence Zoo

def deeply_nested(a):
    return {"a": {"b": {"c": {"d": {"e": a}}}}}

print(deeply_nested("fin")))
{ "bad": "json", "trailing": "comma" }