Lab

The typeface on this site has a width axis from 50% to 200% and a weight axis from 100 to 900. Here those two axes are a thermometer: cold letters contract and thin out, hot letters swell. Type something and warm it up.

Hello

The live material needs WebGL2 on real graphics hardware. The letters above still change temperature; they just do it with CSS.

Lab notes

A thermometer made of type

Science Gothic is a variable font: one file that contains every width from 50% to 200% and every weight from 100 to 900. The site draws a single line through that space and calls it temperature. At the frozen end the letters are condensed and thin; at the molten end they are wide and heavy. Cold things contract and hot things expand, so this is roughly what a typeface would do if it obeyed physics.

The name uses the whole line. Everything else on the site sits somewhere on it too: this page’s headings are room temperature, “Things run hot.” is set hot, “Say hello.” is set cool.

50%100%150%200% 500900 width weight frozen molten
The temperature line through Science Gothic’s design space, and the nine temperatures its outlines are sampled at.

Every point has its own temperature

At build time a script opens the font and samples every letter’s outline at nine temperatures along that line. Variable fonts guarantee the outlines are point-compatible, so the same point can be followed from frozen to molten. Nine samples keep the in-between shapes within 1% of the em of what the font itself would draw (worst case: 17 units out of 2,000).

When the engine runs, each outline point is placed at the temperature of the heat field underneath it. A letter can be half frozen and half molten, and it swells where your hand is. The outlines are filled on the GPU with a stencil winding count, antialiased with 4× MSAA, then shaded as ice or lava from the same field that shaped them.

The letter “a”, drawn from the site’s own glyph data at all nine sampled temperatures, frozen (blue) to molten (orange).

The heat

The heat is a coarse grid, one cell every 14 CSS pixels, simulated on the CPU because it is tiny: a few thousand cells. Each frame it is carried along a slow curling flow (hot cells rise), then diffused, then pulled back toward the temperature of the room. Those are two separate passes, because the one-pass version was not stable and blew up in the prototype.

Your pointer (when the live version runs) carries the opposite temperature of the room: in Ice mode it melts, in Lava mode it freezes. Letters heat up fast and cool down slowly, which is most of why it feels like a material and not an animation. When the live version runs, “Show the heat” above draws the raw field and every outline point.

Seven hundred and forty thousand points

The crystal on the home page draws one point for each member of the communities I run: a 100 × 100 × 74 lattice. There are no vertex buffers. Each point works out where it lives from its own index, so 740,000 points cost almost no memory. Heat shakes points out of their lattice sites; cold puts them back.

When the crystal is live, the buttons beside it act out what each tool does. Protator’s raid freezes at the surface, staggered over 120 ms because that is how fast Protator generates a CAPTCHA. If a device can’t hold 740,000 points at its refresh rate, it gets fewer, and the caption says so.

Fast first, then spectacular

Everything you read is plain HTML with the CSS inlined, and the name is real text in a 10 KB font file that is requested before anything else. That text is the page’s largest paint, and it is finished before any script runs. The WebGL engine loads afterwards, when the browser is idle, and only for scenes near the screen. It compiles its shaders in the background, measures its own frame rate and lowers its resolution until it holds your display’s refresh rate. It stops completely when nothing is visible.

Nothing loads for it if you asked your browser to save data, or if WebGL2 is missing or only emulated in software. You get the same page, set in the same type, still. If you asked for reduced motion, it draws one frame and stops.

Measured performance of the production build
MeasureTargetMeasured
Performance score≥ 95100
Accessibility, best practices, SEO100 each100 each
Largest Contentful Paint< 1.5 s1.1 s
Cumulative Layout Shift< 0.050
Interaction to Next Paint< 100 ms64 ms
Home page, first load—16 requests, 211 KB
Home page, production build. Lighthouse mobile with its default throttling (slow 4G, 4× slower CPU); INP is the slowest scripted tap under the same CPU throttling.

For everyone

All text meets WCAG AA contrast in both modes. Every control is a real button or link with a visible focus ring, and the canvases are decoration with text alternatives. With reduced motion the material freezes into a still frame, and mode changes and reveals happen instantly. Without JavaScript the site still reads completely; only the contact details stay locked, because they are decoded on request to keep scrapers out.

Credits