GlassNav

A bar of glass across the top of a page, clear over a hero and frosted once it has scrolled.

scroll the page to settle the glass

Paste into Claude Code, Cursor or any agent. Pinned to a tag, so it will not change under you.

Options

settleOver 120

0 to 600

Pixels of scroll over which the glass goes from clear to frosted. Roughly the height of whatever is behind it at the top of the page.

blur 14

0 to 40

Blur at full settle. Past about 20 it stops reading as glass and starts reading as fog, and it is the setting most likely to cost a user on an old machine their frame rate.

tint 0.55

0 to 1

How milky it goes once settled. This is the contrast control: glass over a photograph can put 2:1 text on a page without anybody noticing, and this is what stops it.

refract true

true · false

Bend the backdrop as well as blurring it. Chromium only. Everywhere else you get the blur and the edge, which is most of the effect, and nothing looks broken.

refraction 18

0 to 60

How far the rim bends what is behind it, in pixels. Past about 30 the bar stops looking like glass and starts looking like a heat haze.

What it needs

Category
Navigation, a component
Dependencies
react@>=18
Browser
No WebGL
Frame budget
~0.1 ms · 0 context
Pinned to
v0.12.0
  • The blur is backdrop-filter, which every current browser supports. The refraction is an SVG filter inside backdrop-filter, which only Chromium applies: Safari ignores it and Firefox parses the value, passes an @supports test and then renders nothing, so there is no feature query that tells the truth
  • What makes a panel read as glass rather than as tinted film is the hairline specular along its top edge, not the blur. Take that one line away and the rest is a grey rectangle
  • The lens is a signed distance field for the rounded rectangle, computed per pixel into a canvas and handed to feImage. The displacement is the field's gradient weighted towards the edge, which is a bevel rather than a uniform stretch
  • prefers-reduced-transparency turns the glass opaque and takes the specular with it, because a highlight on something that is not transparent is a lie about the material
  • forced-colors throws out every background and shadow, so the bar falls back to a border, which is the one thing the mode keeps
  • A nav landmark, a list, and links. The bar is markup rather than a widget, so the keyboard behaviour is the browser's
  • The current page is marked with aria-current='page', which is also what the underline styling keys off, so what is announced and what is drawn cannot drift
  • Contrast is the real risk. Glass over a photograph can put 2:1 text on the page without anybody noticing, which is why the tint comes up as the page scrolls under it rather than staying clear
  • Scroll is read on a rAF rather than on the event, and the settle value is rounded to two places before it is written, so a style recalculation only happens when something changed
  • The lens map is drawn once per resize at quarter scale, not per frame. It is a smooth field and feImage resamples it
  • backdrop-filter is not free: it forces the backdrop into its own layer. One bar on a page is the intended dose