---
title: Liquid Glass
description: Glassmorphism extension with backdrop-blur surfaces and frosted overlays
visibility: guest
draft: false
---

# Liquid Glass

An optional glassmorphism extension for the **Cupertino** theme. Adds frosted-glass and refraction effects to any element via CSS classes.

::: warning
**The demos on this page only render as glass under the Cupertino Glass theme.** Pick it from the theme switcher in the bottom-left corner, and note that the entry is **Cupertino Glass** — the plain **Cupertino** entry is a different theme and cannot show the effect. Under every other theme the cards below render as ordinary opaque cards. That is the page, not your browser.
:::

## Installation

```bash
php artisan wirekit:glass install
```

This publishes two files to `public/vendor/wirekit/glass/`:

- `wirekit-glass.css` — glass class definitions
- `wirekit-glass.js` — optional: sets `wk-glass-tier2` on `<html>` for your own styling (the refraction itself needs no detection)

Then add the component as the **first element in your layout's `<body>`**:

```blade
<head>
    @wirekitStyles
</head>
<body>
    {{-- FIRST thing in the body, never in the head: this emits an <svg>, and an SVG in
         the head ends head parsing — every metadata tag after it is reparented into the
         body, where a crawler does not look. --}}
    <x-wirekit::glass />

    {{-- … your layout … --}}

    @wirekitScripts
</body>
```

The `<x-wirekit::glass />` component loads the CSS, JS, and injects the SVG filter definition needed for Tier 2 refraction.

<style>
@keyframes wk-gradient-shift {
    0% { background-position: 0% 50%, 0 0; }
    50% { background-position: 100% 50%, 0 0; }
    100% { background-position: 0% 50%, 0 0; }
}
@media (prefers-reduced-motion: reduce) {
    .wk-gradient-animated,
    .wk-glass-bg,
    .wk-glass-bg-dark { animation-play-state: paused !important; }
}
/* Pattern overlay — makes glass transparency visually obvious. The dots
   stay still while the gradient shifts behind them, so the blur of the
   backdrop-filter softens the dots into halos and the eye can clearly
   see "the box is letting the pattern through". */
.wk-glass-bg {
    background-image:
        radial-gradient(circle, rgba(255, 255, 255, 0.45) 2px, transparent 2.5px),
        var(--wk-glass-bg-gradient);
    background-size: 28px 28px, 400% 400%;
    background-repeat: repeat, no-repeat;
    background-position: 0 0, 0% 50%;
    animation: wk-gradient-shift 15s ease infinite;
}
.wk-glass-bg-dark {
    background-image:
        radial-gradient(circle, rgba(255, 255, 255, 0.18) 2px, transparent 2.5px),
        var(--wk-glass-bg-gradient);
    background-size: 28px 28px, 400% 400%;
    background-repeat: repeat, no-repeat;
    background-position: 0 0, 0% 50%;
    animation: wk-gradient-shift 20s ease infinite;
}
</style>

## Tier 1 — Frosted Glass

The `.wk-glass` class adds a frosted-glass effect using `backdrop-filter: blur()`. Works in all modern browsers.

:::preview{title="Frosted glass card"}
<div class="wk-glass-bg" style="--wk-glass-bg-gradient: linear-gradient(-45deg, #667eea, #764ba2, #23a6d5, #23d5ab); padding: 3rem; border-radius: 1rem;">
    <x-wirekit::card class="wk-glass" style="max-width: 24rem;">
        <x-wirekit::card.header>Frosted Glass</x-wirekit::card.header>
        <x-wirekit::card.body>
            This card uses the <code>wk-glass</code> class for a frosted backdrop effect. The colorful gradient and the dotted pattern behind it both bleed through softly — the dots make the transparency obvious.
        </x-wirekit::card.body>
    </x-wirekit::card>
</div>
:::

```blade
<x-wirekit::card class="wk-glass">
    <x-wirekit::card.header>Frosted Glass</x-wirekit::card.header>
    <x-wirekit::card.body>
        Content here.
    </x-wirekit::card.body>
</x-wirekit::card>
```

## Tier 2 — Refraction Glass

The `.wk-glass-refract` class renders **clear** refracting glass rather than frosted glass with an effect added — an SVG `feDisplacementMap` bends the backdrop the way a textured pane does, so what is behind the surface stays visible and comes through distorted. A thin blur and a thin wash are deliberate here: the refraction can only bend a backdrop that still reaches the eye. The distortion sits on a layer behind the content, so the surface's own text stays perfectly legible.

Pick it when you want the material to read as glass. Pick `wk-glass` when you want the content on top to sit on a calm surface — that one is built to hide what is behind it. One further difference matters at the call site: a refracting surface clips anything overflowing it, so it is not the right host for a dropdown or a tooltip.

:::preview{title="Refraction glass card"}
{{-- Injects the #wk-glass-refract SVG filter. Without it the card still
     frosts, but the refraction this demo is about does nothing. --}}
<x-wirekit::glass />
<div class="wk-glass-bg" style="--wk-glass-bg-gradient: linear-gradient(-45deg, #f093fb, #f5576c, #4facfe, #a18cd1); padding: 3rem; border-radius: 1rem;">
    <x-wirekit::card class="wk-glass-refract" style="max-width: 24rem;">
        <x-wirekit::card.header>Refraction Glass</x-wirekit::card.header>
        <x-wirekit::card.body>
            The background refracts through the card like looking through textured glass — watch the dotted pattern bend behind the box. The text on top is untouched.
        </x-wirekit::card.body>
    </x-wirekit::card>
</div>
:::

```blade
<x-wirekit::card class="wk-glass-refract">
    <x-wirekit::card.header>Refraction Glass</x-wirekit::card.header>
    <x-wirekit::card.body>
        Content here.
    </x-wirekit::card.body>
</x-wirekit::card>
```

## Side-by-Side Comparison

:::preview{title="Tier 1 vs Tier 2"}
{{-- Injects the #wk-glass-refract SVG filter. Without it the card still
     frosts, but the refraction this demo is about does nothing. --}}
<x-wirekit::glass />
<div class="wk-glass-bg" style="--wk-glass-bg-gradient: linear-gradient(-45deg, #a18cd1, #fbc2eb, #8ec5fc, #84fab0); padding: 2rem; border-radius: 1rem; display: flex; gap: 1.5rem; flex-wrap: wrap;">
    <x-wirekit::card class="wk-glass" style="flex: 1; min-width: 14rem;">
        <x-wirekit::card.header>Tier 1 — Frosted</x-wirekit::card.header>
        <x-wirekit::card.body>
            <code>wk-glass</code> — all browsers. Dot pattern softly diffuses through the glass.
        </x-wirekit::card.body>
    </x-wirekit::card>
    <x-wirekit::card class="wk-glass-refract" style="flex: 1; min-width: 14rem;">
        <x-wirekit::card.header>Tier 2 — Refraction</x-wirekit::card.header>
        <x-wirekit::card.body>
            <code>wk-glass-refract</code> — dots distort organically behind the glass.
        </x-wirekit::card.body>
    </x-wirekit::card>
</div>
:::

## With Other Components

Glass classes work on any element. Here are examples with different WireKit components:

:::preview{title="Glass alert"}
<div class="wk-glass-bg" style="--wk-glass-bg-gradient: linear-gradient(-45deg, #667eea, #764ba2, #11998e, #38ef7d); padding: 2rem; border-radius: 1rem;">
    <x-wirekit::alert variant="info" class="wk-glass">
        This alert uses the frosted glass effect. The background gradient and the dotted pattern are both softly visible behind it.
    </x-wirekit::alert>
</div>
:::

:::preview{title="Glass badge row"}
{{-- Injects the #wk-glass-refract SVG filter. Without it the card still
     frosts, but the refraction this demo is about does nothing. --}}
<x-wirekit::glass />
<div class="wk-glass-bg" style="--wk-glass-bg-gradient: linear-gradient(-45deg, #f093fb, #f5576c, #fccb90, #ee7752); padding: 2rem; border-radius: 1rem; display: flex; gap: 0.5rem; flex-wrap: wrap;">
    <x-wirekit::badge class="wk-glass">Frosted</x-wirekit::badge>
    <x-wirekit::badge class="wk-glass-refract">Refraction</x-wirekit::badge>
    <x-wirekit::badge intent="success" class="wk-glass">Success</x-wirekit::badge>
</div>
:::

## Dark Mode

Glass classes auto-adapt to dark mode. The dark variant uses a darker translucent background (`rgba(30, 30, 32, 0.78)`) with reduced border luminance — matching Apple's dark system backgrounds.

:::preview{title="Dark mode glass"}
<div class="wk-glass-bg-dark dark" style="--wk-glass-bg-gradient: linear-gradient(-45deg, #1a1a2e, #16213e, #0f3460, #1b1b3a); padding: 3rem; border-radius: 1rem;">
    <x-wirekit::card class="wk-glass" style="max-width: 24rem;">
        <x-wirekit::card.header>Dark Glass</x-wirekit::card.header>
        <x-wirekit::card.body>
            Dark mode uses Apple HIG system colors with a darker translucent overlay. The dotted pattern is rendered with low-luminance alpha so it sits subtly on the dark gradient without overpowering it.
        </x-wirekit::card.body>
    </x-wirekit::card>
</div>
:::

## How It Works

### Tier 1 — Frosted Glass (all browsers)

```css
.wk-glass {
    backdrop-filter: blur(20px) saturate(1.8) brightness(1.05);
    background: rgba(255, 255, 255, 0.72);
    border: 0.5px solid rgba(255, 255, 255, 0.45);
}
```

The `backdrop-filter` blurs and saturates the content behind the element. The semi-transparent white background creates the characteristic frosted look.

### Tier 2 — SVG Refraction

```css
.wk-glass-refract {
    /* 1. Clips the overshooting layer below back to a straight edge. */
    overflow: hidden;
    isolation: isolate;
    background: transparent;
}

.wk-glass-refract::before {
    /* 2. A layer BEHIND the content carries the backdrop, so the distortion
          lands on the background and the card's own text stays sharp. */
    content: '';
    position: absolute;
    inset: -40px; /* 3. Overshoots — see below. */
    z-index: -1;
    background: rgba(255, 255, 255, 0.22);
    backdrop-filter: blur(3px) saturate(1.6) brightness(1.03);
    filter: url(#wk-glass-refract); /* 4. feTurbulence + feDisplacementMap. */
}
```

Two details in there are load-bearing, and both are easy to undo by accident.

**Tier 2 is a different material, not Tier 1 with an effect on top.** Its blur and
its wash are far thinner than Tier 1's on purpose. Frosting exists to destroy the
structure behind it, and a refraction can only bend structure that still arrives —
raise the blur to Tier 1's and the distortion has nothing left to work on, so the
effect disappears completely while every declaration stays valid.

**The layer overshoots and the element clips it.** The displacement moves that
layer's own edge along with everything else, so a layer sized exactly to the card
would give the *card* a rippling outline. Overshooting pushes the rippled edge
outside, and `overflow: hidden` brings a straight one back. **The cost:** a Tier 2
surface clips its descendants, so it cannot host a dropdown or tooltip that
overflows it. Tier 1 has no such restriction and stays the default.

### Detection Script

The included JS detects Tier 2 support and adds `wk-glass-tier2` to `<html>`:

```js
// Debug mode: add ?wk-glass-debug to your URL
// Console output: [WireKit Glass] Tier: 2 (Refraction) | UA: ...
```

## CSS Classes

| Class | Tier | Browsers | Effect |
| --- | --- | --- | --- |
| `wk-glass` | 1 | All modern | Frosted glass — blur + saturate + translucent background. Hides what is behind it. |
| `wk-glass-refract` | 2 | All modern | Clear refracting glass — the backdrop stays visible and bends. Clips its own overflow. |

## HTML Classes (set by JS)

| Class | Set on | Meaning |
| --- | --- | --- |
| `wk-glass-tier2` | `<html>` | Browser applies SVG filters through `filter` — set for your own styling; the refraction does not depend on it |

## Accessibility

- Glass effects are purely decorative — no impact on screen readers
- Text on glass surfaces must still meet WCAG 2.2 contrast requirements (4.5:1 for normal text, 3:1 for large text)
- The semi-transparent backgrounds are calibrated to maintain readable contrast with WireKit's default text colors
- Reduced motion: the animated gradient backgrounds on this page respect `prefers-reduced-motion: reduce` — the animation pauses automatically for users who prefer reduced motion

## Keyboard Interaction

This component is purely presentational and does not respond to keyboard input.

## Design Tokens

Liquid Glass ships its own CSS variables (one custom property + the standard WireKit color tokens it composes against) rather than reaching for the core `--color-wk-*` palette directly:

| Token | Used for |
| --- | --- |
| `--wk-glass-bg-gradient` | Animated background-gradient layer behind a `.wk-glass-bg` container — set inline (`style="--wk-glass-bg-gradient: linear-gradient(...)"`) to drive the color passes for the demo gradients |

Glass surfaces themselves rely on browser features (`backdrop-filter: blur() saturate()` and SVG `feDisplacementMap` for Tier 2) rather than additional theme tokens. Text rendered on top of glass surfaces inherits the standard WireKit text tokens (`--color-wk-text`, `--color-wk-text-muted`, etc.) from the Cupertino preset.

## Customization

The glass CSS is published to `public/vendor/wirekit/glass/wirekit-glass.css`. You can edit it directly to adjust blur intensity, saturation, background opacity, or border style.

Key values to tune:

| Property | Default | Effect |
| --- | --- | --- |
| `blur()` | `20px` | Frosted intensity — higher = more opaque |
| `saturate()` | `1.8` | Color vibrancy of blurred background |
| `brightness()` | `1.05` | Slight lift to prevent dull appearance |
| `background alpha` | `0.72` (light) / `0.78` (dark) | Translucency — lower = more see-through |
| `feDisplacementMap scale` | `2` | Refraction intensity — higher = more distortion |

## Usage & Conventions

::: info
**Browser support:** Tier 1 (frosted glass via `backdrop-filter`) works in every supported browser. Tier 2 adds an SVG `feDisplacementMap` through `filter` on a pseudo-element — also within the supported baseline, and additive: where it is not applied, the Tier 1 frosted glass remains.
:::
