LayerwiseLayerwise
  • Features
  • Pricing
  • Templates
  • Docs
DownloadDownload
FeaturesPricingTemplatesDocsAI Website BuilderVibe CodingPersonal Software
DownloadDownload
  1. Glossary
  2. /
  3. Visual styles

Liquid glass

Also called Apple Liquid Glass or iOS 26 Liquid Glass

Apple’s translucent interface material from 2025 that bends, reflects, and tints the content behind it, with bright highlights along its edges.

import {
  Fragment,
  useEffect,
  useId,
  useRef,
  useState,
  type CSSProperties,
  type ReactNode
} from 'react';

// Liquid glass the way liquid-glass-react (MIT, by Max Rovensky) builds it:
// the backdrop is frosted and bent by an SVG displacement filter that moves
// red, green, and blue by slightly different amounts, with two rims that
// catch the light, a soft shadow, a hover sheen, and an elastic lean toward
// the pointer. The bend renders in Chromium; other browsers keep the rest.

const BEND = 70; // how far the map can shift the backdrop, in px
const ELASTICITY = 0.15; // 0 is rigid
const FROST = 'blur(6px) saturate(140%)';

// The displacement map: red holds the x shift (an S-curve across), blue the
// y shift (a ramp down), and 128 means no shift.
const stops = (values: number[], color: (value: number) => string) =>
  values
    .map((v, i) => `<stop offset="${i / 8}" stop-color="${color(v)}"/>`)
    .join('');
const MAP = `data:image/svg+xml,${encodeURIComponent(
  `<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256">
    <linearGradient id="x">${stops([250, 234, 214, 178, 124, 72, 33, 15, 1], (v) => `rgb(${v},0,0)`)}</linearGradient>
    <linearGradient id="y" x2="0" y2="1">${stops([255, 248, 230, 190, 131, 76, 36, 14, 0], (v) => `rgb(0,0,${v})`)}</linearGradient>
    <rect width="256" height="256" fill="url(#x)"/>
    <rect width="256" height="256" fill="url(#y)" style="mix-blend-mode:screen"/>
  </svg>`
)}`;

// Each color channel is displaced a little further than the last.
const CHANNELS = [
  { scale: -BEND, keep: '1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0' },
  { scale: -BEND * 1.1, keep: '0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0' },
  { scale: -BEND * 1.2, keep: '0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0' }
];

function GlassFilter({ id }: { id: string }) {
  // Sized like the glass, since the map's percentages resolve against it.
  return (
    <svg aria-hidden='true' className='pointer-events-none absolute size-full'>
      <filter
        id={id}
        x='-35%'
        y='-35%'
        width='170%'
        height='170%'
        colorInterpolationFilters='sRGB'
      >
        <feImage
          href={MAP}
          x='0'
          y='0'
          width='100%'
          height='100%'
          preserveAspectRatio='xMidYMid slice'
          result='map'
        />
        {CHANNELS.map(({ scale, keep }, index) => (
          <Fragment key={index}>
            <feDisplacementMap
              in='SourceGraphic'
              in2='map'
              scale={scale}
              xChannelSelector='R'
              yChannelSelector='B'
            />
            <feColorMatrix type='matrix' values={keep} result={`c${index}`} />
          </Fragment>
        ))}
        <feBlend in='c0' in2='c1' mode='screen' />
        <feBlend in2='c2' mode='screen' />
        <feGaussianBlur stdDeviation='0.3' />
      </filter>
    </svg>
  );
}

/** Wraps any content in liquid glass. Position it with `className`. */
export function LiquidGlass({
  className,
  children
}: {
  className: string;
  children: ReactNode;
}) {
  const filterId = `glass${useId().replace(/[^\w-]/g, '')}`;
  const ref = useRef<HTMLDivElement>(null);
  const [lean, setLean] = useState({ transform: 'none', x: 0, y: 0 });
  const [hovered, setHovered] = useState(false);
  const [pressed, setPressed] = useState(false);

  // Within 200px, lean and stretch toward the pointer; the rims' light
  // turns with it everywhere.
  useEffect(() => {
    const follow = (event: PointerEvent) => {
      const element = ref.current;
      if (!element) return;
      const rect = element.getBoundingClientRect();
      const { offsetWidth: width, offsetHeight: height } = element;
      const dx = event.clientX - rect.left - rect.width / 2;
      const dy = event.clientY - rect.top - rect.height / 2;
      const edge = Math.hypot(
        Math.max(0, Math.abs(dx) - width / 2),
        Math.max(0, Math.abs(dy) - height / 2)
      );
      const near = Math.max(0, 1 - edge / 200);
      const distance = Math.hypot(dx, dy) || 1;
      const stretch = Math.min(distance / 300, 1) * ELASTICITY * near;
      const along = (a: number, b: number) =>
        Math.max(0.8, 1 + (a * 0.3 - b * 0.15) * stretch);
      const [ax, ay] = [Math.abs(dx) / distance, Math.abs(dy) / distance];
      const shift = ELASTICITY * 0.1 * near;
      setLean({
        transform: `translate(${dx * shift}px, ${dy * shift}px) scale(${along(ax, ay)}, ${along(ay, ax)})`,
        x: (dx / width) * 100,
        y: (dy / height) * 100
      });
    };
    window.addEventListener('pointermove', follow);
    return () => window.removeEventListener('pointermove', follow);
  }, []);

  // The library screens and overlays these rims onto the glass. Blend modes
  // here would make Chrome isolate the glass and leave its backdrop-filter
  // nothing to frost, so they are plain white, dimmed to look the same.
  const rim = (low: number, high: number): CSSProperties => ({
    padding: 1.5,
    mask: 'linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0)',
    boxShadow:
      'inset 0 0 0 0.5px rgb(255 255 255 / 0.5), inset 0 1px 3px rgb(255 255 255 / 0.25), 0 1px 4px rgb(0 0 0 / 0.35)',
    background: `linear-gradient(${135 + lean.x * 1.2}deg, transparent, rgb(255 255 255 / ${low + Math.abs(lean.x) * 0.008}) ${Math.max(10, 33 + lean.y * 0.3)}%, rgb(255 255 255 / ${high + Math.abs(lean.x) * 0.012}) ${Math.min(90, 66 + lean.y * 0.4)}%, transparent)`
  });
  const sheen = pressed ? 0.2 : hovered ? 0.1 : 0;

  return (
    <div
      ref={ref}
      className={`rounded-full transition-transform duration-200 ease-out ${className}`}
      style={{ transform: lean.transform }}
      onPointerEnter={() => setHovered(true)}
      onPointerLeave={() => {
        setHovered(false);
        setPressed(false);
      }}
      onPointerDown={() => setPressed(true)}
      onPointerUp={() => setPressed(false)}
    >
      <div className='relative overflow-hidden rounded-full shadow-[0_12px_40px_rgb(0_0_0/0.25)]'>
        <GlassFilter id={filterId} />
        <span
          className='absolute inset-0'
          style={{ backdropFilter: FROST, filter: `url(#${filterId})` }}
        />
        <div className='relative text-white [text-shadow:0_2px_12px_rgb(0_0_0/0.4)]'>
          {children}
        </div>
      </div>
      <span
        aria-hidden='true'
        className='pointer-events-none absolute inset-0 rounded-full opacity-20'
        style={rim(0.12, 0.4)}
      />
      <span
        aria-hidden='true'
        className='pointer-events-none absolute inset-0 rounded-full'
        style={rim(0.12, 0.24)}
      />
      <span
        aria-hidden='true'
        className='pointer-events-none absolute inset-0 rounded-full bg-[radial-gradient(circle_at_50%_0%,white,transparent)] transition-opacity duration-200'
        style={{ opacity: sheen }}
      />
    </div>
  );
}

const TABS = ['Home', 'New', 'Radio', 'Library'];

export function GlassTabBar() {
  const [active, setActive] = useState('Home');

  return (
    <LiquidGlass className='fixed bottom-6 left-1/2 -translate-x-1/2'>
      <nav aria-label='Main' className='flex gap-1 p-1.5'>
        {TABS.map((tab) => (
          <button
            key={tab}
            type='button'
            aria-current={active === tab ? 'page' : undefined}
            onClick={() => setActive(tab)}
            className='rounded-full px-4 py-2 text-sm font-medium transition-colors aria-[current=page]:bg-white/20 aria-[current=page]:text-red-400'
          >
            {tab}
          </button>
        ))}
      </nav>
    </LiquidGlass>
  );
}
Make the bottom tab bar look like Apple’s Liquid Glass, built the way the open-source liquid-glass-react library does it. Frost the backdrop with a 6px blur and 140% saturation, and bend it near the edges with an SVG displacement filter (scale 70) that shifts red, green, and blue slightly apart. Add two thin rims whose light turns toward the pointer, a soft shadow, a hover sheen, and a slight elastic lean toward the pointer. Keep the rims in normal blending: blend modes next to the glass stop Chrome from frosting the backdrop. Keep the labels white, and put the selected tab on a 20% white pill. The bending only renders in Chromium, so check that Safari and Firefox still look right with just the frost and rims.

Paste into Layerwise or any AI coding tool.

What is Liquid glass?

Liquid Glass is the design material Apple introduced at WWDC in June 2025 for iOS 26, macOS Tahoe 26, and its other platforms. Tab bars, toolbars, and controls look like pieces of curved glass: content behind them bends near the edges, highlights catch the light as things move, and the tint adapts to what is underneath. Controls can also stretch and merge like drops of liquid as they change.

On the web, convincing versions stack several layers. The demo above and the example below are built like the open-source liquid-glass-react library: they frost the backdrop with backdrop-filter, bend it with an SVG feDisplacementMap filter that shifts red, green, and blue by slightly different amounts for faint color fringes, draw two 1.5px rims whose gradient turns toward the pointer, and add a soft shadow and an elastic lean. Only Chromium-based browsers run SVG filters on a backdrop, so Safari and Firefox get the frost and rims without the bending.

Use it the way Apple does: for floating navigation and controls that sit above content, rather than for whole cards of text. Like any glass effect it needs a contrast check, and some people turn on reduced transparency in their system settings, so respect prefers-reduced-transparency where browsers support it and fall back to a more opaque fill.

Often confused with

Glassmorphism
Glassmorphism is a heavily frosted blur with a light border. Liquid glass stays clearer and adds bending light and moving highlights at the edges.

Related terms

All terms

Glassmorphism

A visual style where panels look like frosted glass: translucent, blurred backgrounds with a thin light border over colorful shapes.

Blur

A softening effect made with CSS filter: blur() on an element itself, or backdrop-filter: blur() on whatever shows through it from behind.

Skeuomorphism

A design style where digital controls imitate real objects and materials, such as metal knobs, leather, paper, and physical switches.

Tabs

A row of labels that switches between panels of related content in the same spot, showing one panel at a time.

Build it with Layerwise

Describe your app, watch it run in a live preview, and publish it with a database, storage, and sign-in built in.

DownloadDownloadRead the docs
LayerwiseLayerwise

Build full-stack web apps in minutes with AI.

Product

  • Features
  • Pricing
  • Download
  • Templates

Solutions

  • AI Website Builder
  • Vibe Coding
  • Personal Software

Resources

  • Documentation
  • Changelog
  • Blog
  • Vibe Coding Glossary
  • llms.txt
  • llms-full.txt

Company

  • About
  • Contact

Legal

  • Privacy
  • Analytics Privacy
  • Terms
  • Security
  • Abuse

© 2026 Layerwise. All rights reserved.

Entrances & exits

  • Fade in
  • Slide in
  • Scale in
  • Pop in
  • Blur in
  • Reveal animation
  • Enter and exit animations

Timing & sequencing

  • Duration
  • Delay
  • Keyframes
  • Tweening
  • Stagger
  • Orchestration
  • Fill mode
  • Stepped animation
  • Looping animation
  • Yoyo animation

Easing

  • Easing
  • Linear easing
  • Ease-in
  • Ease-out
  • Ease-in-out
  • Cubic-bezier
  • Asymmetric easing
  • Overshoot easing

Springs & physics

  • Spring animation
  • Stiffness
  • Damping
  • Mass
  • Bounce
  • Velocity
  • Momentum
  • Interruptible animation
  • Rubber-banding

Transforms

  • Translate
  • Scale
  • Rotate
  • Skew
  • 3D flip
  • Perspective
  • Transform origin
  • Origin-aware animation

State transitions

  • Crossfade
  • Morph
  • Shared element transition
  • Layout animation
  • Height auto animation
  • Direction-aware transition
  • Continuity transition
  • Page transition
  • View Transitions API

Scroll effects

  • Scroll reveal
  • Scroll-driven animation
  • Parallax scrolling
  • Scrollytelling
  • Scroll pinning
  • Horizontal scroll section
  • Scroll progress bar
  • Scroll snap
  • Smooth scrolling

Interaction feedback

  • Hover effect
  • Press feedback
  • Ripple effect
  • Shake animation
  • Hold to confirm
  • Drag gesture
  • Drag to reorder
  • Swipe to dismiss
  • Pull to refresh
  • Magnetic button
  • Custom cursor
  • 3D tilt card
  • Spotlight card

Text effects

  • Typewriter effect
  • Text scramble
  • Split text animation
  • Text morph
  • Rotating words
  • Gradient text
  • Shimmer text
  • Number ticker
  • Tabular numbers
  • Underline animation

Loops & ambient motion

  • Marquee
  • Pulse animation
  • Float animation
  • Orbit animation
  • Idle animation
  • Particle background
  • Border beam
  • Confetti
  • Animated gradient

Visual effects

  • Blur
  • Clip-path
  • Mask
  • Before/after slider
  • SVG line drawing
  • Lottie animation

Motion principles

  • Purposeful animation
  • Anticipation
  • Follow-through
  • Squash and stretch
  • Perceived performance
  • Frequency of use
  • Spatial consistency
  • Reduced motion

Animation performance

  • Frame rate (FPS)
  • Jank
  • GPU acceleration
  • will-change
  • Layout thrashing

Layout

  • Hero section
  • Above the fold
  • Sticky header
  • Sidebar
  • Bento grid
  • Card
  • Flexbox
  • CSS Grid
  • Padding vs margin
  • Responsive design
  • Container
  • Masonry layout
  • Split screen
  • Z-index
  • Overflow

Components

  • Button variants
  • Modal
  • Drawer
  • Popover
  • Tooltip
  • Dropdown menu
  • Context menu
  • Toast notification
  • Tabs
  • Segmented control
  • Accordion
  • Carousel
  • Command palette
  • Combobox
  • Toggle switch
  • Checkbox
  • Radio button
  • Date picker
  • Breadcrumb
  • Pagination
  • Infinite scroll
  • Badge
  • Avatar stack
  • Empty state
  • Skeleton screen
  • Spinner
  • Progress bar
  • Data table
  • Stepper
  • Floating label
  • Inline validation
  • Alert banner
  • Tag input

States & patterns

  • Interaction states
  • Focus ring
  • Loading state
  • Optimistic UI
  • Debounce
  • Lazy loading
  • Dark mode
  • Micro-interaction
  • Affordance
  • Undo
  • Drag and drop
  • Keyboard shortcut

Visual styles

  • Glassmorphism
  • Liquid glass
  • Neumorphism
  • Claymorphism
  • Neo-brutalism
  • Skeuomorphism
  • Flat design
  • Mesh gradient
  • Aurora background
  • Grain texture
  • Glow effect
  • Drop shadow
  • Border radius
  • Grid background
  • Typographic hierarchy
  • Accent color
  • Color contrast

Vibe coding & AI

  • Vibe coding
  • Prompt
  • Context window
  • Token
  • AI agent
  • Tool call
  • Hallucination
  • Diff
  • Live preview
  • Checkpoint
  • Git commit
  • Deploy
  • Frontend and backend
  • API
  • Database
  • Rules file
  • MCP
  • Plan mode
  • Visual edit
Golden HourAna Vale