Tailwind v4MIT licensed

Tailwind Liquid Glass Accordion

An FAQ where each panel is a glass card that opens fluidly — the 0fr → 1fr grid trick, written as two utilities. It is the cleanest answer to 'you cannot animate height:auto', it needs no JavaScript, and on native <details> the keyboard and screen-reader behaviour is already correct.

Live Demo
Plain CSSTailwind v4
Try it

Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time

Untitled UI React · Affiliate link

Get Untitled UI Pro

The code

<section class="lgt-16 grid w-full min-h-svh place-items-center p-15 font-lgt16-sans bg-[image:url('https://picsum.photos/seed/lgfaq/1100/800')] bg-cover bg-center bg-fixed" aria-label="Tailwind liquid glass FAQ accordion">
  <div class="flex w-[min(560px,94vw)] flex-col gap-3.5">

    <details open class="group overflow-hidden rounded-[18px] border border-white/28 bg-white/10 backdrop-blur-[18px] backdrop-saturate-170 shadow-[inset_0_1px_0_rgba(255,255,255,.4),0_16px_34px_-22px_rgba(0,0,0,.6)] transition-colors duration-300 open:border-white/50">
      <summary class="flex cursor-pointer list-none items-center justify-between gap-4 px-5 py-4.5 text-base font-bold text-white focus-visible:outline-3 focus-visible:-outline-offset-3 focus-visible:outline-white [&amp;::-webkit-details-marker]:hidden">
        What is Liquid Glass?
        <span aria-hidden="true" class="relative size-5 flex-none before:absolute before:top-1/2 before:left-1/2 before:h-0.5 before:w-3.5 before:-translate-x-1/2 before:-translate-y-1/2 before:bg-white after:absolute after:top-1/2 after:left-1/2 after:h-0.5 after:w-3.5 after:-translate-x-1/2 after:-translate-y-1/2 after:rotate-90 after:bg-white after:transition-transform after:duration-300 group-open:after:rotate-0 motion-reduce:after:transition-none"></span>
      </summary>
      <div class="grid grid-rows-[0fr] transition-[grid-template-rows] duration-350 ease-out group-open:grid-rows-[1fr] motion-reduce:transition-none">
        <div class="overflow-hidden"><p class="px-5 pb-5 text-[15px] leading-relaxed text-white/90">A translucent material that samples and refracts what's behind it &mdash; frosted blur plus specular light and, at its richest, real SVG displacement. It's the design language Apple introduced at WWDC 2025.</p></div>
      </div>
    </details>

    <details class="group overflow-hidden rounded-[18px] border border-white/28 bg-white/10 backdrop-blur-[18px] backdrop-saturate-170 shadow-[inset_0_1px_0_rgba(255,255,255,.4),0_16px_34px_-22px_rgba(0,0,0,.6)] transition-colors duration-300 open:border-white/50">
      <summary class="flex cursor-pointer list-none items-center justify-between gap-4 px-5 py-4.5 text-base font-bold text-white focus-visible:outline-3 focus-visible:-outline-offset-3 focus-visible:outline-white [&amp;::-webkit-details-marker]:hidden">
        Is it good for performance?
        <span aria-hidden="true" class="relative size-5 flex-none before:absolute before:top-1/2 before:left-1/2 before:h-0.5 before:w-3.5 before:-translate-x-1/2 before:-translate-y-1/2 before:bg-white after:absolute after:top-1/2 after:left-1/2 after:h-0.5 after:w-3.5 after:-translate-x-1/2 after:-translate-y-1/2 after:rotate-90 after:bg-white after:transition-transform after:duration-300 group-open:after:rotate-0 motion-reduce:after:transition-none"></span>
      </summary>
      <div class="grid grid-rows-[0fr] transition-[grid-template-rows] duration-350 ease-out group-open:grid-rows-[1fr] motion-reduce:transition-none">
        <div class="overflow-hidden"><p class="px-5 pb-5 text-[15px] leading-relaxed text-white/90">Yes, when disciplined: animate transform, opacity and filter only, cap blur radii, isolate paint with <code>isolate</code>, and reserve boxes so layout shift stays at zero. This demo ships no JavaScript at all.</p></div>
      </div>
    </details>

    <details class="group overflow-hidden rounded-[18px] border border-white/28 bg-white/10 backdrop-blur-[18px] backdrop-saturate-170 shadow-[inset_0_1px_0_rgba(255,255,255,.4),0_16px_34px_-22px_rgba(0,0,0,.6)] transition-colors duration-300 open:border-white/50">
      <summary class="flex cursor-pointer list-none items-center justify-between gap-4 px-5 py-4.5 text-base font-bold text-white focus-visible:outline-3 focus-visible:-outline-offset-3 focus-visible:outline-white [&amp;::-webkit-details-marker]:hidden">
        Is it accessible?
        <span aria-hidden="true" class="relative size-5 flex-none before:absolute before:top-1/2 before:left-1/2 before:h-0.5 before:w-3.5 before:-translate-x-1/2 before:-translate-y-1/2 before:bg-white after:absolute after:top-1/2 after:left-1/2 after:h-0.5 after:w-3.5 after:-translate-x-1/2 after:-translate-y-1/2 after:rotate-90 after:bg-white after:transition-transform after:duration-300 group-open:after:rotate-0 motion-reduce:after:transition-none"></span>
      </summary>
      <div class="grid grid-rows-[0fr] transition-[grid-template-rows] duration-350 ease-out group-open:grid-rows-[1fr] motion-reduce:transition-none">
        <div class="overflow-hidden"><p class="px-5 pb-5 text-[15px] leading-relaxed text-white/90">Built on native details/summary, so keyboard toggling and disclosure semantics come free. Keep text on a solid-enough tint to hold WCAG contrast over busy backdrops.</p></div>
      </div>
    </details>

    <details class="group overflow-hidden rounded-[18px] border border-white/28 bg-white/10 backdrop-blur-[18px] backdrop-saturate-170 shadow-[inset_0_1px_0_rgba(255,255,255,.4),0_16px_34px_-22px_rgba(0,0,0,.6)] transition-colors duration-300 open:border-white/50">
      <summary class="flex cursor-pointer list-none items-center justify-between gap-4 px-5 py-4.5 text-base font-bold text-white focus-visible:outline-3 focus-visible:-outline-offset-3 focus-visible:outline-white [&amp;::-webkit-details-marker]:hidden">
        How does it map to Tailwind?
        <span aria-hidden="true" class="relative size-5 flex-none before:absolute before:top-1/2 before:left-1/2 before:h-0.5 before:w-3.5 before:-translate-x-1/2 before:-translate-y-1/2 before:bg-white after:absolute after:top-1/2 after:left-1/2 after:h-0.5 after:w-3.5 after:-translate-x-1/2 after:-translate-y-1/2 after:rotate-90 after:bg-white after:transition-transform after:duration-300 group-open:after:rotate-0 motion-reduce:after:transition-none"></span>
      </summary>
      <div class="grid grid-rows-[0fr] transition-[grid-template-rows] duration-350 ease-out group-open:grid-rows-[1fr] motion-reduce:transition-none">
        <div class="overflow-hidden"><p class="px-5 pb-5 text-[15px] leading-relaxed text-white/90">Directly: <code>backdrop-blur-[18px] backdrop-saturate-170 bg-white/10 border-white/28 rounded-[18px]</code>. Colours become <code>@theme</code> entries, states become variants, and only <code>@property</code>, <code>@keyframes</code> and vendor pseudo-elements stay as CSS.</p></div>
      </div>
    </details>

  </div>
</section>
@import "tailwindcss";

@theme {
  --font-lgt16-sans: 'Manrope', system-ui, sans-serif;
}

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-lgt16-sans: 'Manrope', system-ui, sans-serif;
}
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=Manrope:wght@400;600;800&display=swap">

What changed in the port

Which parts became utilities, which stayed CSS, and why.

  • The whole height-auto animation is two utilities: grid-rows-[0fr] and group-open:grid-rows-[1fr], plus overflow-hidden on the child.
  • group on the <details> lets both the marker and the panel read the native open state — no JavaScript, no aria bookkeeping.
  • The +/&minus; marker is two pseudo-element bars; only the vertical one rotates, so a plus becomes a minus with one group-open:after:rotate-0.
  • open: (on the element) and group-open: (on descendants) are both used here, which is a good illustration of when each applies.
  • Adding a shared name attribute makes the group single-open natively — a genuine reason to stay on <details>.
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 Liquid Glass Accordion
Source: https://codefronts.com/design-styles/tailwind-liquid-glass-effects/tailwind-liquid-glass-accordion/

An FAQ where each panel is a glass card that opens fluidly &mdash; the 0fr &rarr; 1fr grid trick, written as two utilities. It is the cleanest answer to 'you cannot animate height:auto', it needs no JavaScript, and on native <details> the keyboard and screen-reader behaviour is already correct.
## HTML
```html
<section class="lgt-16 grid w-full min-h-svh place-items-center p-15 font-lgt16-sans bg-[image:url('https://picsum.photos/seed/lgfaq/1100/800')] bg-cover bg-center bg-fixed" aria-label="Tailwind liquid glass FAQ accordion">
  <div class="flex w-[min(560px,94vw)] flex-col gap-3.5">

    <details open class="group overflow-hidden rounded-[18px] border border-white/28 bg-white/10 backdrop-blur-[18px] backdrop-saturate-170 shadow-[inset_0_1px_0_rgba(255,255,255,.4),0_16px_34px_-22px_rgba(0,0,0,.6)] transition-colors duration-300 open:border-white/50">
      <summary class="flex cursor-pointer list-none items-center justify-between gap-4 px-5 py-4.5 text-base font-bold text-white focus-visible:outline-3 focus-visible:-outline-offset-3 focus-visible:outline-white [&amp;::-webkit-details-marker]:hidden">
        What is Liquid Glass?
        <span aria-hidden="true" class="relative size-5 flex-none before:absolute before:top-1/2 before:left-1/2 before:h-0.5 before:w-3.5 before:-translate-x-1/2 before:-translate-y-1/2 before:bg-white after:absolute after:top-1/2 after:left-1/2 after:h-0.5 after:w-3.5 after:-translate-x-1/2 after:-translate-y-1/2 after:rotate-90 after:bg-white after:transition-transform after:duration-300 group-open:after:rotate-0 motion-reduce:after:transition-none"></span>
      </summary>
      <div class="grid grid-rows-[0fr] transition-[grid-template-rows] duration-350 ease-out group-open:grid-rows-[1fr] motion-reduce:transition-none">
        <div class="overflow-hidden"><p class="px-5 pb-5 text-[15px] leading-relaxed text-white/90">A translucent material that samples and refracts what's behind it &mdash; frosted blur plus specular light and, at its richest, real SVG displacement. It's the design language Apple introduced at WWDC 2025.</p></div>
      </div>
    </details>

    <details class="group overflow-hidden rounded-[18px] border border-white/28 bg-white/10 backdrop-blur-[18px] backdrop-saturate-170 shadow-[inset_0_1px_0_rgba(255,255,255,.4),0_16px_34px_-22px_rgba(0,0,0,.6)] transition-colors duration-300 open:border-white/50">
      <summary class="flex cursor-pointer list-none items-center justify-between gap-4 px-5 py-4.5 text-base font-bold text-white focus-visible:outline-3 focus-visible:-outline-offset-3 focus-visible:outline-white [&amp;::-webkit-details-marker]:hidden">
        Is it good for performance?
        <span aria-hidden="true" class="relative size-5 flex-none before:absolute before:top-1/2 before:left-1/2 before:h-0.5 before:w-3.5 before:-translate-x-1/2 before:-translate-y-1/2 before:bg-white after:absolute after:top-1/2 after:left-1/2 after:h-0.5 after:w-3.5 after:-translate-x-1/2 after:-translate-y-1/2 after:rotate-90 after:bg-white after:transition-transform after:duration-300 group-open:after:rotate-0 motion-reduce:after:transition-none"></span>
      </summary>
      <div class="grid grid-rows-[0fr] transition-[grid-template-rows] duration-350 ease-out group-open:grid-rows-[1fr] motion-reduce:transition-none">
        <div class="overflow-hidden"><p class="px-5 pb-5 text-[15px] leading-relaxed text-white/90">Yes, when disciplined: animate transform, opacity and filter only, cap blur radii, isolate paint with <code>isolate</code>, and reserve boxes so layout shift stays at zero. This demo ships no JavaScript at all.</p></div>
      </div>
    </details>

    <details class="group overflow-hidden rounded-[18px] border border-white/28 bg-white/10 backdrop-blur-[18px] backdrop-saturate-170 shadow-[inset_0_1px_0_rgba(255,255,255,.4),0_16px_34px_-22px_rgba(0,0,0,.6)] transition-colors duration-300 open:border-white/50">
      <summary class="flex cursor-pointer list-none items-center justify-between gap-4 px-5 py-4.5 text-base font-bold text-white focus-visible:outline-3 focus-visible:-outline-offset-3 focus-visible:outline-white [&amp;::-webkit-details-marker]:hidden">
        Is it accessible?
        <span aria-hidden="true" class="relative size-5 flex-none before:absolute before:top-1/2 before:left-1/2 before:h-0.5 before:w-3.5 before:-translate-x-1/2 before:-translate-y-1/2 before:bg-white after:absolute after:top-1/2 after:left-1/2 after:h-0.5 after:w-3.5 after:-translate-x-1/2 after:-translate-y-1/2 after:rotate-90 after:bg-white after:transition-transform after:duration-300 group-open:after:rotate-0 motion-reduce:after:transition-none"></span>
      </summary>
      <div class="grid grid-rows-[0fr] transition-[grid-template-rows] duration-350 ease-out group-open:grid-rows-[1fr] motion-reduce:transition-none">
        <div class="overflow-hidden"><p class="px-5 pb-5 text-[15px] leading-relaxed text-white/90">Built on native details/summary, so keyboard toggling and disclosure semantics come free. Keep text on a solid-enough tint to hold WCAG contrast over busy backdrops.</p></div>
      </div>
    </details>

    <details class="group overflow-hidden rounded-[18px] border border-white/28 bg-white/10 backdrop-blur-[18px] backdrop-saturate-170 shadow-[inset_0_1px_0_rgba(255,255,255,.4),0_16px_34px_-22px_rgba(0,0,0,.6)] transition-colors duration-300 open:border-white/50">
      <summary class="flex cursor-pointer list-none items-center justify-between gap-4 px-5 py-4.5 text-base font-bold text-white focus-visible:outline-3 focus-visible:-outline-offset-3 focus-visible:outline-white [&amp;::-webkit-details-marker]:hidden">
        How does it map to Tailwind?
        <span aria-hidden="true" class="relative size-5 flex-none before:absolute before:top-1/2 before:left-1/2 before:h-0.5 before:w-3.5 before:-translate-x-1/2 before:-translate-y-1/2 before:bg-white after:absolute after:top-1/2 after:left-1/2 after:h-0.5 after:w-3.5 after:-translate-x-1/2 after:-translate-y-1/2 after:rotate-90 after:bg-white after:transition-transform after:duration-300 group-open:after:rotate-0 motion-reduce:after:transition-none"></span>
      </summary>
      <div class="grid grid-rows-[0fr] transition-[grid-template-rows] duration-350 ease-out group-open:grid-rows-[1fr] motion-reduce:transition-none">
        <div class="overflow-hidden"><p class="px-5 pb-5 text-[15px] leading-relaxed text-white/90">Directly: <code>backdrop-blur-[18px] backdrop-saturate-170 bg-white/10 border-white/28 rounded-[18px]</code>. Colours become <code>@theme</code> entries, states become variants, and only <code>@property</code>, <code>@keyframes</code> and vendor pseudo-elements stay as CSS.</p></div>
      </div>
    </details>

  </div>
</section>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --font-lgt16-sans: 'Manrope', system-ui, sans-serif;
}
```

How this works

The trick, in full: a grid container whose single row is sized 0fr collapses its child to zero height; animating that track to 1fr grows it to the content's natural height. The child needs overflow-hidden so it clips on the way. That is the entire mechanism:

<div class="grid grid-rows-[0fr] transition-[grid-template-rows]
            duration-350 group-open:grid-rows-[1fr]">
  <div class="overflow-hidden"> ... answer ... </div>
</div>

Why not max-height? Because max-height animation requires you to guess a number larger than the content, which makes the timing wrong for every panel that is shorter than the guess. The grid approach animates to the real height, always.

The marker is two pseudo-element bars. Horizontal stays; vertical rotates from 90deg to 0 on open, turning a plus into a minus. Two utilities per bar, no icon font, no SVG.

Native disclosure semantics. Enter and Space toggle, the state is exposed to assistive tech, and adding a shared name attribute to every <details> makes the group single-open with no JavaScript at all.

Make it yours

  • Make it exclusive (one open at a time) by giving every <details> the same name attribute — a native feature, no accordion library required.
  • Change the open feel with the transition duration and easing on the grid wrapper; 350ms is the point where it reads as fluid rather than slow.
  • Swap the +/&minus; marker for a chevron by replacing the two bars with a single rotated glyph.
  • Tint the open state further with group-open:bg-white/16 for a stronger active cue.
  • Add a summary description line inside the <summary>; the grid trick does not care how tall the answer is.

Gotchas — read before shipping

  • The overflow-hidden child is mandatory. Without it the content does not clip and the panel appears to jump open.
  • Animate grid-template-rows, not height or max-height — the first is exact, the others are a guess or a jank source.
  • Padding on the collapsing element leaks: keep vertical padding on the inner content and let it come along, or the closed panel keeps a few pixels of height.
  • group-open: requires group on the <details> itself, not on a wrapper div.
  • Do not replace <details> with buttons and divs to get styling freedom. You would be rebuilding disclosure semantics that already work.
  • will-change on every panel is a memory cost for no gain — if you use it at all, scope it to the open one.

Browser support

ChromeSafariFirefoxEdge
111+16.4+128+111+

details/summary is universal; animating grid-template-rows needs Chrome 107+, Safari 16+ and Firefox 66+, degrading to an instant open where unsupported. Tailwind v4's sheet sets the overall floor.

Techniques used in this demo

HTML & JSno Tailwind involved

Search CodeFronts

Loading…