25 Tailwind CSS FAQ Accordion
07 / 25

All 25 in 25 Tailwind CSS FAQ Accordion

  1. 01Tailwind Peer-Checked FAQ Accordion with No JavaScript
  2. 02Tailwind Native Details/Summary FAQ with Custom Styled Icons
  3. 03Tailwind Exclusive Accordion — Only One FAQ Open at a Time
  4. 04Tailwind Multi-Open FAQ Accordion with a Live CSS Counter
  5. 05Tailwind CSS FAQ Accordion Template (Free, Copy-Paste)
  6. 06Tailwind Dark Mode FAQ Accordion with light-dark() and No .dark Class
  7. 07Tailwind Glassmorphism FAQ Accordion with Frosted Backdrop Blur
  8. 08Tailwind Minimalist E-Commerce FAQ Accordion for Product Pages
  9. 09Tailwind Neumorphic Soft-UI FAQ Accordion Cards
  10. 10Tailwind Animate Height Auto FAQ with grid-rows 0fr to 1fr
  11. 11Tailwind FAQ Chevron Rotate 180 Degrees on Toggle
  12. 12Tailwind Animated Plus to Minus Icon Morph FAQ Accordion
  13. 13Tailwind Spring Bounce FAQ Accordion with linear() Easing
  14. 14Tailwind Two-Column FAQ Accordion Grid with Independent Columns
  15. 15Tailwind Horizontal FAQ Accordion with Sideways Expanding Panels
  16. 16Tailwind Categorised FAQ Help Centre with a Sticky Sidebar Menu
  17. 17Tailwind Card-Style FAQ Panels with a Layered Shadow Elevation System
  18. 18Tailwind FAQ Accordion with a Live Search Bar Filter
  19. 19Tailwind Expand All and Collapse All FAQ Accordion Buttons
  20. 20Tailwind FAQ with a Still Have Questions Contact CTA Card
  21. 21Tailwind Accessible ARIA FAQ Accordion with Keyboard Navigation
  22. 22Tailwind FAQ with FAQPage JSON-LD Schema for Rich Snippets and AI Search
  23. 23Bootstrap 5 Accordion Rebuilt in Tailwind (and the JavaScript You Delete)
  24. 24Tailwind FAQ Component in React, Vue, Svelte and Astro (One Port Recipe)
  25. 25Tailwind FAQ with Voice Search Using the Speech Recognition API
Tailwind v4MIT licensed

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.

Live Demo
Plain CSSTailwind v4
Try it

Complete Tailwind CSS landing page templates in HTML, React, Next.js and Vue · from $49

Cruip · Affiliate link

Browse Cruip templates

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

1Load Tailwind
<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.

2Add the stylesheetRequiredthe @theme block is what makes the custom utilities exist
@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;
  }
}
3Fonts used by this demooptional — skip if you have your own type stack
<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 duplicated backdrop-filter declaration plus its -webkit- twin in a separate [open] rule. Only the prefix shim survives.
  • The negated @supports stayed 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 as group-open:, so the whole row has a pointer affordance — the original hovered the icon only, which missed the row's padding.
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
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-filter samples only what is behind the element; a parent with overflow-hidden plus 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 arbitrary backdrop-* values: the one-line shim is in the stylesheet.

Browser support

ChromeSafariFirefoxEdge
129+not yetnot yet129+

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.

Techniques used in this demo

Utilitiesfirst-class utility or variant

Search CodeFronts

Loading…