25 Tailwind CSS FAQ Accordion
02 / 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 Native Details/Summary FAQ with Custom Styled Icons

The most semantic FAQ possible, in utilities: native <details>/<summary> for behaviour, group-open: for every open-state style, and the marker killed by list-none [&::-webkit-details-marker]:hidden. The height-to-auto animation is the one thing utilities cannot reach, so it stays four lines of @supports CSS — enhancing every accordion on the page at once. Styled as a warm editorial help page.

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-02 w-full min-h-svh grid place-items-center bg-tfa02-bg font-tfa02-sans text-tfa02-ink px-5 py-12">
  <div class="w-[min(660px,100%)]">
    <header>
      <h1 class="font-tfa02-serif text-[clamp(32px,6vw,46px)] font-semibold leading-[1.05] tracking-[-0.02em]">Help &amp; support</h1>
      <p class="mt-3 max-w-[56ch] text-[14.5px] leading-[1.7] text-tfa02-mut">Built on native <code class="rounded bg-tfa02-code px-1.5 py-0.5 font-tfa02-mono text-[0.85em] text-tfa02-acc">&lt;details&gt;</code> — keyboard support, screen-reader semantics and find-in-page expansion come free. Try <kbd class="rounded-md border border-b-2 border-tfa02-edge bg-white px-1.5 py-0.5 font-tfa02-mono text-[0.82em]">Ctrl</kbd>+<kbd class="rounded-md border border-b-2 border-tfa02-edge bg-white px-1.5 py-0.5 font-tfa02-mono text-[0.82em]">F</kbd> for “passport”.</p>
    </header>

    <div data-panel class="mt-9 border-t border-tfa02-edge">
      <details class="group border-b border-tfa02-edge open:border-tfa02-accedge" open>
        <summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-1 py-5 font-tfa02-serif text-[19px] font-semibold tracking-[-0.01em] transition-colors duration-200 hover:text-tfa02-acc focus-visible:rounded-lg focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tfa02-acc [&::-webkit-details-marker]:hidden">
          How long does delivery take?
          <span aria-hidden="true" class="grid size-8 shrink-0 place-items-center rounded-full border border-tfa02-edge text-tfa02-acc transition-[transform,background-color,border-color] duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] group-hover:border-tfa02-accedge group-open:-rotate-180 group-open:border-tfa02-accedge group-open:bg-tfa02-code motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="14" height="14"><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-1 pb-6 pt-0.5 text-[14.5px] leading-[1.75] text-tfa02-mut">Standard delivery is 3–5 business days across the US, UK, Canada and Australia. Express (1–2 days) is available at checkout, and every order gets a tracked link the moment it leaves the warehouse.</p>
      </details>

      <details class="group border-b border-tfa02-edge open:border-tfa02-accedge">
        <summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-1 py-5 font-tfa02-serif text-[19px] font-semibold tracking-[-0.01em] transition-colors duration-200 hover:text-tfa02-acc focus-visible:rounded-lg focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tfa02-acc [&::-webkit-details-marker]:hidden">
          Do I need a passport copy to book?
          <span aria-hidden="true" class="grid size-8 shrink-0 place-items-center rounded-full border border-tfa02-edge text-tfa02-acc transition-[transform,background-color,border-color] duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] group-hover:border-tfa02-accedge group-open:-rotate-180 group-open:border-tfa02-accedge group-open:bg-tfa02-code motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="14" height="14"><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-1 pb-6 pt-0.5 text-[14.5px] leading-[1.75] text-tfa02-mut">Only for international itineraries. Upload a photo of the ID page once and we auto-fill every future booking — the file is encrypted at rest and deleted 30 days after your trip ends.</p>
      </details>

      <details class="group border-b border-tfa02-edge open:border-tfa02-accedge">
        <summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-1 py-5 font-tfa02-serif text-[19px] font-semibold tracking-[-0.01em] transition-colors duration-200 hover:text-tfa02-acc focus-visible:rounded-lg focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tfa02-acc [&::-webkit-details-marker]:hidden">
          Can I change my order after placing it?
          <span aria-hidden="true" class="grid size-8 shrink-0 place-items-center rounded-full border border-tfa02-edge text-tfa02-acc transition-[transform,background-color,border-color] duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] group-hover:border-tfa02-accedge group-open:-rotate-180 group-open:border-tfa02-accedge group-open:bg-tfa02-code motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="14" height="14"><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-1 pb-6 pt-0.5 text-[14.5px] leading-[1.75] text-tfa02-mut">Yes — orders can be edited for 60 minutes after checkout from your account page. After that the warehouse has it, but you can always refuse delivery or start a free return.</p>
      </details>

      <details class="group border-b border-tfa02-edge open:border-tfa02-accedge">
        <summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-1 py-5 font-tfa02-serif text-[19px] font-semibold tracking-[-0.01em] transition-colors duration-200 hover:text-tfa02-acc focus-visible:rounded-lg focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tfa02-acc [&::-webkit-details-marker]:hidden">
          Which payment methods do you accept?
          <span aria-hidden="true" class="grid size-8 shrink-0 place-items-center rounded-full border border-tfa02-edge text-tfa02-acc transition-[transform,background-color,border-color] duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] group-hover:border-tfa02-accedge group-open:-rotate-180 group-open:border-tfa02-accedge group-open:bg-tfa02-code motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="14" height="14"><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-1 pb-6 pt-0.5 text-[14.5px] leading-[1.75] text-tfa02-mut">All major cards, Apple Pay, Google Pay and PayPal. Business customers can request invoicing with NET-30 terms once approved.</p>
      </details>
    </div>

    <p class="mt-6 text-[12.5px] leading-relaxed text-tfa02-mut">Open/close animates to <code class="rounded bg-tfa02-code px-1.5 py-0.5 font-tfa02-mono text-[0.85em] text-tfa02-acc">height:auto</code> via <code class="rounded bg-tfa02-code px-1.5 py-0.5 font-tfa02-mono text-[0.85em] text-tfa02-acc">::details-content</code> — the only four lines utilities cannot express.</p>
  </div>
</section>
@import "tailwindcss";

@theme {
  --color-tfa02-bg: #f7f3ec;
  --color-tfa02-bg: oklch(0.96 0.014 85);
  --color-tfa02-ink: #2e2620;
  --color-tfa02-ink: oklch(0.25 0.02 60);
  --color-tfa02-mut: #6a5f56;
  --color-tfa02-mut: oklch(0.47 0.022 60);
  --color-tfa02-edge: #ded5c7;
  --color-tfa02-edge: oklch(0.88 0.018 80);
  --color-tfa02-accedge: #c8865f;
  --color-tfa02-accedge: oklch(0.7 0.09 45);
  --color-tfa02-code: #f0e2d6;
  --color-tfa02-code: oklch(0.92 0.026 60);
  --color-tfa02-acc: #a8502a;
  --color-tfa02-acc: oklch(0.52 0.14 45);
  --font-tfa02-serif: 'Newsreader', Georgia, serif;
  --font-tfa02-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
  --font-tfa02-mono: 'JetBrains Mono', ui-monospace, monospace;
}

.tfa-02 {
  width: 100%;
  min-height: 100svh;
}
/* The port's limit, in four lines: ::details-content has no Tailwind variant and interpolate-size
   is an inherited opt-in rather than a design-scale value. Declared once for the whole list. */

.tfa-02 [data-panel] {
  interpolate-size: allow-keywords;
}

@supports (interpolate-size: allow-keywords) {
  .tfa-02 details::details-content {
    height: 0;
    overflow: clip;
    opacity: 0;
    transition: height .4s cubic-bezier(.4,0,.2,1), opacity .35s, content-visibility .4s allow-discrete;
  }

  .tfa-02 details[open]::details-content {
    height: auto;
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .tfa-02 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 {
  --color-tfa02-bg: #f7f3ec;
  --color-tfa02-bg: oklch(0.96 0.014 85);
  --color-tfa02-ink: #2e2620;
  --color-tfa02-ink: oklch(0.25 0.02 60);
  --color-tfa02-mut: #6a5f56;
  --color-tfa02-mut: oklch(0.47 0.022 60);
  --color-tfa02-edge: #ded5c7;
  --color-tfa02-edge: oklch(0.88 0.018 80);
  --color-tfa02-accedge: #c8865f;
  --color-tfa02-accedge: oklch(0.7 0.09 45);
  --color-tfa02-code: #f0e2d6;
  --color-tfa02-code: oklch(0.92 0.026 60);
  --color-tfa02-acc: #a8502a;
  --color-tfa02-acc: oklch(0.52 0.14 45);
  --font-tfa02-serif: 'Newsreader', Georgia, serif;
  --font-tfa02-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
  --font-tfa02-mono: 'JetBrains Mono', ui-monospace, monospace;
}

.tfa-02 {
  width: 100%;
  min-height: 100svh;
}
/* The port's limit, in four lines: ::details-content has no Tailwind variant and interpolate-size
   is an inherited opt-in rather than a design-scale value. Declared once for the whole list. */

.tfa-02 [data-panel] {
  interpolate-size: allow-keywords;
}

@supports (interpolate-size: allow-keywords) {
  .tfa-02 details::details-content {
    height: 0;
    overflow: clip;
    opacity: 0;
    transition: height .4s cubic-bezier(.4,0,.2,1), opacity .35s, content-visibility .4s allow-discrete;
  }

  .tfa-02 details[open]::details-content {
    height: auto;
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .tfa-02 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=Newsreader:opsz,wght@6..72,400;6..72,500;6..72,600;6..72,700&family=Plus+Jakarta+Sans:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap">

What changed in the port

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

  • summary{list-style:none} + summary::-webkit-details-marker{display:none} collapse into list-none [&::-webkit-details-marker]:hidden on the summary. Two rules in two syntaxes become one class list on the element they concern — the clearest single win in this collection.
  • .item[open] .ic becomes group-open:, and .item[open] itself becomes plain open:. Tailwind has variants for both halves of the details state, so no [open] attribute selector is needed anywhere.
  • The @supports + ::details-content block is irreducible. Anyone claiming a fully utility-based animated <details> is either using a plugin or animating a wrapper element instead — which reintroduces the wrapper the native pattern exists to delete.
  • UI upgrade from the CSS original: muted copy moved from oklch(0.5) to 0.47 and the accent from 0.55 to 0.52, putting both above 4.5:1 on the warm ground; the focus ring moved from outline-offset:3px to 4px so it clears the serif descenders.
  • UI upgrade: the icon ring now also responds to group-hover: (border tint), so the affordance appears on the whole row rather than only on the question text, and the open <details> tints its bottom border — open state is legible even with the panel scrolled past.
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 Native Details/Summary FAQ with Custom Styled Icons
Source: https://codefronts.com/snippets/tailwind-css-faq-accordion/tailwind-native-details-summary-faq-custom-icons/

The most semantic FAQ possible, in utilities: native <details>/<summary> for behaviour, group-open: for every open-state style, and the marker killed by list-none [&::-webkit-details-marker]:hidden. The height-to-auto animation is the one thing utilities cannot reach, so it stays four lines of @supports CSS — enhancing every accordion on the page at once. Styled as a warm editorial help page.
## HTML
```html
<section class="tfa-02 w-full min-h-svh grid place-items-center bg-tfa02-bg font-tfa02-sans text-tfa02-ink px-5 py-12">
  <div class="w-[min(660px,100%)]">
    <header>
      <h1 class="font-tfa02-serif text-[clamp(32px,6vw,46px)] font-semibold leading-[1.05] tracking-[-0.02em]">Help &amp; support</h1>
      <p class="mt-3 max-w-[56ch] text-[14.5px] leading-[1.7] text-tfa02-mut">Built on native <code class="rounded bg-tfa02-code px-1.5 py-0.5 font-tfa02-mono text-[0.85em] text-tfa02-acc">&lt;details&gt;</code> — keyboard support, screen-reader semantics and find-in-page expansion come free. Try <kbd class="rounded-md border border-b-2 border-tfa02-edge bg-white px-1.5 py-0.5 font-tfa02-mono text-[0.82em]">Ctrl</kbd>+<kbd class="rounded-md border border-b-2 border-tfa02-edge bg-white px-1.5 py-0.5 font-tfa02-mono text-[0.82em]">F</kbd> for “passport”.</p>
    </header>

    <div data-panel class="mt-9 border-t border-tfa02-edge">
      <details class="group border-b border-tfa02-edge open:border-tfa02-accedge" open>
        <summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-1 py-5 font-tfa02-serif text-[19px] font-semibold tracking-[-0.01em] transition-colors duration-200 hover:text-tfa02-acc focus-visible:rounded-lg focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tfa02-acc [&::-webkit-details-marker]:hidden">
          How long does delivery take?
          <span aria-hidden="true" class="grid size-8 shrink-0 place-items-center rounded-full border border-tfa02-edge text-tfa02-acc transition-[transform,background-color,border-color] duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] group-hover:border-tfa02-accedge group-open:-rotate-180 group-open:border-tfa02-accedge group-open:bg-tfa02-code motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="14" height="14"><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-1 pb-6 pt-0.5 text-[14.5px] leading-[1.75] text-tfa02-mut">Standard delivery is 3–5 business days across the US, UK, Canada and Australia. Express (1–2 days) is available at checkout, and every order gets a tracked link the moment it leaves the warehouse.</p>
      </details>

      <details class="group border-b border-tfa02-edge open:border-tfa02-accedge">
        <summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-1 py-5 font-tfa02-serif text-[19px] font-semibold tracking-[-0.01em] transition-colors duration-200 hover:text-tfa02-acc focus-visible:rounded-lg focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tfa02-acc [&::-webkit-details-marker]:hidden">
          Do I need a passport copy to book?
          <span aria-hidden="true" class="grid size-8 shrink-0 place-items-center rounded-full border border-tfa02-edge text-tfa02-acc transition-[transform,background-color,border-color] duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] group-hover:border-tfa02-accedge group-open:-rotate-180 group-open:border-tfa02-accedge group-open:bg-tfa02-code motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="14" height="14"><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-1 pb-6 pt-0.5 text-[14.5px] leading-[1.75] text-tfa02-mut">Only for international itineraries. Upload a photo of the ID page once and we auto-fill every future booking — the file is encrypted at rest and deleted 30 days after your trip ends.</p>
      </details>

      <details class="group border-b border-tfa02-edge open:border-tfa02-accedge">
        <summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-1 py-5 font-tfa02-serif text-[19px] font-semibold tracking-[-0.01em] transition-colors duration-200 hover:text-tfa02-acc focus-visible:rounded-lg focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tfa02-acc [&::-webkit-details-marker]:hidden">
          Can I change my order after placing it?
          <span aria-hidden="true" class="grid size-8 shrink-0 place-items-center rounded-full border border-tfa02-edge text-tfa02-acc transition-[transform,background-color,border-color] duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] group-hover:border-tfa02-accedge group-open:-rotate-180 group-open:border-tfa02-accedge group-open:bg-tfa02-code motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="14" height="14"><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-1 pb-6 pt-0.5 text-[14.5px] leading-[1.75] text-tfa02-mut">Yes — orders can be edited for 60 minutes after checkout from your account page. After that the warehouse has it, but you can always refuse delivery or start a free return.</p>
      </details>

      <details class="group border-b border-tfa02-edge open:border-tfa02-accedge">
        <summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-1 py-5 font-tfa02-serif text-[19px] font-semibold tracking-[-0.01em] transition-colors duration-200 hover:text-tfa02-acc focus-visible:rounded-lg focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-tfa02-acc [&::-webkit-details-marker]:hidden">
          Which payment methods do you accept?
          <span aria-hidden="true" class="grid size-8 shrink-0 place-items-center rounded-full border border-tfa02-edge text-tfa02-acc transition-[transform,background-color,border-color] duration-400 ease-[cubic-bezier(0.4,0,0.2,1)] group-hover:border-tfa02-accedge group-open:-rotate-180 group-open:border-tfa02-accedge group-open:bg-tfa02-code motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="14" height="14"><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-1 pb-6 pt-0.5 text-[14.5px] leading-[1.75] text-tfa02-mut">All major cards, Apple Pay, Google Pay and PayPal. Business customers can request invoicing with NET-30 terms once approved.</p>
      </details>
    </div>

    <p class="mt-6 text-[12.5px] leading-relaxed text-tfa02-mut">Open/close animates to <code class="rounded bg-tfa02-code px-1.5 py-0.5 font-tfa02-mono text-[0.85em] text-tfa02-acc">height:auto</code> via <code class="rounded bg-tfa02-code px-1.5 py-0.5 font-tfa02-mono text-[0.85em] text-tfa02-acc">::details-content</code> — the only four lines utilities cannot express.</p>
  </div>
</section>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-tfa02-bg: #f7f3ec;
  --color-tfa02-bg: oklch(0.96 0.014 85);
  --color-tfa02-ink: #2e2620;
  --color-tfa02-ink: oklch(0.25 0.02 60);
  --color-tfa02-mut: #6a5f56;
  --color-tfa02-mut: oklch(0.47 0.022 60);
  --color-tfa02-edge: #ded5c7;
  --color-tfa02-edge: oklch(0.88 0.018 80);
  --color-tfa02-accedge: #c8865f;
  --color-tfa02-accedge: oklch(0.7 0.09 45);
  --color-tfa02-code: #f0e2d6;
  --color-tfa02-code: oklch(0.92 0.026 60);
  --color-tfa02-acc: #a8502a;
  --color-tfa02-acc: oklch(0.52 0.14 45);
  --font-tfa02-serif: 'Newsreader', Georgia, serif;
  --font-tfa02-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
  --font-tfa02-mono: 'JetBrains Mono', ui-monospace, monospace;
}

.tfa-02 {
  width: 100%;
  min-height: 100svh;
}
/* The port's limit, in four lines: ::details-content has no Tailwind variant and interpolate-size
   is an inherited opt-in rather than a design-scale value. Declared once for the whole list. */

.tfa-02 [data-panel] {
  interpolate-size: allow-keywords;
}

@supports (interpolate-size: allow-keywords) {
  .tfa-02 details::details-content {
    height: 0;
    overflow: clip;
    opacity: 0;
    transition: height .4s cubic-bezier(.4,0,.2,1), opacity .35s, content-visibility .4s allow-discrete;
  }

  .tfa-02 details[open]::details-content {
    height: auto;
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .tfa-02 details::details-content {
    transition-duration: 1ms;
  }
}
```

How this works

The element manages state; utilities only paint it. Tailwind ships both variants this needs: open: for the details element and group-open: for anything inside it.

<details class="group border-b open:border-tfa02-accedge">
  <summary class="flex min-h-11 cursor-pointer list-none items-center justify-between
                  [&::-webkit-details-marker]:hidden">
    How long does delivery take?
    <span class="transition-transform duration-400 group-open:-rotate-180">svg</span>
  </summary>

What must stay CSS. ::details-content is a pseudo-element with no Tailwind variant, and interpolate-size is an inherited opt-in, not a design-scale value. Both live in the stylesheet, once, for the whole list:

.tfa-02 [data-panel] { interpolate-size: allow-keywords }
@supports (interpolate-size: allow-keywords) {
  .tfa-02 details::details-content{ height:0; overflow:clip; opacity:0;
    transition: height .4s ease, opacity .35s, content-visibility .4s allow-discrete }
  .tfa-02 details[open]::details-content{ height:auto; opacity:1 }
}

content-visibility with allow-discrete is what keeps the closing animation visible; without it the content is yanked from rendering the instant open is removed. Where the pseudo-element is unsupported the @supports block never applies and panels snap — exactly how <details> has behaved for a decade.

Free platform behaviour: Chrome's find-in-page auto-expands a closed <details> containing a match, so your answers are searchable while collapsed. No utility gives you that; the element does.

Make it yours

  • Icon: one inline SVG in the summary — swap the path for a plus or brand glyph; group-open:-rotate-180 is untouched.
  • Default-open item: the open attribute, which round-trips with the UI state.
  • Exclusive mode: add name="faq" to every <details> and the browser closes siblings for you (demo 03).
  • Timing: change the duration-400 utility and the two .4s values in the CSS block together, or the icon and panel desynchronise.

Gotchas — read before shipping

  • summary with display:flex hides the marker as a side effect in some engines — do not rely on it; keep the explicit list-none + [&::-webkit-details-marker]:hidden pair.
  • Do not put a heading inside <summary> and expect heading semantics: summary maps to a button-like role and some screen readers drop the level. Put the h2/h3 around the details block if you need a document outline.
  • overflow:clip (not hidden) on ::details-content avoids creating a scroll container that can trap programmatic scrolling.
  • interpolate-size is inherited — declare it once on the list, not per <details>.

Browser support

ChromeSafariFirefoxEdge
131+18.4+instant fallback131+

<details> is universal; the height-to-auto animation via ::details-content/interpolate-size is Chrome 131 / Safari 18.4. Firefox gets instant open/close through the @supports fallback — fully functional, just unanimated.

Techniques used in this demo

Utilitiesfirst-class utility or variant

Search CodeFronts

Loading…