03 / 36
All 36 in 36 Tailwind CSS Button Hover Effects
- 01Tailwind Magnetic Ripple Attraction Button Hover Effect
- 02Tailwind Cyberpunk Holographic Glitch Grid Button
- 03Tailwind Frosted Glassmorphism Shimmer Glow Button
- 04Tailwind Organic Blob Morph Button Hover Effect
- 05Tailwind Dual-Line Intersection Border Draw Button
- 06Tailwind Isometric Tactile 3D Depress Button
- 07Tailwind Infinite Sliding Kinetic Marquee Button
- 08Tailwind Chroma Conic Gradient Border Spin Button
- 09Tailwind Minimalist Border & Outline Drawing Hover Effects
- 10Tailwind Modern 3D Skeuomorphic Button Press Effects
- 11Tailwind Neo-Brutalist & Cyberpunk Button Glow Effects
- 12Tailwind Sliding Background Color Wipe Button Effects
- 13Tailwind Liquid Fill & Organic Morphing Button Effects
- 14Tailwind Kinetic Text Flip & Icon Reveal Button Effects
- 15Tailwind Liquid Wave Fill Button Hover Effect
- 16Tailwind Magnetic Border Drift Button
- 17Tailwind Glitch Slice Button Hover Effect
- 18Tailwind Neon Pulse Glow Button Hover Effect
- 19Tailwind Split Reveal Curtain Button Effect
- 20Tailwind Diagonal Shutter Sweep Button Effect
- 21Tailwind Elastic Lift Spring Button Hover Effect
- 22Tailwind Center Underline Draw Link Button Effects
- 23Tailwind 3D Flip Card Button Hover Effect
- 24Tailwind Particle Burst Confetti Button Effect
- 25Tailwind Slide Doors Closing Panel Button Effect
- 26Tailwind Typewriter Retype Terminal Button Effect
- 27Tailwind Hard Shadow Shift Flat Button Effect
- 28Tailwind Material Ripple Wave Button Effect
- 29Tailwind Rainbow Gradient Border Spin Button
- 30Tailwind Morph Shape Silhouette Button Effects
- 31Tailwind Icon Slide In Directional Button Effect
- 32Tailwind Cursor Spotlight Glow Button
- 33Tailwind Stagger Fill Equaliser Button Effect
- 34Tailwind Sunburst Expand Radiant Button Effect
- 35Tailwind 3D Press Plunger Key Button Effect
- 36Tailwind Add-to-Cart Liquid Glass Ripple Button
Tailwind Frosted Glassmorphism Shimmer Glow Button
The modern SaaS / Apple-style glass CTA: a translucent frosted pill that blurs the backdrop behind a hairline light rim, and on hover a diagonal shimmer beam sweeps across at 45 degrees like light on a wet lens. Tailwind ports this almost one-to-one — backdrop-blur-[16px] backdrop-saturate-[1.8] is the whole frost.
Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time
Untitled UI React · Affiliate link
The code
<div class="tbh-03-group w-full min-h-svh flex flex-wrap">
<section class="tbh-03a flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh03-sans bg-tbh03a-fallback bg-[url('https://picsum.photos/seed/bheglass/1200/800')] bg-cover bg-center" aria-label="Frosted glass shimmer button">
<button type="button" class="relative isolate overflow-hidden cursor-pointer rounded-full border border-white/40 px-10 py-[17px] text-base font-bold text-white bg-[color-mix(in_oklab,white_16%,transparent)] [text-shadow:0_1px_6px_oklch(0_0_0/0.35)] shadow-[inset_0_1px_0_oklch(1_0_0/0.6),inset_0_-8px_18px_-12px_oklch(0_0_0/0.5),0_16px_34px_-18px_oklch(0_0_0/0.7)] backdrop-blur-[16px] backdrop-saturate-[1.8] transition-[translate,scale,box-shadow] duration-300 hover:-translate-y-0.5 active:translate-y-0 active:scale-[.97] focus-visible:outline-3 focus-visible:outline-white focus-visible:outline-offset-[3px] after:content-[''] after:absolute after:-top-[20%] after:left-0 after:w-[55%] after:h-[140%] after:z-[2] after:pointer-events-none after:skew-x-[-16deg] after:-translate-x-[180%] after:bg-[linear-gradient(105deg,transparent_25%,oklch(1_0_0/0.6)_50%,transparent_75%)] after:transition-[translate] after:duration-[800ms] after:ease-[cubic-bezier(.2,.8,.2,1)] hover:after:translate-x-[260%] focus-visible:after:translate-x-[260%] motion-reduce:transition-none motion-reduce:hover:after:-translate-x-[180%] motion-reduce:focus-visible:after:-translate-x-[180%]">
<span class="relative z-[1]">Download app</span>
</button>
</section>
<section class="tbh-03b flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh03-sans bg-tbh03b-fallback bg-[url('https://picsum.photos/seed/bheglass2/1200/800')] bg-cover bg-center" aria-label="Tinted glass glow button">
<button type="button" class="relative isolate cursor-pointer rounded-[14px] border border-[color-mix(in_oklab,var(--color-tbh03b-glow)_50%,white)] px-[42px] py-[17px] text-base font-bold text-white bg-[color-mix(in_oklab,var(--color-tbh03b-glow)_22%,transparent)] [text-shadow:0_1px_6px_oklch(0_0_0/0.35)] shadow-[inset_0_1px_0_oklch(1_0_0/0.5),0_12px_30px_-16px_oklch(0_0_0/0.7)] backdrop-blur-[18px] backdrop-saturate-[1.6] transition-[translate,scale,box-shadow] duration-300 hover:-translate-y-0.5 hover:shadow-[inset_0_1px_0_oklch(1_0_0/0.6),0_0_0_1px_color-mix(in_oklab,var(--color-tbh03b-glow)_70%,transparent),0_18px_40px_-14px_var(--color-tbh03b-glow)] focus-visible:-translate-y-0.5 focus-visible:shadow-[inset_0_1px_0_oklch(1_0_0/0.6),0_18px_40px_-14px_var(--color-tbh03b-glow)] active:translate-y-0 active:scale-[.98] focus-visible:outline-3 focus-visible:outline-white focus-visible:outline-offset-[3px] motion-reduce:transition-[box-shadow] motion-reduce:hover:translate-y-0">
<span class="relative z-[1]">Open dashboard</span>
</button>
</section>
</div><div class="tbh-03-group w-full min-h-svh flex flex-wrap">
<section class="tbh-03a flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh03-sans bg-tbh03a-fallback bg-[url('https://picsum.photos/seed/bheglass/1200/800')] bg-cover bg-center" aria-label="Frosted glass shimmer button">
<button type="button" class="relative isolate overflow-hidden cursor-pointer rounded-full border border-white/40 px-10 py-[17px] text-base font-bold text-white bg-[color-mix(in_oklab,white_16%,transparent)] [text-shadow:0_1px_6px_oklch(0_0_0/0.35)] shadow-[inset_0_1px_0_oklch(1_0_0/0.6),inset_0_-8px_18px_-12px_oklch(0_0_0/0.5),0_16px_34px_-18px_oklch(0_0_0/0.7)] backdrop-blur-[16px] backdrop-saturate-[1.8] transition-[translate,scale,box-shadow] duration-300 hover:-translate-y-0.5 active:translate-y-0 active:scale-[.97] focus-visible:outline-3 focus-visible:outline-white focus-visible:outline-offset-[3px] after:content-[''] after:absolute after:-top-[20%] after:left-0 after:w-[55%] after:h-[140%] after:z-[2] after:pointer-events-none after:skew-x-[-16deg] after:-translate-x-[180%] after:bg-[linear-gradient(105deg,transparent_25%,oklch(1_0_0/0.6)_50%,transparent_75%)] after:transition-[translate] after:duration-[800ms] after:ease-[cubic-bezier(.2,.8,.2,1)] hover:after:translate-x-[260%] focus-visible:after:translate-x-[260%] motion-reduce:transition-none motion-reduce:hover:after:-translate-x-[180%] motion-reduce:focus-visible:after:-translate-x-[180%]">
<span class="relative z-[1]">Download app</span>
</button>
</section>
<section class="tbh-03b flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh03-sans bg-tbh03b-fallback bg-[url('https://picsum.photos/seed/bheglass2/1200/800')] bg-cover bg-center" aria-label="Tinted glass glow button">
<button type="button" class="relative isolate cursor-pointer rounded-[14px] border border-[color-mix(in_oklab,var(--color-tbh03b-glow)_50%,white)] px-[42px] py-[17px] text-base font-bold text-white bg-[color-mix(in_oklab,var(--color-tbh03b-glow)_22%,transparent)] [text-shadow:0_1px_6px_oklch(0_0_0/0.35)] shadow-[inset_0_1px_0_oklch(1_0_0/0.5),0_12px_30px_-16px_oklch(0_0_0/0.7)] backdrop-blur-[18px] backdrop-saturate-[1.6] transition-[translate,scale,box-shadow] duration-300 hover:-translate-y-0.5 hover:shadow-[inset_0_1px_0_oklch(1_0_0/0.6),0_0_0_1px_color-mix(in_oklab,var(--color-tbh03b-glow)_70%,transparent),0_18px_40px_-14px_var(--color-tbh03b-glow)] focus-visible:-translate-y-0.5 focus-visible:shadow-[inset_0_1px_0_oklch(1_0_0/0.6),0_18px_40px_-14px_var(--color-tbh03b-glow)] active:translate-y-0 active:scale-[.98] focus-visible:outline-3 focus-visible:outline-white focus-visible:outline-offset-[3px] motion-reduce:transition-[box-shadow] motion-reduce:hover:translate-y-0">
<span class="relative z-[1]">Open dashboard</span>
</button>
</section>
</div>@import "tailwindcss";
@theme {
--color-tbh03a-fallback: #14213d;
--color-tbh03a-fallback: oklch(0.28 0.06 265);
--color-tbh03b-fallback: #1a1030;
--color-tbh03b-fallback: oklch(0.22 0.07 290);
--color-tbh03b-glow: #7d8dff;
--color-tbh03b-glow: oklch(0.7 0.16 265);
--font-tbh03-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* Stays CSS: Safari < 16.4 needs the prefixed backdrop-filter, which has no utility form. */
.tbh-03a button {
-webkit-backdrop-filter: blur(16px) saturate(180%);
}
.tbh-03b button {
-webkit-backdrop-filter: blur(18px) saturate(160%);
}
.tbh-03-group {
width: 100%;
min-height: 100svh;
}
.tbh-03a,
.tbh-03b {
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-tbh03a-fallback: #14213d;
--color-tbh03a-fallback: oklch(0.28 0.06 265);
--color-tbh03b-fallback: #1a1030;
--color-tbh03b-fallback: oklch(0.22 0.07 290);
--color-tbh03b-glow: #7d8dff;
--color-tbh03b-glow: oklch(0.7 0.16 265);
--font-tbh03-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* Stays CSS: Safari < 16.4 needs the prefixed backdrop-filter, which has no utility form. */
.tbh-03a button {
-webkit-backdrop-filter: blur(16px) saturate(180%);
}
.tbh-03b button {
-webkit-backdrop-filter: blur(18px) saturate(160%);
}
.tbh-03-group {
width: 100%;
min-height: 100svh;
}
.tbh-03a,
.tbh-03b {
min-height: 100svh;
}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-tbh03a-fallback: #14213d;
--color-tbh03a-fallback: oklch(0.28 0.06 265);
--color-tbh03b-fallback: #1a1030;
--color-tbh03b-fallback: oklch(0.22 0.07 290);
--color-tbh03b-glow: #7d8dff;
--color-tbh03b-glow: oklch(0.7 0.16 265);
--font-tbh03-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* Stays CSS: Safari < 16.4 needs the prefixed backdrop-filter, which has no utility form. */
.tbh-03a button {
-webkit-backdrop-filter: blur(16px) saturate(180%);
}
.tbh-03b button {
-webkit-backdrop-filter: blur(18px) saturate(160%);
}
.tbh-03-group {
width: 100%;
min-height: 100svh;
}
.tbh-03a,
.tbh-03b {
min-height: 100svh;
}@import "tailwindcss";
@theme {
--color-tbh03a-fallback: #14213d;
--color-tbh03a-fallback: oklch(0.28 0.06 265);
--color-tbh03b-fallback: #1a1030;
--color-tbh03b-fallback: oklch(0.22 0.07 290);
--color-tbh03b-glow: #7d8dff;
--color-tbh03b-glow: oklch(0.7 0.16 265);
--font-tbh03-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* Stays CSS: Safari < 16.4 needs the prefixed backdrop-filter, which has no utility form. */
.tbh-03a button {
-webkit-backdrop-filter: blur(16px) saturate(180%);
}
.tbh-03b button {
-webkit-backdrop-filter: blur(18px) saturate(160%);
}
.tbh-03-group {
width: 100%;
min-height: 100svh;
}
.tbh-03a,
.tbh-03b {
min-height: 100svh;
}<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=Space+Grotesk:wght@400;500;600;700&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=Space+Grotesk:wght@400;500;600;700&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- The closest one-to-one port in the batch:
backdrop-filter:blur(16px) saturate(180%)becomesbackdrop-blur-[16px] backdrop-saturate-[1.8], and the three-layer inset shadow becomes one arbitraryshadow-[...]. Only the-webkit-shim had to stay CSS. - The hover state no longer repeats the skew. In CSS,
transform:translateX(260%) skewX(-16deg)had to restate the skew or lose it;hover:after:translate-x-[260%]touches only thetranslateproperty, andafter:skew-x-[-16deg]holds unchanged. - UI change from the CSS original: the shimmer now fires on
focus-visible:as well as hover, and the press state isactive:translate-y-0 active:scale-[.97]rather than a single combined transform — so a keyboard user sees the same effect a mouse user does.
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 Frosted Glassmorphism Shimmer Glow Button
Source: https://codefronts.com/motion/tailwind-css-button-hover-effects/tailwind-frosted-glassmorphism-shimmer-glow-button/
The modern SaaS / Apple-style glass CTA: a translucent frosted pill that blurs the backdrop behind a hairline light rim, and on hover a diagonal shimmer beam sweeps across at 45 degrees like light on a wet lens. Tailwind ports this almost one-to-one — backdrop-blur-[16px] backdrop-saturate-[1.8] is the whole frost.
## HTML
```html
<div class="tbh-03-group w-full min-h-svh flex flex-wrap">
<section class="tbh-03a flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh03-sans bg-tbh03a-fallback bg-[url('https://picsum.photos/seed/bheglass/1200/800')] bg-cover bg-center" aria-label="Frosted glass shimmer button">
<button type="button" class="relative isolate overflow-hidden cursor-pointer rounded-full border border-white/40 px-10 py-[17px] text-base font-bold text-white bg-[color-mix(in_oklab,white_16%,transparent)] [text-shadow:0_1px_6px_oklch(0_0_0/0.35)] shadow-[inset_0_1px_0_oklch(1_0_0/0.6),inset_0_-8px_18px_-12px_oklch(0_0_0/0.5),0_16px_34px_-18px_oklch(0_0_0/0.7)] backdrop-blur-[16px] backdrop-saturate-[1.8] transition-[translate,scale,box-shadow] duration-300 hover:-translate-y-0.5 active:translate-y-0 active:scale-[.97] focus-visible:outline-3 focus-visible:outline-white focus-visible:outline-offset-[3px] after:content-[''] after:absolute after:-top-[20%] after:left-0 after:w-[55%] after:h-[140%] after:z-[2] after:pointer-events-none after:skew-x-[-16deg] after:-translate-x-[180%] after:bg-[linear-gradient(105deg,transparent_25%,oklch(1_0_0/0.6)_50%,transparent_75%)] after:transition-[translate] after:duration-[800ms] after:ease-[cubic-bezier(.2,.8,.2,1)] hover:after:translate-x-[260%] focus-visible:after:translate-x-[260%] motion-reduce:transition-none motion-reduce:hover:after:-translate-x-[180%] motion-reduce:focus-visible:after:-translate-x-[180%]">
<span class="relative z-[1]">Download app</span>
</button>
</section>
<section class="tbh-03b flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh03-sans bg-tbh03b-fallback bg-[url('https://picsum.photos/seed/bheglass2/1200/800')] bg-cover bg-center" aria-label="Tinted glass glow button">
<button type="button" class="relative isolate cursor-pointer rounded-[14px] border border-[color-mix(in_oklab,var(--color-tbh03b-glow)_50%,white)] px-[42px] py-[17px] text-base font-bold text-white bg-[color-mix(in_oklab,var(--color-tbh03b-glow)_22%,transparent)] [text-shadow:0_1px_6px_oklch(0_0_0/0.35)] shadow-[inset_0_1px_0_oklch(1_0_0/0.5),0_12px_30px_-16px_oklch(0_0_0/0.7)] backdrop-blur-[18px] backdrop-saturate-[1.6] transition-[translate,scale,box-shadow] duration-300 hover:-translate-y-0.5 hover:shadow-[inset_0_1px_0_oklch(1_0_0/0.6),0_0_0_1px_color-mix(in_oklab,var(--color-tbh03b-glow)_70%,transparent),0_18px_40px_-14px_var(--color-tbh03b-glow)] focus-visible:-translate-y-0.5 focus-visible:shadow-[inset_0_1px_0_oklch(1_0_0/0.6),0_18px_40px_-14px_var(--color-tbh03b-glow)] active:translate-y-0 active:scale-[.98] focus-visible:outline-3 focus-visible:outline-white focus-visible:outline-offset-[3px] motion-reduce:transition-[box-shadow] motion-reduce:hover:translate-y-0">
<span class="relative z-[1]">Open dashboard</span>
</button>
</section>
</div>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tbh03a-fallback: #14213d;
--color-tbh03a-fallback: oklch(0.28 0.06 265);
--color-tbh03b-fallback: #1a1030;
--color-tbh03b-fallback: oklch(0.22 0.07 290);
--color-tbh03b-glow: #7d8dff;
--color-tbh03b-glow: oklch(0.7 0.16 265);
--font-tbh03-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* Stays CSS: Safari < 16.4 needs the prefixed backdrop-filter, which has no utility form. */
.tbh-03a button {
-webkit-backdrop-filter: blur(16px) saturate(180%);
}
.tbh-03b button {
-webkit-backdrop-filter: blur(18px) saturate(160%);
}
.tbh-03-group {
width: 100%;
min-height: 100svh;
}
.tbh-03a,
.tbh-03b {
min-height: 100svh;
}
```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 Frosted Glassmorphism Shimmer Glow Button
Source: https://codefronts.com/motion/tailwind-css-button-hover-effects/tailwind-frosted-glassmorphism-shimmer-glow-button/
The modern SaaS / Apple-style glass CTA: a translucent frosted pill that blurs the backdrop behind a hairline light rim, and on hover a diagonal shimmer beam sweeps across at 45 degrees like light on a wet lens. Tailwind ports this almost one-to-one — backdrop-blur-[16px] backdrop-saturate-[1.8] is the whole frost.
## HTML
```html
<div class="tbh-03-group w-full min-h-svh flex flex-wrap">
<section class="tbh-03a flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh03-sans bg-tbh03a-fallback bg-[url('https://picsum.photos/seed/bheglass/1200/800')] bg-cover bg-center" aria-label="Frosted glass shimmer button">
<button type="button" class="relative isolate overflow-hidden cursor-pointer rounded-full border border-white/40 px-10 py-[17px] text-base font-bold text-white bg-[color-mix(in_oklab,white_16%,transparent)] [text-shadow:0_1px_6px_oklch(0_0_0/0.35)] shadow-[inset_0_1px_0_oklch(1_0_0/0.6),inset_0_-8px_18px_-12px_oklch(0_0_0/0.5),0_16px_34px_-18px_oklch(0_0_0/0.7)] backdrop-blur-[16px] backdrop-saturate-[1.8] transition-[translate,scale,box-shadow] duration-300 hover:-translate-y-0.5 active:translate-y-0 active:scale-[.97] focus-visible:outline-3 focus-visible:outline-white focus-visible:outline-offset-[3px] after:content-[''] after:absolute after:-top-[20%] after:left-0 after:w-[55%] after:h-[140%] after:z-[2] after:pointer-events-none after:skew-x-[-16deg] after:-translate-x-[180%] after:bg-[linear-gradient(105deg,transparent_25%,oklch(1_0_0/0.6)_50%,transparent_75%)] after:transition-[translate] after:duration-[800ms] after:ease-[cubic-bezier(.2,.8,.2,1)] hover:after:translate-x-[260%] focus-visible:after:translate-x-[260%] motion-reduce:transition-none motion-reduce:hover:after:-translate-x-[180%] motion-reduce:focus-visible:after:-translate-x-[180%]">
<span class="relative z-[1]">Download app</span>
</button>
</section>
<section class="tbh-03b flex-[1_1_340px] min-w-[300px] grid place-items-center px-6 py-14 font-tbh03-sans bg-tbh03b-fallback bg-[url('https://picsum.photos/seed/bheglass2/1200/800')] bg-cover bg-center" aria-label="Tinted glass glow button">
<button type="button" class="relative isolate cursor-pointer rounded-[14px] border border-[color-mix(in_oklab,var(--color-tbh03b-glow)_50%,white)] px-[42px] py-[17px] text-base font-bold text-white bg-[color-mix(in_oklab,var(--color-tbh03b-glow)_22%,transparent)] [text-shadow:0_1px_6px_oklch(0_0_0/0.35)] shadow-[inset_0_1px_0_oklch(1_0_0/0.5),0_12px_30px_-16px_oklch(0_0_0/0.7)] backdrop-blur-[18px] backdrop-saturate-[1.6] transition-[translate,scale,box-shadow] duration-300 hover:-translate-y-0.5 hover:shadow-[inset_0_1px_0_oklch(1_0_0/0.6),0_0_0_1px_color-mix(in_oklab,var(--color-tbh03b-glow)_70%,transparent),0_18px_40px_-14px_var(--color-tbh03b-glow)] focus-visible:-translate-y-0.5 focus-visible:shadow-[inset_0_1px_0_oklch(1_0_0/0.6),0_18px_40px_-14px_var(--color-tbh03b-glow)] active:translate-y-0 active:scale-[.98] focus-visible:outline-3 focus-visible:outline-white focus-visible:outline-offset-[3px] motion-reduce:transition-[box-shadow] motion-reduce:hover:translate-y-0">
<span class="relative z-[1]">Open dashboard</span>
</button>
</section>
</div>
```
## CSS
```css
@import "tailwindcss";
@theme {
--color-tbh03a-fallback: #14213d;
--color-tbh03a-fallback: oklch(0.28 0.06 265);
--color-tbh03b-fallback: #1a1030;
--color-tbh03b-fallback: oklch(0.22 0.07 290);
--color-tbh03b-glow: #7d8dff;
--color-tbh03b-glow: oklch(0.7 0.16 265);
--font-tbh03-sans: 'Space Grotesk', system-ui, sans-serif;
}
/* Stays CSS: Safari < 16.4 needs the prefixed backdrop-filter, which has no utility form. */
.tbh-03a button {
-webkit-backdrop-filter: blur(16px) saturate(180%);
}
.tbh-03b button {
-webkit-backdrop-filter: blur(18px) saturate(160%);
}
.tbh-03-group {
width: 100%;
min-height: 100svh;
}
.tbh-03a,
.tbh-03b {
min-height: 100svh;
}
```How this works
Glass is a stack, not a colour. A translucent color-mix() fill, a backdrop-blur, an inset hairline for thickness and a cast shadow for lift — four utilities, all of which used to be four declarations. Nothing conceptual changed in the port; what changed is that the stack is legible next to the element it describes.
The sweep is one transform, twice. The beam is a 55%-wide gradient sheet parked at -180% with a -16deg skew, and hover moves it to 260%. Because v4 writes translate and skew as separate properties, the hover state states only the X offset — the skew is never repeated, which is exactly what the CSS version had to do.
Design B trades the sweep for a glow. Same glass, but hover layers an accent-tinted outer shadow instead of a beam, which is the calmer option for dashboards where a shine on every button reads as noise.
Make it yours
- Frost strength:
backdrop-blur-[16px]— keep it at or below 24px, since large blur radii are the single most expensive thing on this list for INP. - Shimmer angle: the
105degin the gradient plusafter:skew-x-[-16deg]; they should move together. - Sweep speed:
after:duration-[800ms], and theease-[cubic-bezier(.2,.8,.2,1)]that makes it decelerate out. - Tint:
bg-[color-mix(in_oklab,var(--color-tbh03b-glow)_22%,transparent)]— raise the percentage for more colour, but re-check label contrast when you do.
Gotchas — read before shipping
backdrop-filterneeds something non-opaque behind it: over a flat background colour the frost is invisible. Both stages here sit on a photo.- Safari below 16.4 needs
-webkit-backdrop-filter, which has no utility — it stays a two-line CSS rule per design. isolateon the button is load-bearing: without a stacking context the shimmer layer can paint over neighbouring content.- Contrast on glass depends on the photo behind it. The label keeps a
[text-shadow:0_1px_6px_...]so it clears 4.5:1 over both light and dark regions of the backdrop — test against your real image, not this one.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 128+ | 111+ |
backdrop-filter is the feature gate (Chrome 76, Safari 14 prefixed, Firefox 103) and degrades gracefully — without it the button is a semi-solid frosted capsule that still shimmers.