Writing

All thoughts on
craft & code.

Essays on motion, frontend performance, and the 1% details that make interfaces feel premium.

30 articles
<canvas />
gsap.to(...)
gl.drawArrays(...)
MotionSep 3, 20261 min read

Form Micro-Interactions: Where Motion Earns Its Keep

Forms are where users are most anxious and most honest. Validation timing, the shake that means no, and success states that reward completion.

PerformanceSep 2, 20261 min read

The Third-Party Script Diet: Your Site Is Slow Because of Other People

Analytics, chat widgets, pixels — the median site ships more third-party code than its own. An audit ritual, a facade pattern, and a worker to exile the rest.

DesignSep 1, 20261 min read

Designing Empty States: The First Screen Users Ever See

Every user meets your product empty before they meet it full. Turning blank screens from dead ends into starting lines — guidance, gradients of emptiness, and tone.

<canvas />
gsap.to(...)
gl.drawArrays(...)
FrontendAug 31, 20261 min read

The dialog Element: Modals You Stop Maintaining

Focus traps, backdrop, Escape handling, inert background — the modal checklist the platform now does for you. showModal(), ::backdrop, and closedby.

MotionAug 30, 20261 min read

A Real prefers-reduced-motion Strategy (Not Just Turning Things Off)

Reduced motion is not no motion. Which animations to keep, which to swap for crossfades, and how to build it as a system instead of an apology.

PerformanceAug 29, 20261 min read

Compositor-Only Animations: The 60fps Contract

transform and opacity animate on a separate thread and cannot jank — everything else can. The rendering pipeline, will-change etiquette, and cheap ways to fake the expensive.

<canvas />
gsap.to(...)
gl.drawArrays(...)
DesignAug 28, 20261 min read

Border Radius Consistency: The Detail That Exposes Rushed UI

Mismatched corner radii are the typo of visual design. Nested radius math, a sane token scale, and why concentric corners feel right.

FrontendAug 27, 20261 min read

CSS Anchor Positioning: Tooltips That Position Themselves

Pin any element to any other element, with automatic flipping when space runs out — the layout problem that kept Popper.js alive, now solved in CSS.

MotionAug 26, 20261 min read

Hover Choreography: Interfaces That Acknowledge You

A good hover state is a conversation: the cursor asks, the element answers, its siblings step back. Group hovers, focus parity, and timing that feels intentional.

<canvas />
gsap.to(...)
gl.drawArrays(...)
PerformanceAug 25, 20261 min read

Image Formats in 2026: AVIF First, and Fewer Bytes Than You Think

AVIF is universally supported and half the size of JPEG at equal quality. The modern image stack: format, sizing, priority, and the three attributes that matter.

DesignAug 24, 20261 min read

Whitespace Is Hierarchy: The Cheapest Design Tool You Have

Before color, weight, or size, spacing tells readers what belongs together. Proximity ratios, spacing scales, and why cramped interfaces feel cheap.

FrontendAug 23, 20261 min read

@property: Typed CSS Variables That Actually Animate

Custom properties are strings — which is why animating them snaps instead of tweening. @property gives them types, and suddenly gradients, angles, and numbers interpolate.

<canvas />
gsap.to(...)
gl.drawArrays(...)
MotionAug 22, 20261 min read

Scroll Snap: Storytelling in Full-Screen Chapters

Scroll snapping turns a page into chapters — carousels, onboarding flows, full-bleed stories — with pure CSS. And the discipline to know when not to.

PerformanceAug 21, 20261 min read

Font Loading Without the Flash: A 2026 Strategy

FOUT, FOIT, and layout shift are all self-inflicted. Preload, font-display, and size-adjust fallbacks make web fonts effectively invisible to loading.

DesignAug 20, 20261 min read

Dark Mode Done Properly: It Is Not a Filter

Inverting colors is not designing a dark theme. Elevation flips from shadows to lightness, saturation must drop, and pure black is a mistake. The real checklist.

<canvas />
gsap.to(...)
gl.drawArrays(...)
FrontendAug 19, 20261 min read

CSS Subgrid: The Alignment Problem Grid Could Not Solve Alone

Cards in a row with misaligned titles, prices, and buttons — the oldest grid frustration. Subgrid lets children align to their grandparent tracks. Solved.

MotionAug 18, 20261 min read

Staggered Reveals: Choreography, Not Decoration

Twelve cards fading in at once reads as one blob. Stagger them 40ms apart and the eye follows a story. The rules of good stagger timing, in CSS.

PerformanceAug 17, 20261 min read

Speculation Rules: Instant Navigation by Betting on the Next Click

The browser can now prerender the next page before the user clicks — entire navigations in 0ms. The Speculation Rules API, and how to bet without wasting bandwidth.

<canvas />
gsap.to(...)
gl.drawArrays(...)
DesignAug 16, 20261 min read

OKLCH: The Color Space Your Design System Should Have

HSL lies: 50% lightness in yellow and blue are wildly different brightnesses. OKLCH makes lightness honest — and makes generated palettes finally look designed.

FrontendAug 15, 20261 min read

The Popover API: Tooltips and Menus Without the Library

Light dismiss, top-layer stacking, focus handling — everything you imported Floating UI for is now two HTML attributes. The Popover API in practice.

MotionAug 14, 20261 min read

FLIP: The Technique Behind Every Smooth Layout Animation

You cannot animate layout without jank — unless you invert it. FLIP turns expensive layout changes into cheap transforms, and it powers every smooth reorder you have seen.

<canvas />
gsap.to(...)
gl.drawArrays(...)
PerformanceAug 13, 20261 min read

content-visibility: The Biggest Rendering Win Nobody Ships

One CSS property that tells the browser to skip rendering offscreen sections entirely — often halving initial render time on long pages. Here is how to use it…

DesignAug 12, 20261 min read

Fluid Type Scales: Stop Breakpointing Your Typography

Font sizes that jump at breakpoints are a relic. clamp() plus viewport units give typography that glides between devices — one line per text style.

FrontendAug 11, 20261 min read

Container Queries: Components That Own Their Responsiveness

Media queries ask how big the window is. Container queries ask how big MY box is — the question components actually needed. Sidebars stop breaking cards forever.

<canvas />
gsap.to(...)
gl.drawArrays(...)
MotionAug 10, 20261 min read

linear() Easing: Real Springs in Pure CSS

cubic-bezier can only draw one hump — no bounce, no overshoot-and-settle. The linear() function ends that limit and brings true spring physics to CSS.

PerformanceAug 9, 20261 min read

INP: The Metric That Finally Measures How Your Site Feels

Interaction to Next Paint punishes what users actually hate: taps that do nothing. Here is where INP debt hides and the patterns that pay it down.

FrontendAug 8, 20261 min read

CSS :has() — The Parent Selector Changes How You Architect Styles

For twenty years CSS could only look down the tree. :has() looks up, sideways, and forward — killing a whole class of state-tracking JavaScript.

<canvas />
gsap.to(...)
gl.drawArrays(...)
DesignAug 7, 20261 min read

Optical Alignment: When the Math Is Wrong

Perfectly centered is often visibly off. Why play icons, quotation marks, and rounded shapes need optical correction — and how to train your eye to see it.

FrontendAug 6, 20262 min read

The View Transitions API: App-Like Navigation Without a SPA

The View Transitions API brings native-app page morphs to plain multi-page sites. Two lines of CSS, no router, no framework — here is how to ship it today.

Got a project in mind? Let's build it.

Or just want to talk shop about motion and frontend craft — say hello.

Start a conversation