FRONTIER/26

A field guide to the web platform · July 2026

THE WEB, unfenced. RUNNING LIVE.

This page is a working dossier of the platform’s newest powers — raymarched shaders, scroll-driven motion, wide-gamut color, morphing DOM. Nothing here is a video or an image. Everything is code, executing in your browser, right now.

WebGL2 · GLSL ES 3.00 Scroll-driven Animations OKLCH · Display-P3 View Transitions Container Queries @property
Scroll
CHAPTER 01

Light, computed per pixel.

The hero behind you is a raymarcher: a single GLSL fragment shader that defines a signed-distance field — a warped gyroid lattice — and marches a ray from a virtual camera through every pixel until it strikes the surface. Lighting, fresnel iridescence, and fog are all derived from the same math. No meshes, no textures, no libraries: one canvas, one webgl2 context, ~120 lines of shader. Below is a second live field — move your pointer through it. WebGL2 · GLSL ES 3.00

Field metaballs · SDF FPS Pointer idle
Move pointer / touch — click to pulse

What you’re looking at

Each pixel evaluates f(p) = Σ r²/|p−cᵢ|² for a set of orbiting centers, then thresholds the field to find a surface. The pointer becomes one of those centers, so your cursor literally bends the geometry. Color comes from a cosine palette — the same trick used in the hero.

Why it matters

WebGL2 is universal; navigator.gpu (WebGPU) is now rolling out across all three engines, bringing compute shaders to the open web. Your browser reports: checking… The shader idioms you see here — SDFs, palettes, domain warping — transfer 1:1 to WGSL.

Chapter 02 — The scrollbar is a timeline.

animation-timeline
02.1 / SCROLL()

This gallery has no JavaScript

Your vertical scroll is driving horizontal translation through animation-timeline: --h-scroll, a named view timeline on the tall wrapper. The mapping is declarative — the compositor runs it off the main thread, so it can’t jank.

02.2 / VIEW()

Elements that watch themselves enter

Every card on this page fades, rises and un-blurs via animation-timeline: view() with animation-range: entry 0% entry 55%. The bar below fills only while its own box crosses the viewport.

02.3 / PARALLAX

Depth from a single property

These dots share one keyframe, translate: 0 -Npx, over animation-range: entry 0% exit 100% — each with a different amplitude custom property. Old-school parallax, minus the scroll listeners.

02.4 / RANGE SYNTAX

Six named ranges, one grammar

entry, exit, cover, contain, entry-crossing, exit-crossing — percentages inside animation-range let you choreograph exactly which slice of an element’s journey drives which animation.

02.5 / THE PROGRESS BAR

Look up

The gradient hairline pinned to the top of the viewport is animation-timeline: scroll(root) — a reading-progress indicator in four lines of CSS. If your engine lacks scroll timelines, it politely disappears instead of breaking.

02.6 / STATUS

Where it stands, mid-2026

Scroll-driven animations shipped first in Chromium, landed in WebKit’s 2025 release train, and Firefox’s implementation is in active rollout. Progressive enhancement — like the fallbacks on this page — is the sensible pattern while engines converge.

Baseline · converging
CHAPTER 03

Color that thinks in lightness, not bytes.

OKLCH describes color the way you perceive it — lightness, chroma, hue — so a palette can be computed instead of hand-picked. This entire page is themed by one number: --hue, a registered @property. Every accent, gradient, glow and border derives from it live. Drag the slider and watch the whole site re-skin itself. OKLCH · color-mix · @property

285°

A tint/shade ladder computed with color-mix(in oklch, …) — seven steps from near-black to near-white, all from the same accent:

Twelve equidistant OKLCH hues at constant lightness and chroma — notice how even the perceived brightness is. That’s perceptual uniformity doing its job:

Left: the same gradient clamped to sRGB. Right: OKLCH chroma pushed into Display-P3 territory. On a wide-gamut screen the right panel is visibly more saturated — colors sRGB simply cannot express:

CHAPTER 04

One font file, infinite voices.

The display face on this page is Fraunces, a variable font with four live axes — weight, optical size, softness, and “wonk”. Instead of shipping a dozen static files, the browser interpolates between masters on the GPU. Drag the axes: the letterforms morph in real time, at full fidelity. font-variation-settings

Grumpy wizards
wght560
opsz144
SOFT100
WONK0

text-wrap, judged by a typographer

balance evens out line lengths for headings; pretty prevents short last lines (orphans). Tiny declarations, huge polish — applied throughout this page.

wrap: normal

Scroll-driven animations land in every engine worth watching this year

wrap: balance

Scroll-driven animations land in every engine worth watching this year

The drop cap, dignified

::first-letter has been around forever, but combined with variable axes and OKLCH accents it stops being a gimmick:

Typography on the web spent a decade as the slowest-moving part of the stack. Then variable fonts, font-palette color fonts, better line-breaking, and per-glyph control arrived in quick succession — and suddenly the most expressive type systems anywhere are the ones rendered by a browser engine.

CHAPTER 05

The DOM learned to morph.

State changes used to be instant cuts. The View Transitions API lets the browser snapshot the old and new frames and interpolate between them — below, the tab title cross-fades and slides with six lines of CSS and one document.startViewTransition() call. View Transitions · :has() · @container · anchors

View-transition tabs

Click a tab. The heading morphs; the panel cross-fades. Fallback: an ordinary instant swap.

The document era

HTML described pages. The browser’s job was typography, links, and forms — and it was brilliant at it.

:has() — the “parent selector”

Cards react to their own contents — no JS. Check the box or type an email: the borders, glows and state labels are pure CSS reading :has(:checked) and :has(:valid).

awaiting input
awaiting input

Container queries — drag the corner

The card below lives in a container-type: inline-size box you can resize. Its layout responds to its own width, not the viewport’s. Components finally own their breakpoints.

Drag right edge ↔
Intrinsic card

Layout follows container width: 2 → 3 columns, thumb grows, CTA appears.

Open

Little magics

A textarea that grows with its content (field-sizing: content), an accordion that animates to height: auto (interpolate-size + ::details-content), and a popover tethered by CSS anchor positioning.

How does the height animation work?
With interpolate-size: allow-keywords (set on :root here), the browser can tween between pixel heights and the auto keyword — the last unsolvable CSS transition.
And the anchor positioning?
The button declares anchor-name; the popover declares position-anchor and position-area: block-start. If it would overflow, position-try-fallbacks flips it below. No measuring, no JS.
I am positioned by pure CSS against my anchor — flip me by resizing the window.
CHAPTER 06

Your browser, audited live.

Every claim on this page is testable, so let’s test. The grid below runs real @supports and API probes against your engine, right now — green means the feature is active on this very page. CSS.supports · live probes

Probing…