GlassNav
A bar of glass across the top of a page, clear over a hero and frosted once it has scrolled.
Options
-
settleOver120 -
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.
-
blur14 -
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.
-
tint0.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.
-
refracttrue -
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.
-
refraction18 -
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