02 / 20
All 20 in 20 Tailwind Liquid Glass Effects
- 01Tailwind Liquid Glass Card with Hover Refraction
- 02Tailwind Liquid Glass Button with Glossy Highlight
- 03Tailwind Liquid Glass Navigation Bar
- 04Tailwind Liquid Gooey Toggle Switch
- 05Tailwind Liquid Glass Modal Dialog
- 06Tailwind Liquid Glass Theme Switcher
- 07Tailwind Liquid Glass Input Form Fields
- 08Tailwind SVG Displacement Liquid Glass Background
- 09Tailwind Liquid Glass Dropdown Menu
- 10Tailwind Liquid Glass Pricing Table
- 11Tailwind Liquid Glass Tooltip Popover
- 12Tailwind Liquid Glass Audio Player UI
- 13Tailwind Liquid Glass Range Slider
- 14Tailwind Liquid Glass Toast Notification
- 15Tailwind Liquid Glass Sidebar Navigation
- 16Tailwind Liquid Glass Accordion
- 17Tailwind Liquid Glass Login Card
- 18Tailwind Liquid Glass Floating Action Button
- 19Tailwind Liquid Glass Loading Skeleton
- 20Tailwind Liquid Glass Multi-Step Form Wizard
Tailwind Liquid Glass Button with Glossy Highlight
A capsule CTA in the macOS Tahoe / iOS 26 language, and a clean demonstration of what group buys you: the sweep lives on an after: layer parked off-screen, and group-hover:after:[transform:...] plus its group-focus-visible: twin drives it across. Two buttons, one shared class string, and the primary variant differs only by its gradient fill.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<section class="lgt-02 grid w-full min-h-svh place-items-center p-15 font-lgt02-sans bg-[image:url('https://picsum.photos/seed/lgbtn/1200/900')] bg-cover bg-center bg-fixed" aria-label="Tailwind liquid glass buttons">
<div class="flex flex-wrap items-center justify-center gap-5">
<button type="button" class="group relative isolate overflow-hidden cursor-pointer rounded-full border border-lgt02-accent/60 bg-linear-to-b from-lgt02-accent-top to-lgt02-accent px-8.5 py-4 text-base font-bold text-white backdrop-blur-[16px] backdrop-saturate-170 shadow-[inset_0_1px_0_rgba(255,255,255,.6),inset_0_-8px_18px_-10px_rgba(0,0,0,.5),0_14px_30px_-16px_rgba(0,0,0,.6)] transition-[transform,box-shadow] duration-200 hover:-translate-y-0.5 focus-visible:-translate-y-0.5 active:translate-y-0 active:scale-97 focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-white after:pointer-events-none after:absolute after:inset-y-0 after:left-0 after:z-2 after:w-3/5 after:[background:linear-gradient(105deg,transparent_20%,rgba(255,255,255,.55)_50%,transparent_80%)] after:[transform:translateX(-160%)_skewX(-12deg)] after:transition-transform after:duration-700 after:ease-lgt02 group-hover:after:[transform:translateX(230%)_skewX(-12deg)] group-focus-visible:after:[transform:translateX(230%)_skewX(-12deg)] motion-reduce:transition-none motion-reduce:after:transition-none motion-reduce:group-hover:after:[transform:translateX(-160%)_skewX(-12deg)]">Get started</button>
<button type="button" class="group relative isolate overflow-hidden cursor-pointer rounded-full border border-white/40 bg-white/14 px-8.5 py-4 text-base font-bold text-white backdrop-blur-[16px] backdrop-saturate-170 shadow-[inset_0_1px_0_rgba(255,255,255,.6),inset_0_-8px_18px_-10px_rgba(0,0,0,.5),0_14px_30px_-16px_rgba(0,0,0,.6)] transition-[transform,box-shadow] duration-200 hover:-translate-y-0.5 focus-visible:-translate-y-0.5 active:translate-y-0 active:scale-97 focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-white after:pointer-events-none after:absolute after:inset-y-0 after:left-0 after:z-2 after:w-3/5 after:[background:linear-gradient(105deg,transparent_20%,rgba(255,255,255,.55)_50%,transparent_80%)] after:[transform:translateX(-160%)_skewX(-12deg)] after:transition-transform after:duration-700 after:ease-lgt02 group-hover:after:[transform:translateX(230%)_skewX(-12deg)] group-focus-visible:after:[transform:translateX(230%)_skewX(-12deg)] motion-reduce:transition-none motion-reduce:after:transition-none motion-reduce:group-hover:after:[transform:translateX(-160%)_skewX(-12deg)]">Learn more</button>
</div>
</section><section class="lgt-02 grid w-full min-h-svh place-items-center p-15 font-lgt02-sans bg-[image:url('https://picsum.photos/seed/lgbtn/1200/900')] bg-cover bg-center bg-fixed" aria-label="Tailwind liquid glass buttons">
<div class="flex flex-wrap items-center justify-center gap-5">
<button type="button" class="group relative isolate overflow-hidden cursor-pointer rounded-full border border-lgt02-accent/60 bg-linear-to-b from-lgt02-accent-top to-lgt02-accent px-8.5 py-4 text-base font-bold text-white backdrop-blur-[16px] backdrop-saturate-170 shadow-[inset_0_1px_0_rgba(255,255,255,.6),inset_0_-8px_18px_-10px_rgba(0,0,0,.5),0_14px_30px_-16px_rgba(0,0,0,.6)] transition-[transform,box-shadow] duration-200 hover:-translate-y-0.5 focus-visible:-translate-y-0.5 active:translate-y-0 active:scale-97 focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-white after:pointer-events-none after:absolute after:inset-y-0 after:left-0 after:z-2 after:w-3/5 after:[background:linear-gradient(105deg,transparent_20%,rgba(255,255,255,.55)_50%,transparent_80%)] after:[transform:translateX(-160%)_skewX(-12deg)] after:transition-transform after:duration-700 after:ease-lgt02 group-hover:after:[transform:translateX(230%)_skewX(-12deg)] group-focus-visible:after:[transform:translateX(230%)_skewX(-12deg)] motion-reduce:transition-none motion-reduce:after:transition-none motion-reduce:group-hover:after:[transform:translateX(-160%)_skewX(-12deg)]">Get started</button>
<button type="button" class="group relative isolate overflow-hidden cursor-pointer rounded-full border border-white/40 bg-white/14 px-8.5 py-4 text-base font-bold text-white backdrop-blur-[16px] backdrop-saturate-170 shadow-[inset_0_1px_0_rgba(255,255,255,.6),inset_0_-8px_18px_-10px_rgba(0,0,0,.5),0_14px_30px_-16px_rgba(0,0,0,.6)] transition-[transform,box-shadow] duration-200 hover:-translate-y-0.5 focus-visible:-translate-y-0.5 active:translate-y-0 active:scale-97 focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-white after:pointer-events-none after:absolute after:inset-y-0 after:left-0 after:z-2 after:w-3/5 after:[background:linear-gradient(105deg,transparent_20%,rgba(255,255,255,.55)_50%,transparent_80%)] after:[transform:translateX(-160%)_skewX(-12deg)] after:transition-transform after:duration-700 after:ease-lgt02 group-hover:after:[transform:translateX(230%)_skewX(-12deg)] group-focus-visible:after:[transform:translateX(230%)_skewX(-12deg)] motion-reduce:transition-none motion-reduce:after:transition-none motion-reduce:group-hover:after:[transform:translateX(-160%)_skewX(-12deg)]">Learn more</button>
</div>
</section>@import "tailwindcss";
@theme {
--color-lgt02-accent: #6a4bff;
--color-lgt02-accent: oklch(0.62 0.2 275);
--color-lgt02-accent-top: #8168ff;
--color-lgt02-accent-top: oklch(0.68 0.18 275);
--font-lgt02-sans: 'Manrope', system-ui, sans-serif;
--ease-lgt02: cubic-bezier(0.2, 0.8, 0.2, 1);
}@import "tailwindcss";
@theme {
--color-lgt02-accent: #6a4bff;
--color-lgt02-accent: oklch(0.62 0.2 275);
--color-lgt02-accent-top: #8168ff;
--color-lgt02-accent-top: oklch(0.68 0.18 275);
--font-lgt02-sans: 'Manrope', system-ui, sans-serif;
--ease-lgt02: cubic-bezier(0.2, 0.8, 0.2, 1);
}Setup — do this once per project
Skip this if your project already runs Tailwind v4.
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>Compiles in the browser — perfect for a CodePen or a quick test, not for production.
npm install tailwindcss @tailwindcss/vite
npm install tailwindcss @tailwindcss/vite// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})// vite.config.js ("type": "module" in package.json)
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [tailwindcss()],
})Any v4 setup works — Vite, PostCSS or the CLI. Nothing in this demo is bundler-specific.
@import "tailwindcss";
@theme {
--color-lgt02-accent: #6a4bff;
--color-lgt02-accent: oklch(0.62 0.2 275);
--color-lgt02-accent-top: #8168ff;
--color-lgt02-accent-top: oklch(0.68 0.18 275);
--font-lgt02-sans: 'Manrope', system-ui, sans-serif;
--ease-lgt02: cubic-bezier(0.2, 0.8, 0.2, 1);
}@import "tailwindcss";
@theme {
--color-lgt02-accent: #6a4bff;
--color-lgt02-accent: oklch(0.62 0.2 275);
--color-lgt02-accent-top: #8168ff;
--color-lgt02-accent-top: oklch(0.68 0.18 275);
--font-lgt02-sans: 'Manrope', system-ui, sans-serif;
--ease-lgt02: cubic-bezier(0.2, 0.8, 0.2, 1);
}<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;600;800&display=swap">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;600;800&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- The two buttons share one class string; the primary only swaps the fill and border, so the variant is a diff rather than a second rule block.
- The specular sweep moves from a standalone
::afterrule into anafter:variant chain, including its own transition and its own reduced-motion pin. group-hover:andgroup-focus-visible:are always typed as a pair — the keyboard affordance becomes a habit you can see in the markup.- The gradient stop that was
color-mix(in oklab, var(--accent) 88%, white)becomes a second theme colour,--color-lgt02-accent-top, which is cheaper to read and mints its ownfrom-*utility. active:scale-97is a real v4 utility — the arbitrary[transform:scale(.97)]the CSS version needed is gone.
Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Liquid Glass Button with Glossy Highlight
Source: https://codefronts.com/design-styles/tailwind-liquid-glass-effects/tailwind-liquid-glass-button-with-glossy-highlight/
A capsule CTA in the macOS Tahoe / iOS 26 language, and a clean demonstration of what group buys you: the sweep lives on an after: layer parked off-screen, and group-hover:after:[transform:...] plus its group-focus-visible: twin drives it across. Two buttons, one shared class string, and the primary variant differs only by its gradient fill.
## HTML
```html
<section class="lgt-02 grid w-full min-h-svh place-items-center p-15 font-lgt02-sans bg-[image:url('https://picsum.photos/seed/lgbtn/1200/900')] bg-cover bg-center bg-fixed" aria-label="Tailwind liquid glass buttons">
<div class="flex flex-wrap items-center justify-center gap-5">
<button type="button" class="group relative isolate overflow-hidden cursor-pointer rounded-full border border-lgt02-accent/60 bg-linear-to-b from-lgt02-accent-top to-lgt02-accent px-8.5 py-4 text-base font-bold text-white backdrop-blur-[16px] backdrop-saturate-170 shadow-[inset_0_1px_0_rgba(255,255,255,.6),inset_0_-8px_18px_-10px_rgba(0,0,0,.5),0_14px_30px_-16px_rgba(0,0,0,.6)] transition-[transform,box-shadow] duration-200 hover:-translate-y-0.5 focus-visible:-translate-y-0.5 active:translate-y-0 active:scale-97 focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-white after:pointer-events-none after:absolute after:inset-y-0 after:left-0 after:z-2 after:w-3/5 after:[background:linear-gradient(105deg,transparent_20%,rgba(255,255,255,.55)_50%,transparent_80%)] after:[transform:translateX(-160%)_skewX(-12deg)] after:transition-transform after:duration-700 after:ease-lgt02 group-hover:after:[transform:translateX(230%)_skewX(-12deg)] group-focus-visible:after:[transform:translateX(230%)_skewX(-12deg)] motion-reduce:transition-none motion-reduce:after:transition-none motion-reduce:group-hover:after:[transform:translateX(-160%)_skewX(-12deg)]">Get started</button>
<button type="button" class="group relative isolate overflow-hidden cursor-pointer rounded-full border border-white/40 bg-white/14 px-8.5 py-4 text-base font-bold text-white backdrop-blur-[16px] backdrop-saturate-170 shadow-[inset_0_1px_0_rgba(255,255,255,.6),inset_0_-8px_18px_-10px_rgba(0,0,0,.5),0_14px_30px_-16px_rgba(0,0,0,.6)] transition-[transform,box-shadow] duration-200 hover:-translate-y-0.5 focus-visible:-translate-y-0.5 active:translate-y-0 active:scale-97 focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-white after:pointer-events-none after:absolute after:inset-y-0 after:left-0 after:z-2 after:w-3/5 after:[background:linear-gradient(105deg,transparent_20%,rgba(255,255,255,.55)_50%,transparent_80%)] after:[transform:translateX(-160%)_skewX(-12deg)] after:transition-transform after:duration-700 after:ease-lgt02 group-hover:after:[transform:translateX(230%)_skewX(-12deg)] group-focus-visible:after:[transform:translateX(230%)_skewX(-12deg)] motion-reduce:transition-none motion-reduce:after:transition-none motion-reduce:group-hover:after:[transform:translateX(-160%)_skewX(-12deg)]">Learn more</button>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-lgt02-accent: #6a4bff;
--color-lgt02-accent: oklch(0.62 0.2 275);
--color-lgt02-accent-top: #8168ff;
--color-lgt02-accent-top: oklch(0.68 0.18 275);
--font-lgt02-sans: 'Manrope', system-ui, sans-serif;
--ease-lgt02: cubic-bezier(0.2, 0.8, 0.2, 1);
}
```Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Liquid Glass Button with Glossy Highlight
Source: https://codefronts.com/design-styles/tailwind-liquid-glass-effects/tailwind-liquid-glass-button-with-glossy-highlight/
A capsule CTA in the macOS Tahoe / iOS 26 language, and a clean demonstration of what group buys you: the sweep lives on an after: layer parked off-screen, and group-hover:after:[transform:...] plus its group-focus-visible: twin drives it across. Two buttons, one shared class string, and the primary variant differs only by its gradient fill.
## HTML
```html
<section class="lgt-02 grid w-full min-h-svh place-items-center p-15 font-lgt02-sans bg-[image:url('https://picsum.photos/seed/lgbtn/1200/900')] bg-cover bg-center bg-fixed" aria-label="Tailwind liquid glass buttons">
<div class="flex flex-wrap items-center justify-center gap-5">
<button type="button" class="group relative isolate overflow-hidden cursor-pointer rounded-full border border-lgt02-accent/60 bg-linear-to-b from-lgt02-accent-top to-lgt02-accent px-8.5 py-4 text-base font-bold text-white backdrop-blur-[16px] backdrop-saturate-170 shadow-[inset_0_1px_0_rgba(255,255,255,.6),inset_0_-8px_18px_-10px_rgba(0,0,0,.5),0_14px_30px_-16px_rgba(0,0,0,.6)] transition-[transform,box-shadow] duration-200 hover:-translate-y-0.5 focus-visible:-translate-y-0.5 active:translate-y-0 active:scale-97 focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-white after:pointer-events-none after:absolute after:inset-y-0 after:left-0 after:z-2 after:w-3/5 after:[background:linear-gradient(105deg,transparent_20%,rgba(255,255,255,.55)_50%,transparent_80%)] after:[transform:translateX(-160%)_skewX(-12deg)] after:transition-transform after:duration-700 after:ease-lgt02 group-hover:after:[transform:translateX(230%)_skewX(-12deg)] group-focus-visible:after:[transform:translateX(230%)_skewX(-12deg)] motion-reduce:transition-none motion-reduce:after:transition-none motion-reduce:group-hover:after:[transform:translateX(-160%)_skewX(-12deg)]">Get started</button>
<button type="button" class="group relative isolate overflow-hidden cursor-pointer rounded-full border border-white/40 bg-white/14 px-8.5 py-4 text-base font-bold text-white backdrop-blur-[16px] backdrop-saturate-170 shadow-[inset_0_1px_0_rgba(255,255,255,.6),inset_0_-8px_18px_-10px_rgba(0,0,0,.5),0_14px_30px_-16px_rgba(0,0,0,.6)] transition-[transform,box-shadow] duration-200 hover:-translate-y-0.5 focus-visible:-translate-y-0.5 active:translate-y-0 active:scale-97 focus-visible:outline-3 focus-visible:outline-offset-3 focus-visible:outline-white after:pointer-events-none after:absolute after:inset-y-0 after:left-0 after:z-2 after:w-3/5 after:[background:linear-gradient(105deg,transparent_20%,rgba(255,255,255,.55)_50%,transparent_80%)] after:[transform:translateX(-160%)_skewX(-12deg)] after:transition-transform after:duration-700 after:ease-lgt02 group-hover:after:[transform:translateX(230%)_skewX(-12deg)] group-focus-visible:after:[transform:translateX(230%)_skewX(-12deg)] motion-reduce:transition-none motion-reduce:after:transition-none motion-reduce:group-hover:after:[transform:translateX(-160%)_skewX(-12deg)]">Learn more</button>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-lgt02-accent: #6a4bff;
--color-lgt02-accent: oklch(0.62 0.2 275);
--color-lgt02-accent-top: #8168ff;
--color-lgt02-accent-top: oklch(0.68 0.18 275);
--font-lgt02-sans: 'Manrope', system-ui, sans-serif;
--ease-lgt02: cubic-bezier(0.2, 0.8, 0.2, 1);
}
```How this works
One class string, two buttons. The glass capsule is shared; the primary adds a gradient fill and a lighter border. That is the entire difference between the variants, and you can see it in the diff rather than in two CSS blocks:
<!-- shared -->
class="group relative isolate overflow-hidden rounded-full
border border-white/40 bg-white/14
backdrop-blur-[16px] backdrop-saturate-170"
<!-- primary adds -->
class="bg-linear-to-b from-lgt02-accentTop to-lgt02-accent
border-lgt02-accent/60"The sweep is one pseudo-element and one transform. A narrow diagonal white gradient sits at 60% width, parked left of the button, skewed. On hover it translates right across the surface over 700ms. Nothing animates layout, so the whole thing runs on the compositor.
Thickness comes from two inset shadows, not from a border-radius trick. A 1px bright inset at the top is the rim-light where the glass edge catches light; a soft dark inset at the bottom is the occlusion under it. Together they read as a solid object rather than a coloured rectangle.
group is doing real work here. The sweep and the label both need the button's hover state, and both are typed with a group-focus-visible: twin — so the keyboard path is visibly identical, not an afterthought.
Make it yours
- Rebrand from one line: edit
--color-lgt02-accentin@themeand the fill, border and focus ring all follow. - Slow the sweep with
group-hover:after:duration-1000for a more languid, luxury feel; speed it to 400ms for a snappier product UI. - Drop the gradient fill for a ghost variant — the frost, rim and sweep alone still read unmistakably as glass.
- Change the sweep angle in the
skewXvalue and the gradient's 105deg; steeper angles look like a faster light source. - Swap
rounded-fullforrounded-2xlif your product language is squarer; nothing else changes.
Gotchas — read before shipping
- Keep the sweep on
translateX, never onleft. Animatinglefttriggers layout every frame and is the classic reason a glass button feels cheap on mobile. - The fill must stay translucent.
bg-lgt02-accentat full opacity gives backdrop-filter nothing to sample and the frost disappears. overflow-hiddenis what clips the sweep to the capsule — without it the light beam escapes the button.- Check label contrast against the brightest frame of the sweep, not the resting state. A 55%-white beam over a mid accent can dip below 4.5:1 for a few frames.
- The browser CDN build compiles in the page and is for prototyping only. Ship the CLI or a plugin build.
- Opacity modifiers work on theme colours (
bg-lgt02-accent/70) but not on arbitrary paint values inside a[background:...]arbitrary property.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
Utilities only, no JavaScript. Tailwind v4's sheet sets the floor; the underlying mechanisms (backdrop-filter, transforms, gradients) go back much further, and where backdrop-filter is missing the button degrades to a solid accent capsule with the same gloss sweep.