simple-liquid-glass
v4.1.0
Published
Zero-dependency React liquid glass with real SVG-displacement refraction on Chromium/Edge/Android-Chrome (a polished frosted-glass fallback on Safari/iOS/Firefox). Directional + animated 'liquid' refraction, lens modes. SSR-safe, ~10KB (web component ~6KB
Maintainers
Keywords
Readme
Simple Liquid Glass
A zero-dependency liquid glass component with real SVG refraction on Chromium, and a polished frosted glass everywhere else. Works on React 16.8–19.
A tiny, zero-dependency React liquid glass component. It renders Apple-style “liquid glass” with an SVG displacement map. On Chromium browsers (Chrome, Edge, Android Chrome) you get real refraction; on Safari, iOS, and Firefox it renders a deliberate, polished frosted glass (blur + saturation + subtle tint + gradient border) — real glass, just not refraction. The same behavior is available in the framework-agnostic <liquid-glass> web component too. Chromatic aberration, gradient borders, automatic text color, SSR-safe — the React core is ~10 KB (the web component ~6.5 KB).
Browser support
| Engine | Refraction | |---|---| | Chrome / Edge / Android Chrome (Chromium) | ✅ real SVG refraction | | Safari / iOS / Firefox | frosted glass (no refraction) |
Real refraction is an SVG displacement map inside CSS backdrop-filter, which renders only on Chromium. WebKit (Safari and all iOS browsers) and Firefox can't run SVG filters in backdrop-filter, so they fall back to the frosted-glass treatment.
🔗 Live demo · 📦 npm · 📖 Changelog
Why simple-liquid-glass?
| | simple-liquid-glass | liquid-glass-react | @specy/liquid-glass | |---|:--:|:--:|:--:| | Real SVG refraction on Chromium | ✅ | ✅ | ❌ (WebGL) | | React 16.8 – 19 | ✅ | ❌ (19 only) | ✅ | | Bundle (gzip) | ~10 KB (web component ~6.5 KB) | ~33 KB | 6.8 MB | | Zero runtime deps | ✅ | ✅ | ❌ (Three.js) | | SSR-safe (Next.js) | ✅ | ⚠️ | ❌ | | Web component (Vue / Svelte / vanilla) | ✅ | ❌ | ❌ | | Actively maintained (2026) | ✅ | ❌ (since Jun 2025) | ❌ |
Choose your path
- React, simple →
import { LiquidGlass } from 'simple-liquid-glass' - Pointer-reactive / “alive” →
import { LiquidGlassInteractive } from 'simple-liquid-glass/interactive' - Vue / Svelte / Astro / plain HTML →
import 'simple-liquid-glass/web-component'→<liquid-glass>
✨ New in 4.x
- Fold-free corners (4.1) — the
classiclens no longer shears or tears the backdrop along rounded-rect corners at highscale; the edge field fades to neutral over a scale-aware band instead of cliffing (with graceful amplitude falloff at extreme scale/aspect). - Chromium-only refraction (4.0) — real SVG refraction runs on Chrome / Edge / Android Chrome; Safari / iOS / Firefox get a polished frosted-glass fallback (the DOM-mirror engine was removed).
Earlier (3.x):
- Shape-adaptive refraction — the lens reads like glass cut to the element's shape; a long navbar or tall sidebar refracts evenly instead of skewing.
- Directional
angle— point the refraction lean any direction; faithful on any aspect ratio. - Lens modes (
lens) —classic(radial),convex(one coherent dome magnifier),shift(uniform offset — straight stays straight),rim(clear center, refractive edge) + manuallensStrength/lensCenter. - Real animated “liquid” refraction (
liquid) —ripple/flow/wobble; the backdrop genuinely warps. GPU-gated: in-view only, pauses on reduced-motion. - Pointer interaction (
LiquidGlassInteractive) —followPointerrefraction and water-like click ripples (clickRipple→ripple/drop).
Earlier highlights and the full per-version history are in the Changelog.
Features
- Liquid glassmorphism with SVG displacement
- Auto text color: detects dark/light backgrounds to keep text legible
- Custom glass color: accepts only semi‑transparent colors (
rgba,hsla, hex with alpha) - Background support: solid colors and gradients with automatic transparency conversion
- Chromatic dispersion and blur with fine‑grained controls
- Adjustable saturation to boost or tame color vibrancy
- Chromatic aberration intensity control to tune the vividness of the edge colors
- Gradient border with masking
- Responsive and content‑agnostic
- TypeScript and tree‑shakable builds (ESM and CJS)
Installation
npm install simple-liquid-glassor with yarn:
yarn add simple-liquid-glassUsage
Basic Usage
import React from 'react';
import { LiquidGlass } from 'simple-liquid-glass';
function App() {
return (
<div style={{ width: '300px', height: '200px' }}>
<LiquidGlass autoTextColor background="rgba(255,255,255,0.4)">
<div style={{ padding: '20px' }}>
<h2>Your Content Here</h2>
<p>This content has a liquid glass effect!</p>
</div>
</LiquidGlass>
</div>
);
}Pointer‑reactive elasticity — LiquidGlassInteractive
import { LiquidGlassInteractive } from 'simple-liquid-glass/interactive';
// Leans toward the cursor with a tiny spring + a pointer‑tracked specular highlight.
// Honors prefers-reduced-motion. Core import is unaffected (this is opt‑in).
<LiquidGlassInteractive elasticity={0.3}>…</LiquidGlassInteractive>Framework‑agnostic web component — <liquid-glass>
For Vue / Svelte / Angular / Astro / plain HTML (no React):
<script type="module" src="https://cdn.jsdelivr.net/npm/simple-liquid-glass/web-component"></script>
<liquid-glass radius="20" frost="0.15" style="width:320px;height:200px;display:block">
Glass anywhere
</liquid-glass>On Chromium the web component renders real SVG refraction; on Safari, iOS, and Firefox it renders the frosted-glass treatment — same as the React component.
Per-framework guides: Vue 3 / Nuxt · Svelte / SvelteKit · Astro · plain HTML / vanilla JS / Angular.
Advanced Usage with Custom Settings
import React from 'react';
import { LiquidGlass } from 'simple-liquid-glass';
function App() {
return (
<div style={{ width: '400px', height: '300px' }}>
<LiquidGlass
mode="custom"
scale={200}
radius={20}
border={0.1}
lightness={60}
displace={0.5}
alpha={0.8}
blur={10}
dispersion={30}
frost={0.2}
background="linear-gradient(45deg, #ff6b6b, #4ecdc4)"
autoTextColor
textOnDark="#ffffff"
textOnLight="#111111"
forceTextColor
borderColor="rgba(255, 255, 255, 0.5)"
className="my-glass-container"
style={{ boxShadow: '0 8px 32px rgba(0, 0, 0, 0.1)' }}
>
<div style={{ padding: '30px' }}>
<h1>Custom Glass Effect</h1>
<p>Fully customized liquid glass morphism with gradient background</p>
</div>
</LiquidGlass>
</div>
);
}Preset Mode
The component comes with a beautiful preset that works out of the box:
<LiquidGlass mode="preset">
<YourContent />
</LiquidGlass>Note: In preset mode, incoming props still override the preset defaults (e.g., scale, radius, blur, etc.).
On iOS, when iosBlurMode is 'auto', a minimal blur (iosMinBlur, default 7px) is applied even if blur is 0 to ensure a visible fallback effect.
The background prop automatically converts solid colors and gradients to semi-transparent (30% opacity) for better glass effects. Images (URLs) are left unchanged.
Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | ReactNode | - | Content to display inside the glass effect |
| mode | 'preset' \| 'custom' | 'preset' | Use preset values or custom configuration |
| scale | number | 160 | Scale of the displacement effect (-360 to 360) |
| radius | number | 50 | Border radius of the glass effect |
| border | number | 0.05 | Border thickness (0 to 0.5) |
| lightness | number | 53 | Lightness of the glass (0 to 100) |
| displace | number | 5 | Displacement blur amount (0 to 10) |
| alpha | number | 0.9 | Alpha transparency (0 to 1) |
| blur | number | 0 | Blur amount for the glass effect |
| dispersion | number | 50 | Chromatic dispersion amount |
| saturation | number | 140 | Color saturation multiplier (%) applied via CSS saturate() |
| aberrationIntensity | number | 0 | Multiplier for chromatic aberration (red/blue separation) |
| frost | number | 0.1 | Frost effect intensity (0 to 1) |
| borderColor | string | 'rgba(120, 120, 120, 0.7)' | Border color in CSS format |
| glassColor | string | 'rgba(255, 255, 255, 0.4)' | Semi‑transparent glass color (rgba, hsla, hsl(.../a), #RGBA, #RRGGBBAA). Invalid/opaque values fall back to frost‑based default |
| background | string | - | Background color or gradient (automatically made semi-transparent) |
| autoTextColor | boolean | false | Automatically detect background luminance and set text color |
| textOnDark | string | '#ffffff' | Text color used when background is detected as dark |
| textOnLight | string | '#111111' | Text color used when background is detected as light |
| forceTextColor | boolean | false | Force the computed text color on all descendants (!important) to override nested styles |
| className | string | - | Additional CSS class names |
| style | CSSProperties | - | Additional inline styles |
| quality | 'low' \| 'standard' \| 'high' \| 'extreme' | 'low' | Rendering quality preset. 'extreme' matches previous versions' visuals |
| autodetectquality | boolean | false | Auto-detect device performance and pick a quality preset |
| mobileFallback | 'css-only' \| 'svg' | CSS-only on mobile | Control mobile rendering strategy |
| effectMode | 'auto' \| 'svg' \| 'blur' \| 'off' | 'auto' | Control effect: auto, force SVG, force CSS blur, or disable |
| angle | number | 0 | Refraction direction in degrees (in-plane lean, not light tilt). 0 = baseline; positive = clockwise. Shape-adapted so the on-screen angle is faithful on any aspect ratio. Chromium SVG path. |
| shapeAdapt | boolean | true | Aspect-faithful + isotropic refraction so the lens reads like glass cut to the element's shape (long navbar / tall sidebar refract evenly). false restores the legacy ≤2.x map. |
| lens | 'classic' \| 'convex' \| 'shift' \| 'rim' | 'classic' | Lens field shape. classic = linear radial; convex = one coherent dome magnifier (no top/bottom split); shift = uniform directional offset (straight stays straight); rim = clear flat center, refraction only at a soft perimeter band. |
| lensStrength | number | 1 | Manual magnitude of the lens field. 0 disables the lens displacement. |
| lensCenter | [number, number] | [0.5, 0.5] | Normalized 0..1 center for convex / rim. |
| liquid | 'ripple' \| 'flow' \| 'wobble' \| false | false | Real animated refraction — the backdrop genuinely warps. Opt-in, GPU-real: runs only while on-screen, pauses on prefers-reduced-motion, Chromium SVG path only. |
| liquidSpeed | number | 1 | Motion rate multiplier for liquid. |
| liquidScale | number | preset | Distortion amplitude (px) for liquid. Defaults to the preset's amplitude. |
LiquidGlassInteractive(fromsimple-liquid-glass/interactive) adds:liquidTrigger('always' \| 'hover' \| 'press', default'always'—hover/pressstay idle until you interact),followPointer(boolean, a refractive bump that distorts the backdrop toward the cursor), andclickRipple(boolean, a real refractive ripple that expands + fades from each click).specular(the pointer-tracked highlight) is now opt-in (defaultfalse). All overlays are clipped to the glass radius.
Examples
Background with Gradient
<LiquidGlass
background="linear-gradient(45deg, #ff6b6b, #4ecdc4)"
autoTextColor
>
<div style={{ padding: '20px' }}>
<h2>Gradient Background</h2>
<p>This uses a gradient background that's automatically made semi-transparent!</p>
</div>
</LiquidGlass>Quality Presets and Autodetection
// Manual quality
<LiquidGlass quality="high" background="rgba(255,255,255,0.35)">
<Content />
</LiquidGlass>
// Autodetect device performance and choose quality automatically
<LiquidGlass autodetectquality background="rgba(255,255,255,0.35)">
<Content />
</LiquidGlass>
// Note:
// - Default quality is 'low'.
// - 'extreme' produces the same visual fidelity as previous versions of this component.
// - For many instances on the same page, prefer quality='low' or autodetectquality.Mobile Fallback Control
// Force CSS-only (strongest performance) even on desktop
<LiquidGlass mobileFallback="css-only" />
// Force SVG filter on mobile (may impact performance)
<LiquidGlass mobileFallback="svg" />
// Default behavior: CSS-only on mobile, SVG on desktop
<LiquidGlass />Browser Support & Rendering Strategies
SVG filters inside backdrop-filter (url(#...)) only work in Chromium (Chrome, Edge, Opera, Android Chrome). Safari/iOS WebKit (bug 245510) and Firefox silently ignore them, so the component picks a strategy per engine:
| Engine | effectMode="auto" |
|--------|--------------------|
| Chromium desktop | SVG displacement (full effect) |
| Chromium Android | Layered CSS (perf) — opt into SVG with mobileFallback="svg" |
| iOS Safari / all iOS browsers | Layered CSS fallback |
| Firefox | Layered CSS fallback |
Layered CSS fallback (automatic): instead of a flat blur, a masked edge ring with a stronger backdrop blur + brightness fakes the refraction band, plus a specular highlight. Zero dependencies, 60fps.
Note: versions 1.4.x shipped an experimental snapshot-based WebGL refraction mode (
effectMode="webgl"). It was removed in 2.0.0: snapshot-based refraction cannot track live page content reliably (smooth-scroll libraries, animations, html2canvas rendering gaps). On non-Chromium engines the component now always uses the layered CSS fallback.
Performance and Fallbacks
- Default behavior: on mobile devices the component uses a CSS-only effect to avoid jank; on desktop it uses the SVG filter.
- Quality presets:
'low'is the default and optimized for many instances;'extreme'matches previous visuals. - Autodetection: set
autodetectqualityto let the component choose a preset based on device performance. - Effect Mode: use
effectModeto force the strategy.
// Force CSS-only blur (no SVG) — recommended on very low-end devices
<LiquidGlass effectMode="blur" />
// Disable all filter effects (keeps border/frost/background)
<LiquidGlass effectMode="off" />
// Force SVG filter everywhere
<LiquidGlass effectMode="svg" />Effect Mode Control
// Force pure CSS blur (no SVG) — ideal per dispositivi molto low-end
<LiquidGlass effectMode="blur" />
// Disattiva totalmente l'effetto (mantiene solo saturazione/frost)
<LiquidGlass effectMode="off" />
// Forza sempre l'SVG
<LiquidGlass effectMode="svg" />
// Selezione automatica (default)
<LiquidGlass effectMode="auto" />Card with Glass Effect
<div className="card-container" style={{
width: '350px',
height: '200px'
}}>
<LiquidGlass
radius={15}
frost={0.15}
autoTextColor
background="linear-gradient(135deg, #667eea 0%, #764ba2 100%)"
>
<div style={{ padding: '24px', height: '100%' }}>
<h3 style={{ marginBottom: '12px' }}>
Glass Card
</h3>
<p>
This is a beautiful glass morphism card with liquid distortion effects and gradient background.
</p>
</div>
</LiquidGlass>
</div>Overlay Effect
<div style={{ position: 'relative', width: '100%', height: '400px' }}>
<img src="background.jpg" alt="Background" style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
<div style={{
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: '300px',
height: '150px'
}}>
<LiquidGlass autoTextColor background="rgba(255,255,255,0.4)">
<div style={{ padding: '20px', textAlign: 'center' }}>
<h2>Overlay Content</h2>
<p>Glass effect over image</p>
</div>
</LiquidGlass>
</div>
</div>Browser Support
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
The component leverages modern CSS (backdrop-filter) and SVG filters. Older browsers may not support all effects.
Performance Tips
- The component uses
ResizeObserverto adapt to size changes efficiently - SVG filters are hardware-accelerated in modern browsers
- For best performance, avoid animating the glass parameters rapidly
- Use the
presetmode for optimal default settings
Accessibility
autoTextColoruses computed styles from the nearest opaque ancestor to decide betweentextOnDarkandtextOnLight. This helps maintain readable contrast automatically. You can setforceTextColorto enforce the computed color on deeply nested content.
Storybook
Run a live playground:
npm run storybookSwitch the Backgrounds toolbar between light/dark to see text color adapt in real time.
Use with AI / LLMs
This library ships an LLM-friendly reference so any assistant can use it correctly and autonomously.
llms.txt— the complete API, recipes, and gotchas in one paste-anywhere file (the llms.txt convention). Feed it to any model.Claude Code skill —
skills/simple-liquid-glass/SKILL.md. Install it so Claude auto-loads the API when you work with the library:# copy into your user skills (or a project's .claude/skills/) mkdir -p ~/.claude/skills/simple-liquid-glass curl -fsSL https://raw.githubusercontent.com/lucaperullo/simple-liquid-glass/main/skills/simple-liquid-glass/SKILL.md \ -o ~/.claude/skills/simple-liquid-glass/SKILL.md
Copy-paste prompt (drop into any chat assistant):
You are helping me build UI with the npm package `simple-liquid-glass` (React + a <liquid-glass>
web component; Apple-style liquid glass with real SVG-displacement refraction). Use this reference
as the source of truth for its API and constraints:
https://raw.githubusercontent.com/lucaperullo/simple-liquid-glass/main/llms.txt
Key rules: real refraction is Chromium-only — Safari, iOS, and Firefox render a frosted-glass
fallback (no refraction); give the element an explicit size; `clickRipple`/`followPointer` are on
`LiquidGlassInteractive` only. Now: <your task>.System-prompt one-liner (for agents): "For simple-liquid-glass, follow its llms.txt; refraction is
Chromium-only (Safari/iOS/Firefox render a frosted-glass fallback); interaction props live on the
/interactive export."
License
MIT © [lucaperullo]
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Support
If you find this package helpful, please consider giving it a star on GitHub!
Keywords
react, react component, react ui, glassmorphism, glass morphism, liquid glass, liquid-glass, glass effect, frosted glass, frosted-glass, blur, blur effect, backdrop-filter, svg filter, displacement, displacement map, chromatic aberration, ui effects, card, overlay, glass ui, glass card, glass panel, glassmorphism react
For issues and feature requests, please create an issue.
