Skip to main content
Copy for LLM

Liquid Glass

An optional liquid-glass extension for the Cupertino theme. Adds glass surfaces in four levels, from clear to opaque, and a refraction effect to any element through CSS classes.

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

php artisan wirekit:glass install

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

  • wirekit-glass.css — glass class definitions
  • wirekit-glass.js — sets wk-glass-tier2 on <html> where the browser accepts an SVG filter through filter. The refraction is gated on that class, so without the script .wk-glass-refract stays the Tier 1 glass surface

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

<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.

Tier 1 — Glass

The .wk-glass class makes an element liquid glass: a light backdrop-filter blur, a thin fill, and an edge that catches the light. It works in every supported browser, at the regular level unless a level says otherwise.

Glass card
Glass
This card uses the wk-glass class. The gradient comes through the glass, the dotted pattern softens behind it, and the edge catches the light.
<x-wirekit::card class="wk-glass">
    <x-wirekit::card.header>Glass</x-wirekit::card.header>
    <x-wirekit::card.body>
        Content here.
    </x-wirekit::card.body>
</x-wirekit::card>

Levels

A level class sets how much of the backdrop the glass shows. Put it on the glass element itself, or on any ancestor, such as <html> for a whole application:

Class Shows of the backdrop Use it for
wk-glass-clear the most: it softens, its detail stays controls over photos, video or strong color
wk-glass-regular some: color and shape come through the default; floating bars, menus and cards over color
wk-glass-frosted little: a milky pane panels full of text, and anything over busy content
wk-glass-opaque nothing: the theme's elevated surface an in-app setting for readers who want no transparency
Four levels
Clear
The dots stay visible behind the glass.
Regular
The default: the color comes through.
Frosted
A milky pane for longer text.
Opaque
No transparency at all.

With levels nested in each other, the nearest one decides the colors and the blur comes from the level defined later in the stylesheet, so write the level on the glass element itself where a level sits inside another.

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 the backdrop itself should bend. Pick wk-glass when the content on top needs a calmer surface: its levels decide how much of the backdrop shows, and wk-glass-frosted hides most of 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.

The bending needs Chromium. Every browser on an iPhone or iPad runs Safari's engine, which accepts the filter and paints nothing from it, so there a refracting surface shows as clear glass under a light frost.

Refraction glass card
Refraction Glass
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 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

Tier 1 vs Tier 2
Tier 1 — Glass
wk-glass — all browsers. The dots soften behind the glass.
Tier 2 — Refraction
wk-glass-refract — dots distort organically behind the glass.

With Other Components

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

Glass alert
Information:
This alert is glass at the regular level. The gradient and the dotted pattern come through it softly.
Glass badge row
Glass Refraction Success

Dark Mode

Glass follows dark mode on its own. Under a .dark ancestor every level takes darker values from the same tokens: a dark fill, a dimmer rim, and an edge that keeps a softer light.

Dark mode glass
Dark Glass
In dark mode the fill turns dark and the edge keeps a softer light. The dotted pattern behind it is drawn faintly, so it sits on the dark gradient without taking over.

How It Works

Tier 1 — Glass (all browsers)

.wk-glass {
    backdrop-filter: blur(6px) saturate(1.6) brightness(1.04);
    background: var(--glass-wk-fill);
    border: 1px solid var(--glass-wk-rim);
    box-shadow:
        inset 2px -2px 1px -1px var(--glass-wk-highlight),
        inset -2px 2px 1px -1px var(--glass-wk-highlight),
        inset 6px -6px 1px -6px var(--glass-wk-sheen),
        inset -6px 6px 1px -6px var(--glass-wk-sheen),
        inset 0 0 2px var(--glass-wk-edge),
        var(--glass-wk-shadow);
}

The blur and the fill decide how much of the backdrop shows, and each level sets both. The edge decides whether the pane reads as glass: two bright inner lines on opposite corners, a softer light inside them, a dark hairline around the pane, and the shadow it casts.

Tier 2 — SVG Refraction

.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 layer keeps its own thin blur and wash, whatever level surrounds it. Frosting removes the structure behind a pane, and a refraction can only bend structure that still arrives: raise the blur to the frosted level's and the distortion has nothing left to work on, so the effect disappears 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>:

// 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 Liquid glass at the regular level: a light blur, a thin fill and an edge that catches the light.
wk-glass-clear, wk-glass-regular, wk-glass-frosted, wk-glass-opaque 1 All modern The level, on the glass element or on any ancestor: from the clearest pane to the theme's opaque surface.
wk-glass-refract 2 Chromium bends the backdrop; Safari shows it lightly frosted, without the bending 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 accepts an SVG filter through filter. The refraction is gated on it: without it, .wk-glass-refract is the Tier 1 glass surface. You can style on it too

Accessibility

  • prefers-reduced-transparency: reduce removes the blur entirely and makes every level the theme's opaque surface. macOS "Reduce transparency" and Windows "Transparency effects: off" both set it, and both are switched on for the same reasons: text over a moving, low-contrast backdrop is hard to read, and for some readers the shifting background is a vestibular trigger. The blur is removed rather than weakened, because a weaker blur is still a blur. Safari does not report this setting to a page, so on Apple devices it does not reach the glass; offer wk-glass-opaque on <html> as an in-app setting for readers who want it.

  • prefers-contrast: more gives an opaque pane with a strong border. Apple's "Increase Contrast" sets it, and Safari reports it, so this is the one Apple accessibility setting the glass answers on its own.

  • forced-colors: active hands the surface to the system. In High Contrast mode the OS replaces colors outright, and a backdrop-filter survives that replacement — so without this the blur would keep painting under text the system had just recolored for contrast, which is the exact combination the mode exists to prevent. The panel becomes Canvas / CanvasText like every other panel in that mode, and its shadow goes with it: a shadow is not recolored either, and survives as a stray smudge around an otherwise flattened panel.

  • On paper the panel keeps a boundary and nothing else. backdrop-filter does not paint in paged media at all, and the material is built from a translucent white fill and border. Browsers drop background graphics when printing unless the reader turns them on, so both would vanish and the content the surface was grouping would print as loose text with nothing around it. The print rule replaces them with a single currentColor border, which prints because the text prints.

  • 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)

  • On the regular, frosted and opaque levels, WireKit's default text holds 4.5:1 over the backdrop of the first demo on this page, in light and dark. The clear level shows the most of what is behind it, so keep its text short and bold, or dim a bright backdrop under it

  • 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

The glass stylesheet declares six custom properties of its own. Each level sets all six, for light and for dark:

Token Colors
--glass-wk-fill the tint laid over the blurred backdrop
--glass-wk-rim the border
--glass-wk-highlight the bright inner edge, top-right and bottom-left
--glass-wk-sheen the softer light just inside it
--glass-wk-edge the dark hairline that gives the pane its thickness
--glass-wk-shadow the shadow the pane casts

The opaque level reads the theme's --color-wk-bg-elevated and --color-wk-border, so it follows every preset. Text on glass inherits the standard text tokens (--color-wk-text, --color-wk-text-muted). The demos on this page draw their backdrop through --glass-demo-gradient, a property of this page's own style block, not of the extension.

Customization

Pick a level first. For values of your own, set the tokens in your own stylesheet: on :root for the default level, under .dark for dark mode, or on a level class for that level. They survive a reinstall of the published file, which an edit to it does not:

/* A warmer, slightly milkier default glass. */
:root {
    --glass-wk-fill: rgb(255 248 240 / 0.3);
}

.dark {
    --glass-wk-fill: rgb(40 32 24 / 0.45);
}

The blur belongs to the level and is not a token: some Safari releases drop a backdrop-filter built from a custom property, which would leave the fill without its blur. Each level sets it to:

Level Blur Fill, light / dark
clear blur(2px) saturate(1.4) 5% white / 16% near-black
regular blur(6px) saturate(1.6) brightness(1.04) 20% white / 40% near-black
frosted blur(20px) saturate(1.8) brightness(1.05) 72% white / 78% near-black
opaque none --color-wk-bg-elevated

The refraction's strength is the scale of the feDisplacementMap in the component, 60: higher bends more.

php artisan wirekit:glass install skips a published file that differs from the package copy, because it may carry your edits, so after an update that changes the glass, run it with --force once your own values live in your stylesheet.

Usage & Conventions

Browser support: Tier 1 (glass via backdrop-filter, at every level) works in every supported browser. Tier 2 bends the backdrop with an SVG feDisplacementMap in Chromium-based browsers such as Chrome and Edge. Safari, and every browser on iPhone and iPad, accepts the filter and paints no displacement from it, so .wk-glass-refract shows there as clear glass under a light frost, without the bending.

Updated in WireKit v2.66.0 (2026-10-13)

Was this page helpful?

Thank you for your feedback!

Voting requires cookies or local storage. What we store