SVG Liquid Glass Refraction for HTML Elements – Hyalite.js

Category: Animation , Javascript | September 10, 2026
AuthorVII-Cae
Last UpdateSeptember 10, 2026
LicenseMIT
Views0 views
SVG Liquid Glass Refraction for HTML Elements – Hyalite.js

Hyalite is a Vanilla JavaScript library that creates real refractive Liquid Glass effects on rounded HTML elements.

It bends the backdrop near the edges while the center stays clear, with controls for bevel width, glass thickness, blur, chromatic dispersion, and rim lighting.

The effect uses SVG filters through backdrop-filter and does not require WebGL.

Full refraction currently runs in Chromium browsers, while Safari and Firefox keep the CSS fallback.

Features

  • Per-corner circular radius handling with CSS overlap rules.
  • Automatic map rebuilding after element size changes.
  • Dynamic attachment and cleanup through container watchers.
  • Multiple watchers on one page.
  • Optional refraction ramps when elements appear.
  • Settled or throttled live rebuilding during resize.
  • Shared lens maps for near-identical element sizes.
  • Motion ramps that respect prefers-reduced-motion.

How To Use It

Basic Usage

Load hyalite.js in the page:

<script src="hyalite.js"></script>

Hyalite writes --hyalite on each attached element. Use the property only on that element because CSS custom properties inherit, and a descendant that reads it would receive a filter built for its parent.

.glass-card {
  backdrop-filter: var(--hyalite, blur(6px));
  -webkit-backdrop-filter: var(--hyalite, blur(6px));
  background: rgba(20, 24, 32, 0.14);
  border-radius: 24px;
  padding: 24px;
}
<div class="glass-card" id="profile-card">
  <h3>Profile</h3>
  <p>Content inside the refractive glass panel.</p>
</div>

Attach Hyalite after the element enters the document:

const card = document.getElementById('profile-card');
Hyalite.attach(card, {
  bevel: 20,
  thickness: 10,
  blur: 3
});

Watch Dynamic Glass Elements

Hyalite.watch() manages matching elements inside a container. It attaches existing matches, new matches, and elements that later gain the matching class.

const glassWatcher = Hyalite.watch(
  document.getElementById('app'),
  '.glass-card',
  {
    bevel: 16,
    thickness: 10,
    blur: 3
  }
);

Stop that watcher when automatic management is no longer needed:

glassWatcher.stop();

Update All Attached Elements

Use Hyalite.setOpts() to change options across attached elements and update watcher settings for future matches.

await Hyalite.setOpts({
  blur: 1,
  dispersion: 0.08,
  rim: 0.6
});

Refresh After a Border Radius Change

ResizeObserver reacts to element dimension changes. A border-radius change that leaves the element dimensions unchanged requires Hyalite.refresh().

card.style.borderRadius = '40px';
Hyalite.refresh(card);

Materialize the Refraction

Set materialize to a duration in milliseconds to ramp displacement and rim lighting from zero when an element is attached.

Hyalite.attach(card, {
  bevel: 24,
  thickness: 12,
  blur: 2,
  materialize: 220
});

Self Filtering

Set self: true when the SVG filter should process the element itself rather than its backdrop.

.filtered-element {
  filter: var(--hyalite, none);
}
Hyalite.attach(
  document.querySelector('.filtered-element'),
  {
    self: true,
    bevel: 16,
    thickness: 10
  }
);

Configuration Options

  • bevel (number, default 16, range 1 to 400): Width of the refracted edge zone in pixels. Element geometry and the largest corner radius can reduce the effective value.
  • thickness (number, default 10, range 0 to 400): Simulated glass thickness in pixels. Larger values increase backdrop displacement near the edge.
  • blur (number, default 3, range 0 to 64): Center frost blur in pixels.
  • dispersion (number, default 0.05, range 0 to 0.5): Chromatic aberration intensity. 0 uses one outer displacement pass.
  • rim (number, default 0.45, range 0 to 4): Edge-light intensity. 0 disables the rim light.
  • light (number, default -145, range -180 to 180): Rim-light direction in degrees. 0 points from above, and positive values rotate clockwise.
  • smooth (number, default 1, range 0 to 4): Blur between the two displacement passes in pixels. It applies only inside the bevel ring. 0 uses one displacement pass.
  • materialize (number, default 0, range 0 to 10000): Attachment ramp duration in milliseconds for displacement and rim lighting.
  • settle (number, default 120, range 0 to 10000): Required size stability in milliseconds before rebuilding a lens map. 0 switches to throttled live rebuilding.
  • self (boolean, default false): Filters the element itself through filter: var(--hyalite) and uses displacement only.
  • onBuild(info) (function): Runs after a new lens map is built. Recreating a filter from a cached map does not call it.

API Methods

APIDescription
Hyalite.watch(container, selector, opts)Attaches matching elements now and as the container changes. Returns an object with stop(), which stops the watcher and detaches its managed elements.
Hyalite.unwatch()Stops every watcher and detaches watcher-managed elements. Manual attachments survive.
Hyalite.attach(el, opts)Manually attaches Hyalite to one element.
Hyalite.detach(el)Detaches an element and removes its --hyalite property.
Hyalite.refresh(el)Rebuilds the filter against the element’s current geometry.
Hyalite.setOpts(opts)Changes options across attached elements and returns a Promise. A newer call supersedes an unfinished earlier call.
Hyalite.info()Returns information from the most recent lens-map build, or null before any map has been built.
Hyalite.supported()Returns the current SVG backdrop-filter compatibility verdict.
Hyalite.force(true | false | null)Overrides browser detection. null returns to automatic detection and the method returns the resulting verdict.
Hyalite.DEFAULTSContains the default option values.
Hyalite.versionContains the current library version string.

`Hyalite.info()` Return Value

FieldTypeDescription
maxDisplacementnumberMaximum displacement represented by the outer lens map.
bevelnumberEffective bevel width used for the map.
mapSize[number, number]Pixel dimensions of the generated map after size bucketing and downsampling.
radii[number, number, number, number]Element corner radii in pixels after CSS overlap handling.
mapstringOuter displacement map as a PNG data URL.
mapInnerstringInner displacement map used by the two-pass smoothing process.
splitnumberFraction of the displacement field assigned to the outer pass.

Corner Radius Behavior

Hyalite calculates circular corner radii individually and follows the CSS overlap rule when adjacent radii exceed the available edge length.

Elliptical radii such as:

border-radius: 40px / 16px;

Browser Compatibility

Browser EngineResult
Chromium browsers such as Chrome, Edge, Brave, Arc, and ElectronFull refraction.
Safari / WebKitCSS fallback.
Firefox / GeckoCSS fallback.

Define the fallback directly in the element styles:

.glass {
  backdrop-filter: var(--hyalite, blur(6px));
  -webkit-backdrop-filter: var(--hyalite, blur(6px));
}

Override Hyalite’s automatic browser verdict at the document level when needed:

<html data-hyalite="force">

Disable it with:

<html data-hyalite="off">

JavaScript can perform the equivalent override through Hyalite.force().

Alternatives & Related Resources

You Might Be Interested In:


Leave a Reply