25 Tailwind CSS FAQ Accordion
22 / 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 FAQ with FAQPage JSON-LD Schema for Rich Snippets and AI Search

A FAQ wearing its structured data: the visible accordion is mirrored 1:1 by a FAQPage JSON-LD block in the same component, making answers parseable by search engines and — increasingly the point — by AI answer engines. Includes a mock SERP preview of the rich result, and the eligibility reality check for 2026.

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-22 w-full min-h-svh grid place-items-center bg-tfa22-bg font-tfa22-sans text-tfa22-ink px-5 py-12">
  <script type="application/ld+json">
  {
    "@context": "https://schema.org",
    "@type": "FAQPage",
    "mainEntity": [
      {"@type":"Question","name":"How long does shipping take?","acceptedAnswer":{"@type":"Answer","text":"Standard shipping takes 3-5 business days in the US, UK, Canada and Australia. Express 1-2 day options are available at checkout."}},
      {"@type":"Question","name":"What is your return policy?","acceptedAnswer":{"@type":"Answer","text":"Returns are free for 60 days from delivery. Start a return from your order email; refunds process within 3-5 days of the carrier scan."}},
      {"@type":"Question","name":"Do you ship internationally?","acceptedAnswer":{"@type":"Answer","text":"Yes, to 40+ countries with duties calculated at checkout, so there are no surprise fees at the door."}},
      {"@type":"Question","name":"How can I track my order?","acceptedAnswer":{"@type":"Answer","text":"Every order emails a tracked link at dispatch, and live status appears on your account orders page."}}
    ]
  }
  </script>

  <div class="w-[min(680px,100%)]">
    <header>
      <span class="inline-block rounded-full bg-tfa22-tint px-3.5 py-1.5 font-tfa22-mono text-[11.5px] font-semibold text-tfa22-acc">&lt;script type="application/ld+json"&gt;</span>
      <h1 class="mt-4 text-[clamp(28px,5vw,40px)] font-extrabold leading-[1.08] tracking-[-0.025em]">Machine-readable FAQ</h1>
      <p class="mt-3 max-w-[56ch] text-[15px] leading-relaxed text-tfa22-mut">The accordion below is mirrored 1:1 in a FAQPage JSON-LD block — same four answers, one set for humans, one for crawlers and AI engines.</p>
    </header>

    <div role="img" aria-label="Mock search result showing a FAQ rich snippet" class="mt-6 rounded-[14px] border border-tfa22-edge bg-white px-5 py-4">
      <div class="font-tfa22-sans text-[12px] text-[oklch(0.45_0.02_150)]">example.com › help › shipping</div>
      <div class="mt-1 text-[18px] font-semibold text-[oklch(0.42_0.16_265)]">Shipping &amp; Returns FAQ — Example Store</div>
      <div class="mt-1 text-[13px] leading-[1.5] text-[oklch(0.35_0.01_260)]">Answers about delivery times, returns, international shipping and order tracking.</div>
      <div class="mt-2.5 divide-y divide-[oklch(0.9_0.005_260)] border-t border-[oklch(0.9_0.005_260)]">
        <div class="flex items-center justify-between py-2 text-[13px] text-[oklch(0.35_0.01_260)]">How long does shipping take?<b class="text-[oklch(0.55_0.01_260)]">⌄</b></div>
        <div class="flex items-center justify-between py-2 text-[13px] text-[oklch(0.35_0.01_260)]">What is your return policy?<b class="text-[oklch(0.55_0.01_260)]">⌄</b></div>
      </div>
      <span class="mt-2.5 block font-tfa22-mono text-[10.5px] text-[oklch(0.5_0.02_150)]">what the rich result renders, where eligible</span>
    </div>

    <div data-panel class="mt-5 flex flex-col gap-2.5">
      <details class="group rounded-[13px] border border-tfa22-edge bg-tfa22-panel transition-[border-color,box-shadow] duration-300 open:border-tfa22-accedge open:shadow-[0_12px_30px_-20px_oklch(0.8_0.14_150/0.4)]" open>
        <summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-4 py-3.5 text-[15px] font-semibold transition-colors duration-200 hover:text-tfa22-acc focus-visible:rounded-[13px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-tfa22-acc [&::-webkit-details-marker]:hidden">How long does shipping take?
          <i aria-hidden="true" class="size-2 shrink-0 -translate-y-0.5 rotate-45 border-b-2 border-r-2 border-tfa22-acc transition-[rotate,translate] duration-350 group-open:translate-y-0.5 group-open:rotate-[225deg] motion-reduce:transition-none"></i>
        </summary>
        <p class="max-w-[60ch] px-4 pb-3.5 text-[13.5px] leading-[1.7] text-tfa22-mut">Standard shipping takes 3–5 business days in the US, UK, Canada and Australia. Express 1–2 day options are available at checkout.</p>
      </details>
      <details class="group rounded-[13px] border border-tfa22-edge bg-tfa22-panel transition-[border-color,box-shadow] duration-300 open:border-tfa22-accedge open:shadow-[0_12px_30px_-20px_oklch(0.8_0.14_150/0.4)]">
        <summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-4 py-3.5 text-[15px] font-semibold transition-colors duration-200 hover:text-tfa22-acc focus-visible:rounded-[13px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-tfa22-acc [&::-webkit-details-marker]:hidden">What is your return policy?
          <i aria-hidden="true" class="size-2 shrink-0 -translate-y-0.5 rotate-45 border-b-2 border-r-2 border-tfa22-acc transition-[rotate,translate] duration-350 group-open:translate-y-0.5 group-open:rotate-[225deg] motion-reduce:transition-none"></i>
        </summary>
        <p class="max-w-[60ch] px-4 pb-3.5 text-[13.5px] leading-[1.7] text-tfa22-mut">Returns are free for 60 days from delivery. Start a return from your order email; refunds process within 3–5 days of the carrier scan.</p>
      </details>
      <details class="group rounded-[13px] border border-tfa22-edge bg-tfa22-panel transition-[border-color,box-shadow] duration-300 open:border-tfa22-accedge open:shadow-[0_12px_30px_-20px_oklch(0.8_0.14_150/0.4)]">
        <summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-4 py-3.5 text-[15px] font-semibold transition-colors duration-200 hover:text-tfa22-acc focus-visible:rounded-[13px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-tfa22-acc [&::-webkit-details-marker]:hidden">Do you ship internationally?
          <i aria-hidden="true" class="size-2 shrink-0 -translate-y-0.5 rotate-45 border-b-2 border-r-2 border-tfa22-acc transition-[rotate,translate] duration-350 group-open:translate-y-0.5 group-open:rotate-[225deg] motion-reduce:transition-none"></i>
        </summary>
        <p class="max-w-[60ch] px-4 pb-3.5 text-[13.5px] leading-[1.7] text-tfa22-mut">Yes — to 40+ countries with duties calculated at checkout, so there are no surprise fees at the door.</p>
      </details>
      <details class="group rounded-[13px] border border-tfa22-edge bg-tfa22-panel transition-[border-color,box-shadow] duration-300 open:border-tfa22-accedge open:shadow-[0_12px_30px_-20px_oklch(0.8_0.14_150/0.4)]">
        <summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-4 py-3.5 text-[15px] font-semibold transition-colors duration-200 hover:text-tfa22-acc focus-visible:rounded-[13px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-tfa22-acc [&::-webkit-details-marker]:hidden">How can I track my order?
          <i aria-hidden="true" class="size-2 shrink-0 -translate-y-0.5 rotate-45 border-b-2 border-r-2 border-tfa22-acc transition-[rotate,translate] duration-350 group-open:translate-y-0.5 group-open:rotate-[225deg] motion-reduce:transition-none"></i>
        </summary>
        <p class="max-w-[60ch] px-4 pb-3.5 text-[13.5px] leading-[1.7] text-tfa22-mut">Every order emails a tracked link at dispatch, and live status appears on your account's orders page.</p>
      </details>
    </div>

    <p class="mt-5 text-[12.5px] text-tfa22-mut">One FAQPage block per page, answers matching the visible text — the two rules with penalties attached.</p>
  </div>
</section>
@import "tailwindcss";

@theme {
  --color-tfa22-bg: #171d1a;
  --color-tfa22-bg: oklch(0.21 0.018 150);
  --color-tfa22-panel: #1f2723;
  --color-tfa22-panel: oklch(0.25 0.022 150);
  --color-tfa22-ink: #f0f5f2;
  --color-tfa22-ink: oklch(0.96 0.008 150);
  --color-tfa22-mut: #b3c0b8;
  --color-tfa22-mut: oklch(0.79 0.016 150);
  --color-tfa22-edge: #343f39;
  --color-tfa22-edge: oklch(0.34 0.025 150);
  --color-tfa22-accedge: #4d9070;
  --color-tfa22-accedge: oklch(0.6 0.09 150);
  --color-tfa22-tint: #23392e;
  --color-tfa22-tint: oklch(0.29 0.045 150);
  --color-tfa22-acc: #7fe0ac;
  --color-tfa22-acc: oklch(0.85 0.13 150);
  --font-tfa22-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
  --font-tfa22-mono: 'JetBrains Mono', ui-monospace, monospace;
}

.tfa-22 {
  width: 100%;
  min-height: 100svh;
}

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

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

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

@media (prefers-reduced-motion: reduce) {
  .tfa-22 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-tfa22-bg: #171d1a;
  --color-tfa22-bg: oklch(0.21 0.018 150);
  --color-tfa22-panel: #1f2723;
  --color-tfa22-panel: oklch(0.25 0.022 150);
  --color-tfa22-ink: #f0f5f2;
  --color-tfa22-ink: oklch(0.96 0.008 150);
  --color-tfa22-mut: #b3c0b8;
  --color-tfa22-mut: oklch(0.79 0.016 150);
  --color-tfa22-edge: #343f39;
  --color-tfa22-edge: oklch(0.34 0.025 150);
  --color-tfa22-accedge: #4d9070;
  --color-tfa22-accedge: oklch(0.6 0.09 150);
  --color-tfa22-tint: #23392e;
  --color-tfa22-tint: oklch(0.29 0.045 150);
  --color-tfa22-acc: #7fe0ac;
  --color-tfa22-acc: oklch(0.85 0.13 150);
  --font-tfa22-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
  --font-tfa22-mono: 'JetBrains Mono', ui-monospace, monospace;
}

.tfa-22 {
  width: 100%;
  min-height: 100svh;
}

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

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

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

@media (prefers-reduced-motion: reduce) {
  .tfa-22 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.

  • The SEO layer is identical to the CSS version, which is the honest finding: structured data is markup, and utilities are styling. Anyone expecting a framework to change their schema story is looking in the wrong layer.
  • The mock SERP card is where the port is actually nicer — Google's own greys and blues are one-off values with no place in a theme, so they live as arbitrary text-[oklch(...)] colours rather than polluting @theme with tokens no component should reuse. That is the rule for one-off brand mimicry.
  • divide-y divide-[...] draws the snippet's question rules in one utility, replacing a hand-written sibling selector.
  • UI upgrade from the CSS original: muted copy oklch(0.67) → 0.79 and the panel 0.21 → 0.25. The SERP preview also moved onto a true white card, since its whole job is to look like a search result.
  • UI upgrade: the preview now carries role=&quot;img&quot; with a single label, so screen readers announce it as one illustration instead of reading fake search results as if they were real page content.
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 FAQ with FAQPage JSON-LD Schema for Rich Snippets and AI Search
Source: https://codefronts.com/snippets/tailwind-css-faq-accordion/tailwind-faq-faqpage-json-ld-rich-snippet/

A FAQ wearing its structured data: the visible accordion is mirrored 1:1 by a FAQPage JSON-LD block in the same component, making answers parseable by search engines and — increasingly the point — by AI answer engines. Includes a mock SERP preview of the rich result, and the eligibility reality check for 2026.
## HTML
```html
<section class="tfa-22 w-full min-h-svh grid place-items-center bg-tfa22-bg font-tfa22-sans text-tfa22-ink px-5 py-12">
  <script type="application/ld+json">
  {
    "@context": "https://schema.org",
    "@type": "FAQPage",
    "mainEntity": [
      {"@type":"Question","name":"How long does shipping take?","acceptedAnswer":{"@type":"Answer","text":"Standard shipping takes 3-5 business days in the US, UK, Canada and Australia. Express 1-2 day options are available at checkout."}},
      {"@type":"Question","name":"What is your return policy?","acceptedAnswer":{"@type":"Answer","text":"Returns are free for 60 days from delivery. Start a return from your order email; refunds process within 3-5 days of the carrier scan."}},
      {"@type":"Question","name":"Do you ship internationally?","acceptedAnswer":{"@type":"Answer","text":"Yes, to 40+ countries with duties calculated at checkout, so there are no surprise fees at the door."}},
      {"@type":"Question","name":"How can I track my order?","acceptedAnswer":{"@type":"Answer","text":"Every order emails a tracked link at dispatch, and live status appears on your account orders page."}}
    ]
  }
  </script>

  <div class="w-[min(680px,100%)]">
    <header>
      <span class="inline-block rounded-full bg-tfa22-tint px-3.5 py-1.5 font-tfa22-mono text-[11.5px] font-semibold text-tfa22-acc">&lt;script type="application/ld+json"&gt;</span>
      <h1 class="mt-4 text-[clamp(28px,5vw,40px)] font-extrabold leading-[1.08] tracking-[-0.025em]">Machine-readable FAQ</h1>
      <p class="mt-3 max-w-[56ch] text-[15px] leading-relaxed text-tfa22-mut">The accordion below is mirrored 1:1 in a FAQPage JSON-LD block — same four answers, one set for humans, one for crawlers and AI engines.</p>
    </header>

    <div role="img" aria-label="Mock search result showing a FAQ rich snippet" class="mt-6 rounded-[14px] border border-tfa22-edge bg-white px-5 py-4">
      <div class="font-tfa22-sans text-[12px] text-[oklch(0.45_0.02_150)]">example.com › help › shipping</div>
      <div class="mt-1 text-[18px] font-semibold text-[oklch(0.42_0.16_265)]">Shipping &amp; Returns FAQ — Example Store</div>
      <div class="mt-1 text-[13px] leading-[1.5] text-[oklch(0.35_0.01_260)]">Answers about delivery times, returns, international shipping and order tracking.</div>
      <div class="mt-2.5 divide-y divide-[oklch(0.9_0.005_260)] border-t border-[oklch(0.9_0.005_260)]">
        <div class="flex items-center justify-between py-2 text-[13px] text-[oklch(0.35_0.01_260)]">How long does shipping take?<b class="text-[oklch(0.55_0.01_260)]">⌄</b></div>
        <div class="flex items-center justify-between py-2 text-[13px] text-[oklch(0.35_0.01_260)]">What is your return policy?<b class="text-[oklch(0.55_0.01_260)]">⌄</b></div>
      </div>
      <span class="mt-2.5 block font-tfa22-mono text-[10.5px] text-[oklch(0.5_0.02_150)]">what the rich result renders, where eligible</span>
    </div>

    <div data-panel class="mt-5 flex flex-col gap-2.5">
      <details class="group rounded-[13px] border border-tfa22-edge bg-tfa22-panel transition-[border-color,box-shadow] duration-300 open:border-tfa22-accedge open:shadow-[0_12px_30px_-20px_oklch(0.8_0.14_150/0.4)]" open>
        <summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-4 py-3.5 text-[15px] font-semibold transition-colors duration-200 hover:text-tfa22-acc focus-visible:rounded-[13px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-tfa22-acc [&::-webkit-details-marker]:hidden">How long does shipping take?
          <i aria-hidden="true" class="size-2 shrink-0 -translate-y-0.5 rotate-45 border-b-2 border-r-2 border-tfa22-acc transition-[rotate,translate] duration-350 group-open:translate-y-0.5 group-open:rotate-[225deg] motion-reduce:transition-none"></i>
        </summary>
        <p class="max-w-[60ch] px-4 pb-3.5 text-[13.5px] leading-[1.7] text-tfa22-mut">Standard shipping takes 3–5 business days in the US, UK, Canada and Australia. Express 1–2 day options are available at checkout.</p>
      </details>
      <details class="group rounded-[13px] border border-tfa22-edge bg-tfa22-panel transition-[border-color,box-shadow] duration-300 open:border-tfa22-accedge open:shadow-[0_12px_30px_-20px_oklch(0.8_0.14_150/0.4)]">
        <summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-4 py-3.5 text-[15px] font-semibold transition-colors duration-200 hover:text-tfa22-acc focus-visible:rounded-[13px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-tfa22-acc [&::-webkit-details-marker]:hidden">What is your return policy?
          <i aria-hidden="true" class="size-2 shrink-0 -translate-y-0.5 rotate-45 border-b-2 border-r-2 border-tfa22-acc transition-[rotate,translate] duration-350 group-open:translate-y-0.5 group-open:rotate-[225deg] motion-reduce:transition-none"></i>
        </summary>
        <p class="max-w-[60ch] px-4 pb-3.5 text-[13.5px] leading-[1.7] text-tfa22-mut">Returns are free for 60 days from delivery. Start a return from your order email; refunds process within 3–5 days of the carrier scan.</p>
      </details>
      <details class="group rounded-[13px] border border-tfa22-edge bg-tfa22-panel transition-[border-color,box-shadow] duration-300 open:border-tfa22-accedge open:shadow-[0_12px_30px_-20px_oklch(0.8_0.14_150/0.4)]">
        <summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-4 py-3.5 text-[15px] font-semibold transition-colors duration-200 hover:text-tfa22-acc focus-visible:rounded-[13px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-tfa22-acc [&::-webkit-details-marker]:hidden">Do you ship internationally?
          <i aria-hidden="true" class="size-2 shrink-0 -translate-y-0.5 rotate-45 border-b-2 border-r-2 border-tfa22-acc transition-[rotate,translate] duration-350 group-open:translate-y-0.5 group-open:rotate-[225deg] motion-reduce:transition-none"></i>
        </summary>
        <p class="max-w-[60ch] px-4 pb-3.5 text-[13.5px] leading-[1.7] text-tfa22-mut">Yes — to 40+ countries with duties calculated at checkout, so there are no surprise fees at the door.</p>
      </details>
      <details class="group rounded-[13px] border border-tfa22-edge bg-tfa22-panel transition-[border-color,box-shadow] duration-300 open:border-tfa22-accedge open:shadow-[0_12px_30px_-20px_oklch(0.8_0.14_150/0.4)]">
        <summary class="flex min-h-11 cursor-pointer list-none items-center justify-between gap-4 px-4 py-3.5 text-[15px] font-semibold transition-colors duration-200 hover:text-tfa22-acc focus-visible:rounded-[13px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-tfa22-acc [&::-webkit-details-marker]:hidden">How can I track my order?
          <i aria-hidden="true" class="size-2 shrink-0 -translate-y-0.5 rotate-45 border-b-2 border-r-2 border-tfa22-acc transition-[rotate,translate] duration-350 group-open:translate-y-0.5 group-open:rotate-[225deg] motion-reduce:transition-none"></i>
        </summary>
        <p class="max-w-[60ch] px-4 pb-3.5 text-[13.5px] leading-[1.7] text-tfa22-mut">Every order emails a tracked link at dispatch, and live status appears on your account's orders page.</p>
      </details>
    </div>

    <p class="mt-5 text-[12.5px] text-tfa22-mut">One FAQPage block per page, answers matching the visible text — the two rules with penalties attached.</p>
  </div>
</section>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-tfa22-bg: #171d1a;
  --color-tfa22-bg: oklch(0.21 0.018 150);
  --color-tfa22-panel: #1f2723;
  --color-tfa22-panel: oklch(0.25 0.022 150);
  --color-tfa22-ink: #f0f5f2;
  --color-tfa22-ink: oklch(0.96 0.008 150);
  --color-tfa22-mut: #b3c0b8;
  --color-tfa22-mut: oklch(0.79 0.016 150);
  --color-tfa22-edge: #343f39;
  --color-tfa22-edge: oklch(0.34 0.025 150);
  --color-tfa22-accedge: #4d9070;
  --color-tfa22-accedge: oklch(0.6 0.09 150);
  --color-tfa22-tint: #23392e;
  --color-tfa22-tint: oklch(0.29 0.045 150);
  --color-tfa22-acc: #7fe0ac;
  --color-tfa22-acc: oklch(0.85 0.13 150);
  --font-tfa22-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
  --font-tfa22-mono: 'JetBrains Mono', ui-monospace, monospace;
}

.tfa-22 {
  width: 100%;
  min-height: 100svh;
}

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

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

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

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

How this works

JSON-LD is invisible to users and first-class to crawlers. A <script type="application/ld+json"> block declares a FAQPage whose mainEntity is a list of Question objects, each with an acceptedAnswer. Tailwind has nothing to do with it, which is precisely why this demo is in the collection: the port changes the styling layer and leaves the SEO layer untouched.

Three rules keep it audit-proof. Match the visible content — invisible-only Q&A is a manual-action risk, not a growth hack, and the JSON here is literally the same four answers as the accordion. One FAQPage per page — multiple blocks compete and usually all get ignored. And keep answers plain-ish: a small whitelist of tags survives, so do not rely on markup semantics inside the JSON.

The 2026 reality check. Google limited FAQ rich result display to well-known government and health sites in 2023 — but the markup is still valid, still parsed, still feeds knowledge panels and AI-generated answers, and Bing still renders FAQ snippets. Structured data has quietly become an AI-legibility investment more than a SERP decoration.

Make it yours

  • Generate, do not hand-write: emit the JSON from the same data source as the visible FAQ. Drift between them is the compliance risk.
  • Combine types: a product page can carry Product and FAQPage as separate blocks, or one @graph array.
  • Validate: the Rich Results Test and the schema.org validator both accept pasted HTML.
  • Track it: Search Console → Enhancements reports parse errors and impressions where snippets still display.

Gotchas — read before shipping

  • JSON-LD answers MUST appear on the visible page. This is the one rule with a penalty attached.
  • Escaping is the number-one validation failure: no raw newlines, and no unescaped quotes inside answer text.
  • Do not mark up promotional non-questions — the guidelines exclude advertising disguised as FAQ.
  • Keep the script adjacent to the component. A schema block orphaned in <head> survives exactly one refactor.

Browser support

ChromeSafariFirefoxEdge
129+not yetnot yet129+

Floor set by oklch(), interpolate-size as this demo is written. The core technique itself goes back further — Chrome n/a (crawler feature).

JSON-LD is inert to browsers — zero rendering cost, no compatibility floor. The visible accordion follows demo 02's floors. Results vary by search-engine policy, not by browser.

Techniques used in this demo

Utilitiesfirst-class utility or variant

Theme tokensset in @theme, used by a utility

Search CodeFronts

Loading…