glass-lens
One SVG feDisplacementMap, a generated lens map, and the unit system every
browser actually understands. No canvas, no clones, no WebGL, no flags — the glass bends the
page's own pixels, so text stays selectable and links stay clickable straight through the lens.
Everything under the lens is real, rendered DOM. Try drag-selecting this paragraph through the distortion, or clicking this link. The effect samples nothing from behind a pane — the content's own pixels are the ones moving.
No pointer required. Here the lens is a static glass pill sized to one segment of a segmented control; selecting a tab glides it across the control's own pixels — the same pattern native iOS uses. Cross-browser, and every tab stays clickable straight through the glass.
A real-world layout: a bar fixed to the top of a scrolling page, with the content sliding
behind it picking up the glass. Scroll inside the frame — the bar refracts whatever passes under
it, live. Cross-browser, no backdrop-filter. (One caveat below on how this scales.)
Scroll this panel. The glass bar above stays put while the article travels underneath it, refracting through the lens as it goes.
Auroras form when charged particles from the sun collide with gases high in the atmosphere. Greens come from oxygen near 100 km; reds from oxygen much higher up; blues and violets from nitrogen.
The band of best viewing sits roughly between 65° and 72° magnetic latitude — a ring over northern Canada, Iceland, Norway, and Siberia.
Activity tracks the eleven-year solar cycle. Near the peak, displays push to lower latitudes and turn brighter and more frequent.
The Kp index runs 0–9. A Kp of 5 or more means a geomagnetic storm and a real chance of color overhead far from the poles.
A tripod and a multi-second exposure pull out color the eye can barely register. Start near f/2.8, ISO 1600, 10 seconds, and adjust from there.
Keep scrolling — the refraction tracks every line of this text as it slides under the bar, because the glass is bending the page's own pixels.
The bar isn't sampling a blurred backdrop. It's the same SVG displacement filter from the demos above, pinned to the top of this scroll container and refreshed as you scroll.
Scales fine for a contained panel like this. For a full, heavy page, see the note in the README — putting an SVG filter on a large scroll container forces the browser to re-rasterize its content, so a production glass nav is better done with a small fixed strip.
The lens map is a small PNG generated on a canvas: its red channel encodes horizontal
displacement, green encodes vertical, and 128 means "don't move." An SVG filter loads it with
feImage, composites it over neutral gray, and hands it to
feDisplacementMap, which bends the element's own rendered pixels. A final mask
sandwich — punch a lens-shaped hole in the original, lay the displaced result over it — keeps
the effect confined to the lens with an invisible seam.
The cross-browser trick is a single attribute: every geometric value in the filter is
expressed in objectBoundingBox fractions. WebKit cannot resolve
userSpaceOnUse pixel geometry for filter primitives applied to HTML elements —
feImage and primitive subregions silently fail — but in bounding-box fractions the entire
primitive set works. Two more details keep the result identical across browsers: the map image
is fully decoded before the filter attaches, and the filter gets a fresh ID on every update, so
no browser serves stale cached filter output.
Moving the lens is nearly free. The map never regenerates on movement — only the fractional subregions of three primitives shift. The map is rebuilt only when the lens changes shape, and even then only one quadrant is computed; the rest is mirrored.