jackosborne.com

Pattern Library

The foundations, elements and interface patterns used across this site. This page is generated from the same tokens and components as the rest of the site, so it evolves with the work.

Foundations

Semantic tokens keep the visual hierarchy consistent across light and dark appearances.

Color

Interface colors describe purpose rather than a fixed appearance.

Color appearance
  • --color-canvas
  • --color-ink
  • --color-ink-muted
  • --color-stage
  • --color-stage-hover
  • --color-image-surface
  • --color-callout-bg
  • --color-focus

Typography

The system stack carries the interface; mono is reserved for numbers, tokens and compact metadata.

Hero · H1

Clear thinking, carefully made.

Section · H2

A major section

Supporting · H3

A supporting idea

Body

Body copy supports sustained reading with a restrained size, comfortable measure and generous line height.

Utility · H5
2025–Present · Brooklyn, New York
Mono · .mono

01 — 2025–Present

Spacing

An 8px foundation scales from compact controls to broad composition.

  1. 8
  2. 16
  3. 24
  4. 32
  5. 48
  6. 72
  7. 96

Grid

Twenty-four implementation tracks resolve into four conceptual rails.

01–06 07–12 13–18 19–24

Editorial content typically occupies tracks 07–18.

grid-column: 1 / 25

Full grid

grid-column: 7 / 19

Editorial rail

grid-column: 4 / 16

Left push

grid-column: 10 / 22

Right push

CSS
.full-grid { grid-column: 1 / 25; }
.editorial-rail { grid-column: 7 / 19; }
.push-left { grid-column: 4 / 16; }
.push-right { grid-column: 10 / 22; }

Shape

Radius communicates object type: restrained for utility, generous for project stages.

12px · Small
24px · Mobile card
32px · Card
999px · Pill
CSS
.utility { border-radius: var(--radius-small); }
.mobile-card { border-radius: var(--radius-card-mobile); }
.card { border-radius: var(--radius-card); }
.pill { border-radius: var(--radius-pill); }

Elements

Native HTML carries the hierarchy before components add any behavior.

Prose

Good interface writing is direct, useful and human. It explains enough to create confidence without competing with the work.

An inline link remains visibly identifiable, while strong text provides semantic emphasis rather than decoration.

Design systems are most useful when they capture decisions, not merely inventory.
HTML
<p>Good interface writing is direct and useful.</p>
<blockquote>Design systems capture decisions.</blockquote>

Lists

Use unordered lists for related items and ordered lists when sequence matters.

Unordered
  • Prefer semantic HTML.
  • Reuse established patterns.
  • Keep the work visually primary.
Ordered
  1. Frame the problem.
  2. Test the important assumption.
  3. Refine the outcome.
HTML
<ul>
  <li>Prefer semantic HTML.</li>
  <li>Reuse established patterns.</li>
</ul>

<ol>
  <li>Frame the problem.</li>
  <li>Test the assumption.</li>
</ol>

Data table

RoleTokenUse
Body--font-size-baseDescriptions and details
Utility--font-size-smLabels and metadata
Divider--color-dividerQuiet structural separation
Stage--color-stageImage and component surfaces
Focus--color-focusKeyboard focus indication
HTML
<div class="breakout">
  <table class="data-table">
    <thead>
      <tr><th>Role</th><th>Token</th><th>Use</th></tr>
    </thead>
    <tbody>
      <tr><td>Body</td><td>--font-size-base</td><td>Descriptions</td></tr>
    </tbody>
  </table>
</div>

Media

Figures can follow the editorial rail or use the grid-width breakout, with captions kept close to their image. CSS controls the displayed dimensions; the responsive-image helper supplies suitable source files for that layout.

Jack Osborne on Edinburgh's Royal Mile
Editorial figure Contained by the reading column.
Jack Osborne on Edinburgh's Royal Mile
Breakout figure Expands into the surrounding grid.
Nunjucks
<figure class="img">
  <div class="bg">
    {% responsiveImage
      "/_/images/about/profile/featured.png",
      "Jack Osborne on Edinburgh's Royal Mile",
      "(min-width: 1140px) min(34vw, 494px), (min-width: 1024px) calc(100vw - 192px), calc(100vw - 64px)",
      "about"
    %}
  </div>
  <figcaption>
    Figure title
    <span>Supporting context.</span>
  </figcaption>
</figure>

<div class="breakout">
  <figure class="img">
    <!-- Use a sizes value that describes the wider layout. -->
    …
  </figure>
</div>

Components

Small, composable patterns support the content without becoming a visual system of their own.

Page introduction

Eyebrow, title and optional description form one compact hierarchy.

Selected work

Saved Places

A focused explanation gives the page enough context without delaying the work.

HTML
<header class="page-intro grid">
  <div class="page-intro__inner row-start-7 row-end-19">
    <p class="page-intro__eyebrow">Selected work</p>
    <h1>Saved Places</h1>
    <p class="page-intro__description">A focused explanation gives the page enough context.</p>
  </div>
</header>

Disclosure

Supporting context remains available without competing with the primary narrative.

Nunjucks
{% call accordion("project-context", "Context") %}
  <ul>
    <li><span class="heading">Role:</span> Product design</li>
    <li><span class="heading">Year:</span> 2026</li>
  </ul>
{% endcall %}

Callout

A short contextual notice uses warmth sparingly.

This is supporting information, not the main event.
HTML
<div class="callout" role="note">
  <svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true">…</svg>
  <div class="callout__text">
    This is supporting information, not the main event.
  </div>
</div>

Project stage

Imagery sits on a neutral gallery-like surface with generous inset space.

Project stage composition
HTML
<div class="work-card__stage single-phone">…</div>
<div class="work-card__stage wide-browser">…</div>
<div class="work-card__stage split-stage">…</div>

Accessibility

Interaction states, native semantics and user preferences are part of the component contract.

Interaction states

Every interactive control should communicate availability, history and keyboard focus without relying on motion alone.

CSS
a:link {
  color: var(--color-link);
  text-decoration-color: var(--color-ink);
}

a:visited {
  color: var(--color-link-visited);
  text-decoration-color: var(--color-link-visited);
}
a:hover,
a:focus { color: var(--color-link-hover); }

a:focus-visible,
button:focus-visible,
summary:focus-visible {
  outline: var(--focus-ring-width) solid var(--color-focus);
  outline-offset: var(--focus-ring-offset);
}

:is(button, input, textarea, select):disabled {
  cursor: not-allowed;
  opacity: 0.45;
}

Keyboard operation

These native controls work without custom keyboard scripting. Use Tab to move through them, then Enter or Space to activate the focused control.

Focusable link
Native disclosure

Disclosure content remains available to keyboard and assistive-technology users.

HTML
<a href="/about/">Focusable link</a>
<button type="button">Native button</button>
<details>
  <summary>Native disclosure</summary>
  <p>Disclosure content.</p>
</details>

Reduced motion

The site follows the operating-system preference and removes non-essential animation and transition duration globally.

Your current preference: Checking…

CSS
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0s !important;
    scroll-behavior: auto !important;
  }
}