07 / 25
All 25 in 25 Tailwind CSS FAQ Accordion
- 01Tailwind Peer-Checked FAQ Accordion with No JavaScript
- 02Tailwind Native Details/Summary FAQ with Custom Styled Icons
- 03Tailwind Exclusive Accordion — Only One FAQ Open at a Time
- 04Tailwind Multi-Open FAQ Accordion with a Live CSS Counter
- 05Tailwind CSS FAQ Accordion Template (Free, Copy-Paste)
- 06Tailwind Dark Mode FAQ Accordion with light-dark() and No .dark Class
- 07Tailwind Glassmorphism FAQ Accordion with Frosted Backdrop Blur
- 08Tailwind Minimalist E-Commerce FAQ Accordion for Product Pages
- 09Tailwind Neumorphic Soft-UI FAQ Accordion Cards
- 10Tailwind Animate Height Auto FAQ with grid-rows 0fr to 1fr
- 11Tailwind FAQ Chevron Rotate 180 Degrees on Toggle
- 12Tailwind Animated Plus to Minus Icon Morph FAQ Accordion
- 13Tailwind Spring Bounce FAQ Accordion with linear() Easing
- 14Tailwind Two-Column FAQ Accordion Grid with Independent Columns
- 15Tailwind Horizontal FAQ Accordion with Sideways Expanding Panels
- 16Tailwind Categorised FAQ Help Centre with a Sticky Sidebar Menu
- 17Tailwind Card-Style FAQ Panels with a Layered Shadow Elevation System
- 18Tailwind FAQ Accordion with a Live Search Bar Filter
- 19Tailwind Expand All and Collapse All FAQ Accordion Buttons
- 20Tailwind FAQ with a Still Have Questions Contact CTA Card
- 21Tailwind Accessible ARIA FAQ Accordion with Keyboard Navigation
- 22Tailwind FAQ with FAQPage JSON-LD Schema for Rich Snippets and AI Search
- 23Bootstrap 5 Accordion Rebuilt in Tailwind (and the JavaScript You Delete)
- 24Tailwind FAQ Component in React, Vue, Svelte and Astro (One Port Recipe)
- 25Tailwind FAQ with Voice Search Using the Speech Recognition API
Tailwind Glassmorphism FAQ Accordion with Frosted Backdrop Blur
Frosted-glass panels floating over a photographic backdrop. Tailwind has utilities for all four glass layers — the tint, backdrop-blur-[18px] backdrop-saturate-150, a translucent border and an inset highlight inside shadow-[...] — so the whole material is a class list, and the open state simply frosts deeper. Includes the two rules most glassmorphism tutorials miss: the saturation boost and the top-edge highlight.
Complete Tailwind CSS landing page templates in HTML, React, Next.js and Vue · from $49
Cruip · Affiliate link
The code
<section class="tfa-07 w-full min-h-svh font-tfa07-sans">
<div class="grid min-h-svh w-full place-items-center bg-[linear-gradient(160deg,oklch(0.45_0.2_290/0.55),oklch(0.5_0.22_340/0.35)_55%,oklch(0.55_0.18_240/0.5)),url('https://images.unsplash.com/photo-1518098268026-4e89f1a2cd8e?q=80&w=1800&auto=format&fit=crop')] bg-cover bg-center px-5 py-12">
<div class="w-[min(620px,100%)]">
<header>
<h1 class="text-[clamp(30px,5vw,42px)] font-extrabold leading-[1.06] tracking-[-0.025em] text-white [text-shadow:0_2px_24px_oklch(0.2_0.08_290/0.6)]">Membership FAQ</h1>
<p class="mt-3 max-w-[52ch] text-[14.5px] leading-relaxed text-white/90 [text-shadow:0_1px_12px_oklch(0.2_0.08_290/0.65)]">Four layers make the glass: tint, frost, edge, highlight. The open panel frosts deeper — no accent colour needed.</p>
</header>
<div data-panel class="mt-7 flex flex-col gap-3">
<details class="group rounded-[18px] border border-white/30 bg-white/15 shadow-[inset_0_1px_0_oklch(1_0_0/0.35),0_24px_48px_oklch(0.3_0.12_290/0.35)] backdrop-blur-[18px] backdrop-saturate-150 transition-[background-color,box-shadow,backdrop-filter] duration-350 open:bg-white/25 open:shadow-[inset_0_1px_0_oklch(1_0_0/0.45),0_30px_60px_oklch(0.3_0.12_290/0.45)] open:backdrop-blur-[26px] open:backdrop-saturate-[1.8]" open>
<summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-5 py-4 text-[15.5px] font-semibold tracking-[-0.01em] text-white [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.55)] focus-visible:rounded-[18px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-white [&::-webkit-details-marker]:hidden">What does membership include?
<span aria-hidden="true" class="grid size-7 shrink-0 place-items-center rounded-full border border-white/40 transition-[rotate,background-color] duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] group-hover:bg-white/20 group-open:rotate-180 group-open:bg-white/20 motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="13" height="13"><path d="M3 6l5 5 5-5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
</summary>
<p class="max-w-[58ch] px-5 pb-4 text-[14px] leading-[1.7] text-white/90 [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.5)]">Unlimited access to every studio location, all live classes, and the on-demand library. Founding members also lock their rate for life — it never increases while the membership stays active.</p>
</details>
<details class="group rounded-[18px] border border-white/30 bg-white/15 shadow-[inset_0_1px_0_oklch(1_0_0/0.35),0_24px_48px_oklch(0.3_0.12_290/0.35)] backdrop-blur-[18px] backdrop-saturate-150 transition-[background-color,box-shadow,backdrop-filter] duration-350 open:bg-white/25 open:shadow-[inset_0_1px_0_oklch(1_0_0/0.45),0_30px_60px_oklch(0.3_0.12_290/0.45)] open:backdrop-blur-[26px] open:backdrop-saturate-[1.8]">
<summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-5 py-4 text-[15.5px] font-semibold tracking-[-0.01em] text-white [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.55)] focus-visible:rounded-[18px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-white [&::-webkit-details-marker]:hidden">Can I freeze my membership?
<span aria-hidden="true" class="grid size-7 shrink-0 place-items-center rounded-full border border-white/40 transition-[rotate,background-color] duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] group-hover:bg-white/20 group-open:rotate-180 group-open:bg-white/20 motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="13" height="13"><path d="M3 6l5 5 5-5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
</summary>
<p class="max-w-[58ch] px-5 pb-4 text-[14px] leading-[1.7] text-white/90 [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.5)]">Yes — up to 3 months per year, in one-month blocks, straight from the app. Frozen months push your renewal date back, so you never pay for time you cannot use.</p>
</details>
<details class="group rounded-[18px] border border-white/30 bg-white/15 shadow-[inset_0_1px_0_oklch(1_0_0/0.35),0_24px_48px_oklch(0.3_0.12_290/0.35)] backdrop-blur-[18px] backdrop-saturate-150 transition-[background-color,box-shadow,backdrop-filter] duration-350 open:bg-white/25 open:shadow-[inset_0_1px_0_oklch(1_0_0/0.45),0_30px_60px_oklch(0.3_0.12_290/0.45)] open:backdrop-blur-[26px] open:backdrop-saturate-[1.8]">
<summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-5 py-4 text-[15.5px] font-semibold tracking-[-0.01em] text-white [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.55)] focus-visible:rounded-[18px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-white [&::-webkit-details-marker]:hidden">Do you offer day passes for guests?
<span aria-hidden="true" class="grid size-7 shrink-0 place-items-center rounded-full border border-white/40 transition-[rotate,background-color] duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] group-hover:bg-white/20 group-open:rotate-180 group-open:bg-white/20 motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="13" height="13"><path d="M3 6l5 5 5-5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
</summary>
<p class="max-w-[58ch] px-5 pb-4 text-[14px] leading-[1.7] text-white/90 [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.5)]">Every member gets 2 free guest passes a month. Additional passes are $15, and guests who join within 7 days get their pass credited toward the first month.</p>
</details>
<details class="group rounded-[18px] border border-white/30 bg-white/15 shadow-[inset_0_1px_0_oklch(1_0_0/0.35),0_24px_48px_oklch(0.3_0.12_290/0.35)] backdrop-blur-[18px] backdrop-saturate-150 transition-[background-color,box-shadow,backdrop-filter] duration-350 open:bg-white/25 open:shadow-[inset_0_1px_0_oklch(1_0_0/0.45),0_30px_60px_oklch(0.3_0.12_290/0.45)] open:backdrop-blur-[26px] open:backdrop-saturate-[1.8]">
<summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-5 py-4 text-[15.5px] font-semibold tracking-[-0.01em] text-white [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.55)] focus-visible:rounded-[18px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-white [&::-webkit-details-marker]:hidden">Which locations are open 24/7?
<span aria-hidden="true" class="grid size-7 shrink-0 place-items-center rounded-full border border-white/40 transition-[rotate,background-color] duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] group-hover:bg-white/20 group-open:rotate-180 group-open:bg-white/20 motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="13" height="13"><path d="M3 6l5 5 5-5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
</summary>
<p class="max-w-[58ch] px-5 pb-4 text-[14px] leading-[1.7] text-white/90 [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.5)]">All flagship locations run 24/7 with app-based entry. Neighbourhood studios open 5am–11pm; the app map badges each one with live hours and current capacity.</p>
</details>
</div>
<p class="mt-6 font-tfa07-mono text-[11.5px] text-white/85 [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.6)]">backdrop-blur-[18px] backdrop-saturate-150 — the saturate is what makes it glass, not smear.</p>
</div>
</div>
</section><section class="tfa-07 w-full min-h-svh font-tfa07-sans">
<div class="grid min-h-svh w-full place-items-center bg-[linear-gradient(160deg,oklch(0.45_0.2_290/0.55),oklch(0.5_0.22_340/0.35)_55%,oklch(0.55_0.18_240/0.5)),url('https://images.unsplash.com/photo-1518098268026-4e89f1a2cd8e?q=80&w=1800&auto=format&fit=crop')] bg-cover bg-center px-5 py-12">
<div class="w-[min(620px,100%)]">
<header>
<h1 class="text-[clamp(30px,5vw,42px)] font-extrabold leading-[1.06] tracking-[-0.025em] text-white [text-shadow:0_2px_24px_oklch(0.2_0.08_290/0.6)]">Membership FAQ</h1>
<p class="mt-3 max-w-[52ch] text-[14.5px] leading-relaxed text-white/90 [text-shadow:0_1px_12px_oklch(0.2_0.08_290/0.65)]">Four layers make the glass: tint, frost, edge, highlight. The open panel frosts deeper — no accent colour needed.</p>
</header>
<div data-panel class="mt-7 flex flex-col gap-3">
<details class="group rounded-[18px] border border-white/30 bg-white/15 shadow-[inset_0_1px_0_oklch(1_0_0/0.35),0_24px_48px_oklch(0.3_0.12_290/0.35)] backdrop-blur-[18px] backdrop-saturate-150 transition-[background-color,box-shadow,backdrop-filter] duration-350 open:bg-white/25 open:shadow-[inset_0_1px_0_oklch(1_0_0/0.45),0_30px_60px_oklch(0.3_0.12_290/0.45)] open:backdrop-blur-[26px] open:backdrop-saturate-[1.8]" open>
<summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-5 py-4 text-[15.5px] font-semibold tracking-[-0.01em] text-white [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.55)] focus-visible:rounded-[18px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-white [&::-webkit-details-marker]:hidden">What does membership include?
<span aria-hidden="true" class="grid size-7 shrink-0 place-items-center rounded-full border border-white/40 transition-[rotate,background-color] duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] group-hover:bg-white/20 group-open:rotate-180 group-open:bg-white/20 motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="13" height="13"><path d="M3 6l5 5 5-5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
</summary>
<p class="max-w-[58ch] px-5 pb-4 text-[14px] leading-[1.7] text-white/90 [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.5)]">Unlimited access to every studio location, all live classes, and the on-demand library. Founding members also lock their rate for life — it never increases while the membership stays active.</p>
</details>
<details class="group rounded-[18px] border border-white/30 bg-white/15 shadow-[inset_0_1px_0_oklch(1_0_0/0.35),0_24px_48px_oklch(0.3_0.12_290/0.35)] backdrop-blur-[18px] backdrop-saturate-150 transition-[background-color,box-shadow,backdrop-filter] duration-350 open:bg-white/25 open:shadow-[inset_0_1px_0_oklch(1_0_0/0.45),0_30px_60px_oklch(0.3_0.12_290/0.45)] open:backdrop-blur-[26px] open:backdrop-saturate-[1.8]">
<summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-5 py-4 text-[15.5px] font-semibold tracking-[-0.01em] text-white [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.55)] focus-visible:rounded-[18px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-white [&::-webkit-details-marker]:hidden">Can I freeze my membership?
<span aria-hidden="true" class="grid size-7 shrink-0 place-items-center rounded-full border border-white/40 transition-[rotate,background-color] duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] group-hover:bg-white/20 group-open:rotate-180 group-open:bg-white/20 motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="13" height="13"><path d="M3 6l5 5 5-5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
</summary>
<p class="max-w-[58ch] px-5 pb-4 text-[14px] leading-[1.7] text-white/90 [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.5)]">Yes — up to 3 months per year, in one-month blocks, straight from the app. Frozen months push your renewal date back, so you never pay for time you cannot use.</p>
</details>
<details class="group rounded-[18px] border border-white/30 bg-white/15 shadow-[inset_0_1px_0_oklch(1_0_0/0.35),0_24px_48px_oklch(0.3_0.12_290/0.35)] backdrop-blur-[18px] backdrop-saturate-150 transition-[background-color,box-shadow,backdrop-filter] duration-350 open:bg-white/25 open:shadow-[inset_0_1px_0_oklch(1_0_0/0.45),0_30px_60px_oklch(0.3_0.12_290/0.45)] open:backdrop-blur-[26px] open:backdrop-saturate-[1.8]">
<summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-5 py-4 text-[15.5px] font-semibold tracking-[-0.01em] text-white [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.55)] focus-visible:rounded-[18px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-white [&::-webkit-details-marker]:hidden">Do you offer day passes for guests?
<span aria-hidden="true" class="grid size-7 shrink-0 place-items-center rounded-full border border-white/40 transition-[rotate,background-color] duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] group-hover:bg-white/20 group-open:rotate-180 group-open:bg-white/20 motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="13" height="13"><path d="M3 6l5 5 5-5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
</summary>
<p class="max-w-[58ch] px-5 pb-4 text-[14px] leading-[1.7] text-white/90 [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.5)]">Every member gets 2 free guest passes a month. Additional passes are $15, and guests who join within 7 days get their pass credited toward the first month.</p>
</details>
<details class="group rounded-[18px] border border-white/30 bg-white/15 shadow-[inset_0_1px_0_oklch(1_0_0/0.35),0_24px_48px_oklch(0.3_0.12_290/0.35)] backdrop-blur-[18px] backdrop-saturate-150 transition-[background-color,box-shadow,backdrop-filter] duration-350 open:bg-white/25 open:shadow-[inset_0_1px_0_oklch(1_0_0/0.45),0_30px_60px_oklch(0.3_0.12_290/0.45)] open:backdrop-blur-[26px] open:backdrop-saturate-[1.8]">
<summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-5 py-4 text-[15.5px] font-semibold tracking-[-0.01em] text-white [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.55)] focus-visible:rounded-[18px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-white [&::-webkit-details-marker]:hidden">Which locations are open 24/7?
<span aria-hidden="true" class="grid size-7 shrink-0 place-items-center rounded-full border border-white/40 transition-[rotate,background-color] duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] group-hover:bg-white/20 group-open:rotate-180 group-open:bg-white/20 motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="13" height="13"><path d="M3 6l5 5 5-5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
</summary>
<p class="max-w-[58ch] px-5 pb-4 text-[14px] leading-[1.7] text-white/90 [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.5)]">All flagship locations run 24/7 with app-based entry. Neighbourhood studios open 5am–11pm; the app map badges each one with live hours and current capacity.</p>
</details>
</div>
<p class="mt-6 font-tfa07-mono text-[11.5px] text-white/85 [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.6)]">backdrop-blur-[18px] backdrop-saturate-150 — the saturate is what makes it glass, not smear.</p>
</div>
</div>
</section>@import "tailwindcss";
@theme {
--font-tfa07-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
--font-tfa07-mono: 'JetBrains Mono', ui-monospace, monospace;
}
.tfa-07 {
width: 100%;
min-height: 100svh;
}
/* Safari < 16.4 prefix — Tailwind does not emit -webkit-backdrop-filter for arbitrary values. */
.tfa-07 details {
-webkit-backdrop-filter: blur(18px) saturate(1.5);
}
.tfa-07 details[open] {
-webkit-backdrop-filter: blur(26px) saturate(1.8);
}
/* Contrast floor where backdrop-filter is unavailable (forced colours, blocklisted GPUs). */
@supports not (backdrop-filter: blur(1px)) {
.tfa-07 details {
background: oklch(0.35 0.08 290 / 0.92);
}
.tfa-07 details[open] {
background: oklch(0.32 0.08 290 / 0.96);
}
}
.tfa-07 [data-panel] {
interpolate-size: allow-keywords;
}
@supports (interpolate-size: allow-keywords) {
.tfa-07 details::details-content {
height: 0;
overflow: clip;
opacity: 0;
transition: height .4s cubic-bezier(.4,0,.2,1), opacity .32s, content-visibility .4s allow-discrete;
}
.tfa-07 details[open]::details-content {
height: auto;
opacity: 1;
}
}
@media (prefers-reduced-motion: reduce) {
.tfa-07 details::details-content {
transition-duration: 1ms;
}
}@import "tailwindcss";
@theme {
--font-tfa07-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
--font-tfa07-mono: 'JetBrains Mono', ui-monospace, monospace;
}
.tfa-07 {
width: 100%;
min-height: 100svh;
}
/* Safari < 16.4 prefix — Tailwind does not emit -webkit-backdrop-filter for arbitrary values. */
.tfa-07 details {
-webkit-backdrop-filter: blur(18px) saturate(1.5);
}
.tfa-07 details[open] {
-webkit-backdrop-filter: blur(26px) saturate(1.8);
}
/* Contrast floor where backdrop-filter is unavailable (forced colours, blocklisted GPUs). */
@supports not (backdrop-filter: blur(1px)) {
.tfa-07 details {
background: oklch(0.35 0.08 290 / 0.92);
}
.tfa-07 details[open] {
background: oklch(0.32 0.08 290 / 0.96);
}
}
.tfa-07 [data-panel] {
interpolate-size: allow-keywords;
}
@supports (interpolate-size: allow-keywords) {
.tfa-07 details::details-content {
height: 0;
overflow: clip;
opacity: 0;
transition: height .4s cubic-bezier(.4,0,.2,1), opacity .32s, content-visibility .4s allow-discrete;
}
.tfa-07 details[open]::details-content {
height: auto;
opacity: 1;
}
}
@media (prefers-reduced-motion: reduce) {
.tfa-07 details::details-content {
transition-duration: 1ms;
}
}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 {
--font-tfa07-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
--font-tfa07-mono: 'JetBrains Mono', ui-monospace, monospace;
}
.tfa-07 {
width: 100%;
min-height: 100svh;
}
/* Safari < 16.4 prefix — Tailwind does not emit -webkit-backdrop-filter for arbitrary values. */
.tfa-07 details {
-webkit-backdrop-filter: blur(18px) saturate(1.5);
}
.tfa-07 details[open] {
-webkit-backdrop-filter: blur(26px) saturate(1.8);
}
/* Contrast floor where backdrop-filter is unavailable (forced colours, blocklisted GPUs). */
@supports not (backdrop-filter: blur(1px)) {
.tfa-07 details {
background: oklch(0.35 0.08 290 / 0.92);
}
.tfa-07 details[open] {
background: oklch(0.32 0.08 290 / 0.96);
}
}
.tfa-07 [data-panel] {
interpolate-size: allow-keywords;
}
@supports (interpolate-size: allow-keywords) {
.tfa-07 details::details-content {
height: 0;
overflow: clip;
opacity: 0;
transition: height .4s cubic-bezier(.4,0,.2,1), opacity .32s, content-visibility .4s allow-discrete;
}
.tfa-07 details[open]::details-content {
height: auto;
opacity: 1;
}
}
@media (prefers-reduced-motion: reduce) {
.tfa-07 details::details-content {
transition-duration: 1ms;
}
}@import "tailwindcss";
@theme {
--font-tfa07-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
--font-tfa07-mono: 'JetBrains Mono', ui-monospace, monospace;
}
.tfa-07 {
width: 100%;
min-height: 100svh;
}
/* Safari < 16.4 prefix — Tailwind does not emit -webkit-backdrop-filter for arbitrary values. */
.tfa-07 details {
-webkit-backdrop-filter: blur(18px) saturate(1.5);
}
.tfa-07 details[open] {
-webkit-backdrop-filter: blur(26px) saturate(1.8);
}
/* Contrast floor where backdrop-filter is unavailable (forced colours, blocklisted GPUs). */
@supports not (backdrop-filter: blur(1px)) {
.tfa-07 details {
background: oklch(0.35 0.08 290 / 0.92);
}
.tfa-07 details[open] {
background: oklch(0.32 0.08 290 / 0.96);
}
}
.tfa-07 [data-panel] {
interpolate-size: allow-keywords;
}
@supports (interpolate-size: allow-keywords) {
.tfa-07 details::details-content {
height: 0;
overflow: clip;
opacity: 0;
transition: height .4s cubic-bezier(.4,0,.2,1), opacity .32s, content-visibility .4s allow-discrete;
}
.tfa-07 details[open]::details-content {
height: auto;
opacity: 1;
}
}
@media (prefers-reduced-motion: reduce) {
.tfa-07 details::details-content {
transition-duration: 1ms;
}
}<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=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500&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=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap">What changed in the port
Which parts became utilities, which stayed CSS, and why.
- All four glass layers are utilities, including the composite inset-plus-lift
shadow-[...]— a comma-separated shadow list survives the arbitrary-value syntax as long as every internal space is an underscore. That is the single most useful thing to know about porting effect-heavy CSS. open:backdrop-blur-[26px]is the port's neatest trick: the CSS version needed a duplicatedbackdrop-filterdeclaration plus its-webkit-twin in a separate[open]rule. Only the prefix shim survives.- The negated
@supportsstayed in CSS on purpose.supports-[...]:exists, but inverting a feature query across two states costs more than it saves. - UI upgrade from the CSS original: answer copy went from a muted token at
oklch(0.93)to full-opacity white at 90% plus a per-element text-shadow. Over the busiest region of the photo the original measured near 3.9:1; this holds above 4.5:1 everywhere. - UI upgrade: the chevron ring now reacts to
group-hover:as well asgroup-open:, so the whole row has a pointer affordance — the original hovered the icon only, which missed the row's padding.
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 Glassmorphism FAQ Accordion with Frosted Backdrop Blur
Source: https://codefronts.com/snippets/tailwind-css-faq-accordion/tailwind-glassmorphism-faq-accordion-frosted-blur/
Frosted-glass panels floating over a photographic backdrop. Tailwind has utilities for all four glass layers — the tint, backdrop-blur-[18px] backdrop-saturate-150, a translucent border and an inset highlight inside shadow-[...] — so the whole material is a class list, and the open state simply frosts deeper. Includes the two rules most glassmorphism tutorials miss: the saturation boost and the top-edge highlight.
## HTML
```html
<section class="tfa-07 w-full min-h-svh font-tfa07-sans">
<div class="grid min-h-svh w-full place-items-center bg-[linear-gradient(160deg,oklch(0.45_0.2_290/0.55),oklch(0.5_0.22_340/0.35)_55%,oklch(0.55_0.18_240/0.5)),url('https://images.unsplash.com/photo-1518098268026-4e89f1a2cd8e?q=80&w=1800&auto=format&fit=crop')] bg-cover bg-center px-5 py-12">
<div class="w-[min(620px,100%)]">
<header>
<h1 class="text-[clamp(30px,5vw,42px)] font-extrabold leading-[1.06] tracking-[-0.025em] text-white [text-shadow:0_2px_24px_oklch(0.2_0.08_290/0.6)]">Membership FAQ</h1>
<p class="mt-3 max-w-[52ch] text-[14.5px] leading-relaxed text-white/90 [text-shadow:0_1px_12px_oklch(0.2_0.08_290/0.65)]">Four layers make the glass: tint, frost, edge, highlight. The open panel frosts deeper — no accent colour needed.</p>
</header>
<div data-panel class="mt-7 flex flex-col gap-3">
<details class="group rounded-[18px] border border-white/30 bg-white/15 shadow-[inset_0_1px_0_oklch(1_0_0/0.35),0_24px_48px_oklch(0.3_0.12_290/0.35)] backdrop-blur-[18px] backdrop-saturate-150 transition-[background-color,box-shadow,backdrop-filter] duration-350 open:bg-white/25 open:shadow-[inset_0_1px_0_oklch(1_0_0/0.45),0_30px_60px_oklch(0.3_0.12_290/0.45)] open:backdrop-blur-[26px] open:backdrop-saturate-[1.8]" open>
<summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-5 py-4 text-[15.5px] font-semibold tracking-[-0.01em] text-white [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.55)] focus-visible:rounded-[18px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-white [&::-webkit-details-marker]:hidden">What does membership include?
<span aria-hidden="true" class="grid size-7 shrink-0 place-items-center rounded-full border border-white/40 transition-[rotate,background-color] duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] group-hover:bg-white/20 group-open:rotate-180 group-open:bg-white/20 motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="13" height="13"><path d="M3 6l5 5 5-5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
</summary>
<p class="max-w-[58ch] px-5 pb-4 text-[14px] leading-[1.7] text-white/90 [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.5)]">Unlimited access to every studio location, all live classes, and the on-demand library. Founding members also lock their rate for life — it never increases while the membership stays active.</p>
</details>
<details class="group rounded-[18px] border border-white/30 bg-white/15 shadow-[inset_0_1px_0_oklch(1_0_0/0.35),0_24px_48px_oklch(0.3_0.12_290/0.35)] backdrop-blur-[18px] backdrop-saturate-150 transition-[background-color,box-shadow,backdrop-filter] duration-350 open:bg-white/25 open:shadow-[inset_0_1px_0_oklch(1_0_0/0.45),0_30px_60px_oklch(0.3_0.12_290/0.45)] open:backdrop-blur-[26px] open:backdrop-saturate-[1.8]">
<summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-5 py-4 text-[15.5px] font-semibold tracking-[-0.01em] text-white [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.55)] focus-visible:rounded-[18px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-white [&::-webkit-details-marker]:hidden">Can I freeze my membership?
<span aria-hidden="true" class="grid size-7 shrink-0 place-items-center rounded-full border border-white/40 transition-[rotate,background-color] duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] group-hover:bg-white/20 group-open:rotate-180 group-open:bg-white/20 motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="13" height="13"><path d="M3 6l5 5 5-5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
</summary>
<p class="max-w-[58ch] px-5 pb-4 text-[14px] leading-[1.7] text-white/90 [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.5)]">Yes — up to 3 months per year, in one-month blocks, straight from the app. Frozen months push your renewal date back, so you never pay for time you cannot use.</p>
</details>
<details class="group rounded-[18px] border border-white/30 bg-white/15 shadow-[inset_0_1px_0_oklch(1_0_0/0.35),0_24px_48px_oklch(0.3_0.12_290/0.35)] backdrop-blur-[18px] backdrop-saturate-150 transition-[background-color,box-shadow,backdrop-filter] duration-350 open:bg-white/25 open:shadow-[inset_0_1px_0_oklch(1_0_0/0.45),0_30px_60px_oklch(0.3_0.12_290/0.45)] open:backdrop-blur-[26px] open:backdrop-saturate-[1.8]">
<summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-5 py-4 text-[15.5px] font-semibold tracking-[-0.01em] text-white [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.55)] focus-visible:rounded-[18px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-white [&::-webkit-details-marker]:hidden">Do you offer day passes for guests?
<span aria-hidden="true" class="grid size-7 shrink-0 place-items-center rounded-full border border-white/40 transition-[rotate,background-color] duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] group-hover:bg-white/20 group-open:rotate-180 group-open:bg-white/20 motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="13" height="13"><path d="M3 6l5 5 5-5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
</summary>
<p class="max-w-[58ch] px-5 pb-4 text-[14px] leading-[1.7] text-white/90 [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.5)]">Every member gets 2 free guest passes a month. Additional passes are $15, and guests who join within 7 days get their pass credited toward the first month.</p>
</details>
<details class="group rounded-[18px] border border-white/30 bg-white/15 shadow-[inset_0_1px_0_oklch(1_0_0/0.35),0_24px_48px_oklch(0.3_0.12_290/0.35)] backdrop-blur-[18px] backdrop-saturate-150 transition-[background-color,box-shadow,backdrop-filter] duration-350 open:bg-white/25 open:shadow-[inset_0_1px_0_oklch(1_0_0/0.45),0_30px_60px_oklch(0.3_0.12_290/0.45)] open:backdrop-blur-[26px] open:backdrop-saturate-[1.8]">
<summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-5 py-4 text-[15.5px] font-semibold tracking-[-0.01em] text-white [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.55)] focus-visible:rounded-[18px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-white [&::-webkit-details-marker]:hidden">Which locations are open 24/7?
<span aria-hidden="true" class="grid size-7 shrink-0 place-items-center rounded-full border border-white/40 transition-[rotate,background-color] duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] group-hover:bg-white/20 group-open:rotate-180 group-open:bg-white/20 motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="13" height="13"><path d="M3 6l5 5 5-5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
</summary>
<p class="max-w-[58ch] px-5 pb-4 text-[14px] leading-[1.7] text-white/90 [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.5)]">All flagship locations run 24/7 with app-based entry. Neighbourhood studios open 5am–11pm; the app map badges each one with live hours and current capacity.</p>
</details>
</div>
<p class="mt-6 font-tfa07-mono text-[11.5px] text-white/85 [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.6)]">backdrop-blur-[18px] backdrop-saturate-150 — the saturate is what makes it glass, not smear.</p>
</div>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--font-tfa07-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
--font-tfa07-mono: 'JetBrains Mono', ui-monospace, monospace;
}
.tfa-07 {
width: 100%;
min-height: 100svh;
}
/* Safari < 16.4 prefix — Tailwind does not emit -webkit-backdrop-filter for arbitrary values. */
.tfa-07 details {
-webkit-backdrop-filter: blur(18px) saturate(1.5);
}
.tfa-07 details[open] {
-webkit-backdrop-filter: blur(26px) saturate(1.8);
}
/* Contrast floor where backdrop-filter is unavailable (forced colours, blocklisted GPUs). */
@supports not (backdrop-filter: blur(1px)) {
.tfa-07 details {
background: oklch(0.35 0.08 290 / 0.92);
}
.tfa-07 details[open] {
background: oklch(0.32 0.08 290 / 0.96);
}
}
.tfa-07 [data-panel] {
interpolate-size: allow-keywords;
}
@supports (interpolate-size: allow-keywords) {
.tfa-07 details::details-content {
height: 0;
overflow: clip;
opacity: 0;
transition: height .4s cubic-bezier(.4,0,.2,1), opacity .32s, content-visibility .4s allow-discrete;
}
.tfa-07 details[open]::details-content {
height: auto;
opacity: 1;
}
}
@media (prefers-reduced-motion: reduce) {
.tfa-07 details::details-content {
transition-duration: 1ms;
}
}
```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 Glassmorphism FAQ Accordion with Frosted Backdrop Blur
Source: https://codefronts.com/snippets/tailwind-css-faq-accordion/tailwind-glassmorphism-faq-accordion-frosted-blur/
Frosted-glass panels floating over a photographic backdrop. Tailwind has utilities for all four glass layers — the tint, backdrop-blur-[18px] backdrop-saturate-150, a translucent border and an inset highlight inside shadow-[...] — so the whole material is a class list, and the open state simply frosts deeper. Includes the two rules most glassmorphism tutorials miss: the saturation boost and the top-edge highlight.
## HTML
```html
<section class="tfa-07 w-full min-h-svh font-tfa07-sans">
<div class="grid min-h-svh w-full place-items-center bg-[linear-gradient(160deg,oklch(0.45_0.2_290/0.55),oklch(0.5_0.22_340/0.35)_55%,oklch(0.55_0.18_240/0.5)),url('https://images.unsplash.com/photo-1518098268026-4e89f1a2cd8e?q=80&w=1800&auto=format&fit=crop')] bg-cover bg-center px-5 py-12">
<div class="w-[min(620px,100%)]">
<header>
<h1 class="text-[clamp(30px,5vw,42px)] font-extrabold leading-[1.06] tracking-[-0.025em] text-white [text-shadow:0_2px_24px_oklch(0.2_0.08_290/0.6)]">Membership FAQ</h1>
<p class="mt-3 max-w-[52ch] text-[14.5px] leading-relaxed text-white/90 [text-shadow:0_1px_12px_oklch(0.2_0.08_290/0.65)]">Four layers make the glass: tint, frost, edge, highlight. The open panel frosts deeper — no accent colour needed.</p>
</header>
<div data-panel class="mt-7 flex flex-col gap-3">
<details class="group rounded-[18px] border border-white/30 bg-white/15 shadow-[inset_0_1px_0_oklch(1_0_0/0.35),0_24px_48px_oklch(0.3_0.12_290/0.35)] backdrop-blur-[18px] backdrop-saturate-150 transition-[background-color,box-shadow,backdrop-filter] duration-350 open:bg-white/25 open:shadow-[inset_0_1px_0_oklch(1_0_0/0.45),0_30px_60px_oklch(0.3_0.12_290/0.45)] open:backdrop-blur-[26px] open:backdrop-saturate-[1.8]" open>
<summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-5 py-4 text-[15.5px] font-semibold tracking-[-0.01em] text-white [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.55)] focus-visible:rounded-[18px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-white [&::-webkit-details-marker]:hidden">What does membership include?
<span aria-hidden="true" class="grid size-7 shrink-0 place-items-center rounded-full border border-white/40 transition-[rotate,background-color] duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] group-hover:bg-white/20 group-open:rotate-180 group-open:bg-white/20 motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="13" height="13"><path d="M3 6l5 5 5-5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
</summary>
<p class="max-w-[58ch] px-5 pb-4 text-[14px] leading-[1.7] text-white/90 [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.5)]">Unlimited access to every studio location, all live classes, and the on-demand library. Founding members also lock their rate for life — it never increases while the membership stays active.</p>
</details>
<details class="group rounded-[18px] border border-white/30 bg-white/15 shadow-[inset_0_1px_0_oklch(1_0_0/0.35),0_24px_48px_oklch(0.3_0.12_290/0.35)] backdrop-blur-[18px] backdrop-saturate-150 transition-[background-color,box-shadow,backdrop-filter] duration-350 open:bg-white/25 open:shadow-[inset_0_1px_0_oklch(1_0_0/0.45),0_30px_60px_oklch(0.3_0.12_290/0.45)] open:backdrop-blur-[26px] open:backdrop-saturate-[1.8]">
<summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-5 py-4 text-[15.5px] font-semibold tracking-[-0.01em] text-white [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.55)] focus-visible:rounded-[18px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-white [&::-webkit-details-marker]:hidden">Can I freeze my membership?
<span aria-hidden="true" class="grid size-7 shrink-0 place-items-center rounded-full border border-white/40 transition-[rotate,background-color] duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] group-hover:bg-white/20 group-open:rotate-180 group-open:bg-white/20 motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="13" height="13"><path d="M3 6l5 5 5-5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
</summary>
<p class="max-w-[58ch] px-5 pb-4 text-[14px] leading-[1.7] text-white/90 [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.5)]">Yes — up to 3 months per year, in one-month blocks, straight from the app. Frozen months push your renewal date back, so you never pay for time you cannot use.</p>
</details>
<details class="group rounded-[18px] border border-white/30 bg-white/15 shadow-[inset_0_1px_0_oklch(1_0_0/0.35),0_24px_48px_oklch(0.3_0.12_290/0.35)] backdrop-blur-[18px] backdrop-saturate-150 transition-[background-color,box-shadow,backdrop-filter] duration-350 open:bg-white/25 open:shadow-[inset_0_1px_0_oklch(1_0_0/0.45),0_30px_60px_oklch(0.3_0.12_290/0.45)] open:backdrop-blur-[26px] open:backdrop-saturate-[1.8]">
<summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-5 py-4 text-[15.5px] font-semibold tracking-[-0.01em] text-white [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.55)] focus-visible:rounded-[18px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-white [&::-webkit-details-marker]:hidden">Do you offer day passes for guests?
<span aria-hidden="true" class="grid size-7 shrink-0 place-items-center rounded-full border border-white/40 transition-[rotate,background-color] duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] group-hover:bg-white/20 group-open:rotate-180 group-open:bg-white/20 motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="13" height="13"><path d="M3 6l5 5 5-5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
</summary>
<p class="max-w-[58ch] px-5 pb-4 text-[14px] leading-[1.7] text-white/90 [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.5)]">Every member gets 2 free guest passes a month. Additional passes are $15, and guests who join within 7 days get their pass credited toward the first month.</p>
</details>
<details class="group rounded-[18px] border border-white/30 bg-white/15 shadow-[inset_0_1px_0_oklch(1_0_0/0.35),0_24px_48px_oklch(0.3_0.12_290/0.35)] backdrop-blur-[18px] backdrop-saturate-150 transition-[background-color,box-shadow,backdrop-filter] duration-350 open:bg-white/25 open:shadow-[inset_0_1px_0_oklch(1_0_0/0.45),0_30px_60px_oklch(0.3_0.12_290/0.45)] open:backdrop-blur-[26px] open:backdrop-saturate-[1.8]">
<summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-5 py-4 text-[15.5px] font-semibold tracking-[-0.01em] text-white [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.55)] focus-visible:rounded-[18px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-white [&::-webkit-details-marker]:hidden">Which locations are open 24/7?
<span aria-hidden="true" class="grid size-7 shrink-0 place-items-center rounded-full border border-white/40 transition-[rotate,background-color] duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] group-hover:bg-white/20 group-open:rotate-180 group-open:bg-white/20 motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="13" height="13"><path d="M3 6l5 5 5-5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
</summary>
<p class="max-w-[58ch] px-5 pb-4 text-[14px] leading-[1.7] text-white/90 [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.5)]">All flagship locations run 24/7 with app-based entry. Neighbourhood studios open 5am–11pm; the app map badges each one with live hours and current capacity.</p>
</details>
</div>
<p class="mt-6 font-tfa07-mono text-[11.5px] text-white/85 [text-shadow:0_1px_10px_oklch(0.2_0.08_290/0.6)]">backdrop-blur-[18px] backdrop-saturate-150 — the saturate is what makes it glass, not smear.</p>
</div>
</div>
</section>
```
## CSS
```css
@import "tailwindcss";
@theme {
--font-tfa07-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
--font-tfa07-mono: 'JetBrains Mono', ui-monospace, monospace;
}
.tfa-07 {
width: 100%;
min-height: 100svh;
}
/* Safari < 16.4 prefix — Tailwind does not emit -webkit-backdrop-filter for arbitrary values. */
.tfa-07 details {
-webkit-backdrop-filter: blur(18px) saturate(1.5);
}
.tfa-07 details[open] {
-webkit-backdrop-filter: blur(26px) saturate(1.8);
}
/* Contrast floor where backdrop-filter is unavailable (forced colours, blocklisted GPUs). */
@supports not (backdrop-filter: blur(1px)) {
.tfa-07 details {
background: oklch(0.35 0.08 290 / 0.92);
}
.tfa-07 details[open] {
background: oklch(0.32 0.08 290 / 0.96);
}
}
.tfa-07 [data-panel] {
interpolate-size: allow-keywords;
}
@supports (interpolate-size: allow-keywords) {
.tfa-07 details::details-content {
height: 0;
overflow: clip;
opacity: 0;
transition: height .4s cubic-bezier(.4,0,.2,1), opacity .32s, content-visibility .4s allow-discrete;
}
.tfa-07 details[open]::details-content {
height: auto;
opacity: 1;
}
}
@media (prefers-reduced-motion: reduce) {
.tfa-07 details::details-content {
transition-duration: 1ms;
}
}
```How this works
Real glass is four layers, not one blur, and each one is a utility: a white tint at 15%, backdrop-blur-[18px] backdrop-saturate-150, a border-white/30 edge, and a composite shadow-[inset_0_1px_0_...,0_24px_48px_...] carrying both the bevel highlight and the lift.
saturate is the difference between glass and mud: blur averages the backdrop toward grey, so you re-boost the colour passing through. The inset 1px white line is light catching the top edge — delete it and the panel goes flat. The lift shadow is tinted with the scene's hue rather than black, which is how shadows behave over colourful backgrounds.
State through material. A deeper tint and a heavier blur on open:, and nothing else — the glass itself communicates, which is why this demo has no accent token.
What stays CSS. The @supports not (backdrop-filter: …) fallback: Tailwind has a supports-[...]: variant, but inverting a feature query across two states would mean four extra variants in two class lists to express three lines. That is a judgement call, and it is the only one in this demo.
Make it yours
- Scene: one background-image utility on the stage. Any busy, colourful image works — glass over flat colour is boring by definition.
- Frost strength:
backdrop-blur-[18px]and the tint alpha are the two dials; heavy blur + low tint reads iOS, light blur + higher tint reads Windows. - Dark glass: a black tint at 25% with a 15% white border and a lower inset-highlight alpha — same four layers.
- Performance: blur cost scales with area. Keep it on cards, never on the full page background.
Gotchas — read before shipping
- Text on glass must clear WCAG against the WORST part of the backdrop, not the average. That is why the tint rises when open and why the copy carries a text-shadow.
backdrop-filtersamples only what is behind the element; a parent withoverflow-hiddenplus a radius can clip the sampled region on some engines. Keep the radius on the glass element itself, as here.- Nested glass double-blurs and destroys GPU time on low-end devices — one glass layer per stack.
- Safari below 16.4 needs the
-webkit-prefix, which Tailwind does not emit for arbitrarybackdrop-*values: the one-line shim is in the stylesheet.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 129+ | not yet | not yet | 129+ |
Floor set by oklch(), backdrop-filter, interpolate-size as this demo is written. The core technique itself goes back further — Chrome 76+.
backdrop-filter is long settled; the @supports fallback covers forced-colours modes and GPU-blocklisted devices. Tailwind v4's own floor still applies to the generated sheet.