CSS Architecture
Building a Color System with oklch
How we moved from HSL to oklch for perceptually uniform palettes across light and dark themes.
· 8 min read
Blog index pages built from semantic <article> elements, composition primitives, and utility
classes. Typography and whitespace carry the design -- no cards, no grids. These variants suit a minimal tech blog;
community and editorial variants are separate patterns.
Core: .flow, .cluster, .switcher, .divider
A few custom styles are included in the page style block used by some of the patterns.
<style>
.article-category {
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--color-primary-text);
font-size: var(--step--2);
font-weight: var(--font-weight-medium);
}
.article-date-col {
flex-basis: 4.5rem;
flex-shrink: 0;
text-align: center;
}
</style>Whitespace alone separates entries. Category label provides the single accent color touch. Titles, excerpt, and meta in a tight internal flow.
CSS Architecture
How we moved from HSL to oklch for perceptually uniform palettes across light and dark themes.
· 8 min read
Tooling
A year in, the constraints that initially felt limiting turned out to be the best part.
· 5 min read
Performance
Using clamp() and custom properties for a type system that adapts to any viewport.
· 6 min read
API Design
The two-tier naming convention that finally stuck after three failed attempts.
· 10 min read
<docs-resize>
<div class="flow flow-space-xl" style="max-inline-size: 40rem">
<article>
<div class="flow flow-space-2xs">
<p class="article-category">CSS Architecture</p>
<h2 class="text-2 text-semibold leading-heading">
<a href="#" class="link-plain">Building a Color System with oklch</a>
</h2>
<p class="text-muted" style="max-inline-size: 45ch">
How we moved from HSL to oklch for perceptually uniform palettes across light and dark themes.
</p>
<p class="text--1 text-subtle">
<time datetime="2026-03-15">Mar 15, 2026</time> · 8 min read
</p>
</div>
</article>
<article>
<div class="flow flow-space-2xs">
<p class="article-category">Tooling</p>
<h2 class="text-2 text-semibold leading-heading">
<a href="#" class="link-plain">Why We Chose esbuild and Stayed</a>
</h2>
<p class="text-muted" style="max-inline-size: 45ch">
A year in, the constraints that initially felt limiting turned out to be the best part.
</p>
<p class="text--1 text-subtle">
<time datetime="2026-02-28">Feb 28, 2026</time> · 5 min read
</p>
</div>
</article>
<article>
<div class="flow flow-space-2xs">
<p class="article-category">Performance</p>
<h2 class="text-2 text-semibold leading-heading">
<a href="#" class="link-plain">Fluid Type Scales Without a Preprocessor</a>
</h2>
<p class="text-muted" style="max-inline-size: 45ch">
Using clamp() and custom properties for a type system that adapts to any viewport.
</p>
<p class="text--1 text-subtle">
<time datetime="2026-02-10">Feb 10, 2026</time> · 6 min read
</p>
</div>
</article>
<article>
<div class="flow flow-space-2xs">
<p class="article-category">API Design</p>
<h2 class="text-2 text-semibold leading-heading">
<a href="#" class="link-plain">Naming Things in a Design Token System</a>
</h2>
<p class="text-muted" style="max-inline-size: 45ch">
The two-tier naming convention that finally stuck after three failed attempts.
</p>
<p class="text--1 text-subtle">
<time datetime="2026-01-22">Jan 22, 2026</time> · 10 min read
</p>
</div>
</article>
</div>
</docs-resize>The first article gets more typographic scale. A divider separates it from the compact entries that follow.
CSS Architecture
How we moved from HSL to oklch for perceptually uniform color palettes across light and dark themes. The migration touched every component and forced us to rethink how we name colors.
· 8 min read
<docs-resize>
<div class="flow flow-space-xl" style="max-inline-size: 40rem">
<article>
<div class="flow flow-space-xs">
<p class="article-category">CSS Architecture</p>
<h2 class="text-3 text-semibold leading-heading">
<a href="#" class="link-plain">Building a Color System with oklch</a>
</h2>
<p style="max-inline-size: 50ch">
How we moved from HSL to oklch for perceptually uniform color palettes across light and dark themes.
The migration touched every component and forced us to rethink how we name colors.
</p>
<p class="text--1 text-subtle">
<time datetime="2026-03-15">Mar 15, 2026</time> · 8 min read
</p>
</div>
</article>
<hr class="divider"/>
<article>
<div class="flow flow-space-2xs">
<p class="article-category">Tooling</p>
<h2 class="text-1 text-semibold leading-heading">
<a href="#" class="link-plain">Why We Chose esbuild and Stayed</a>
</h2>
<p class="text--1 text-subtle">
<time datetime="2026-02-28">Feb 28, 2026</time> · 5 min read
</p>
</div>
</article>
<article>
<div class="flow flow-space-2xs">
<p class="article-category">Performance</p>
<h2 class="text-1 text-semibold leading-heading">
<a href="#" class="link-plain">Fluid Type Scales Without a Preprocessor</a>
</h2>
<p class="text--1 text-subtle">
<time datetime="2026-02-10">Feb 10, 2026</time> · 6 min read
</p>
</div>
</article>
<article>
<div class="flow flow-space-2xs">
<p class="article-category">API Design</p>
<h2 class="text-1 text-semibold leading-heading">
<a href="#" class="link-plain">Naming Things in a Design Token System</a>
</h2>
<p class="text--1 text-subtle">
<time datetime="2026-01-22">Jan 22, 2026</time> · 10 min read
</p>
</div>
</article>
</div>
</docs-resize>A stacked date column gives a scannable chronological rhythm. The switcher stacks the layout on narrow containers.
Mar
15
2026
CSS Architecture
How we moved from HSL to oklch for perceptually uniform palettes across light and dark themes.
8 min read
Feb
28
2026
Tooling
A year in, the constraints that initially felt limiting turned out to be the best part.
5 min read
Feb
10
2026
Performance
Using clamp() and custom properties for a type system that adapts to any viewport.
6 min read
Jan
22
2026
API Design
The two-tier naming convention that finally stuck after three failed attempts.
10 min read
<docs-resize>
<div class="flow flow-space-l" style="max-inline-size: 40rem">
<article>
<div class="switcher" style="--switcher-threshold: 20rem; --switcher-align: flex-start; --switcher-gap: var(--space-sm)">
<div class="article-date-col">
<p class="text--2 text-subtle text-uppercase">Mar</p>
<p class="text-3 text-semibold leading-tight">15</p>
<p class="text--1 text-subtle">2026</p>
</div>
<div class="flow flow-space-2xs">
<p class="article-category">CSS Architecture</p>
<h2 class="text-2 text-semibold leading-heading">
<a href="#" class="link-plain">Building a Color System with oklch</a>
</h2>
<p class="text-muted" style="max-inline-size: 45ch">
How we moved from HSL to oklch for perceptually uniform palettes across light and dark themes.
</p>
<p class="text--1 text-subtle">8 min read</p>
</div>
</div>
</article>
<hr class="divider"/>
<article>
<div class="switcher" style="--switcher-threshold: 20rem; --switcher-align: flex-start; --switcher-gap: var(--space-sm)">
<div class="article-date-col">
<p class="text--2 text-subtle text-uppercase">Feb</p>
<p class="text-3 text-semibold leading-tight">28</p>
<p class="text--1 text-subtle">2026</p>
</div>
<div class="flow flow-space-2xs">
<p class="article-category">Tooling</p>
<h2 class="text-2 text-semibold leading-heading">
<a href="#" class="link-plain">Why We Chose esbuild and Stayed</a>
</h2>
<p class="text-muted" style="max-inline-size: 45ch">
A year in, the constraints that initially felt limiting turned out to be the best part.
</p>
<p class="text--1 text-subtle">5 min read</p>
</div>
</div>
</article>
<hr class="divider"/>
<article>
<div class="switcher" style="--switcher-threshold: 20rem; --switcher-align: flex-start; --switcher-gap: var(--space-sm)">
<div class="article-date-col">
<p class="text--2 text-subtle text-uppercase">Feb</p>
<p class="text-3 text-semibold leading-tight">10</p>
<p class="text--1 text-subtle">2026</p>
</div>
<div class="flow flow-space-2xs">
<p class="article-category">Performance</p>
<h2 class="text-2 text-semibold leading-heading">
<a href="#" class="link-plain">Fluid Type Scales Without a Preprocessor</a>
</h2>
<p class="text-muted" style="max-inline-size: 45ch">
Using clamp() and custom properties for a type system that adapts to any viewport.
</p>
<p class="text--1 text-subtle">6 min read</p>
</div>
</div>
</article>
<hr class="divider"/>
<article>
<div class="switcher" style="--switcher-threshold: 20rem; --switcher-align: flex-start; --switcher-gap: var(--space-sm)">
<div class="article-date-col">
<p class="text--2 text-subtle text-uppercase">Jan</p>
<p class="text-3 text-semibold leading-tight">22</p>
<p class="text--1 text-subtle">2026</p>
</div>
<div class="flow flow-space-2xs">
<p class="article-category">API Design</p>
<h2 class="text-2 text-semibold leading-heading">
<a href="#" class="link-plain">Naming Things in a Design Token System</a>
</h2>
<p class="text-muted" style="max-inline-size: 45ch">
The two-tier naming convention that finally stuck after three failed attempts.
</p>
<p class="text--1 text-subtle">10 min read</p>
</div>
</div>
</article>
</div>
</docs-resize><article> elements so each entry is a landmark for assistive technology<h2> -- adjust to match the heading level in your page context<time> with datetime for machine-readable dates