25 Tailwind CSS FAQ Accordion
15 / 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
Pure TailwindMIT licensed

Tailwind Horizontal FAQ Accordion with Sideways Expanding Panels

The showpiece: five photo panels standing shoulder to shoulder, the active one unfolding sideways to reveal its answer while the others compress into spines with vertically-written titles. Demo 10's fr-unit trick rotated 90° — grid-cols-[64px_0fr] to [64px_1fr] — plus a grow-[3.2] transition, [writing-mode:vertical-rl] spines, and radio state, so it stays pure Tailwind.

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-15 w-full min-h-svh font-tfa15-sans text-white">
  <div class="@container grid min-h-svh w-full place-items-center bg-tfa15-bg px-5 py-12">
    <div class="w-[min(1020px,100%)]">
      <header>
        <h1 class="text-[clamp(26px,4.4vw,40px)] font-extrabold tracking-[-0.025em]">Plan your expedition</h1>
        <p class="mt-3 max-w-[54ch] text-[14.5px] leading-relaxed text-white/85">Five questions standing sideways — the open one unfolds. Arrow keys move between panels.</p>
      </header>

      <div class="mt-7 flex min-h-[420px] gap-2.5 @max-tfa15fold:min-h-0 @max-tfa15fold:flex-col">
        <div class="group relative grid flex-1 overflow-hidden rounded-[18px] bg-[linear-gradient(oklch(0.2_0.03_260/0.25),oklch(0.15_0.03_260/0.7)),url('https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?q=80&w=1200&auto=format&fit=crop')] bg-cover bg-center outline-2 outline-offset-[3px] outline-transparent transition-[grid-template-columns,grid-template-rows,flex-grow,outline-color] duration-600 ease-[cubic-bezier(0.3,0.8,0.25,1)] grid-cols-[64px_0fr] has-checked:grid-cols-[64px_1fr] has-checked:grow-[3.2] [&:not(:has(:checked)):hover]:grow-[1.15] has-focus-visible:outline-tfa15-acc @max-tfa15fold:grid-cols-[1fr] @max-tfa15fold:grid-rows-[56px_0fr] @max-tfa15fold:has-checked:grid-cols-[1fr] @max-tfa15fold:has-checked:grid-rows-[56px_1fr] @max-tfa15fold:has-checked:grow-[1] motion-reduce:transition-none">
          <input id="tfa15-p1" type="radio" name="tfa15" class="absolute opacity-0 pointer-events-none" checked>
          <label for="tfa15-p1" class="grid min-w-11 cursor-pointer items-end justify-items-center py-[18px] @max-tfa15fold:min-h-11 @max-tfa15fold:place-items-center @max-tfa15fold:justify-items-start @max-tfa15fold:px-5 @max-tfa15fold:py-0">
            <h3 class="[writing-mode:vertical-rl] rotate-180 text-[13.5px] font-bold uppercase tracking-[0.06em] text-white [text-shadow:0_1px_12px_oklch(0.15_0.03_260/0.85)] transition-colors duration-300 group-hover:text-tfa15-acc group-has-checked:text-tfa15-acc @max-tfa15fold:[writing-mode:horizontal-tb] @max-tfa15fold:rotate-0">When to go?</h3>
          </label>
          <div class="grid min-w-0 items-end overflow-hidden @max-tfa15fold:min-h-0">
            <div class="w-[max(260px,26cqi)] translate-x-3.5 py-[22px] pl-2 pr-6 opacity-0 transition-[translate,opacity] delay-150 duration-500 ease-[cubic-bezier(0.3,0.8,0.25,1)] group-has-checked:translate-x-0 group-has-checked:opacity-100 motion-reduce:transition-none @max-tfa15fold:w-full @max-tfa15fold:px-5 @max-tfa15fold:pb-5 @max-tfa15fold:pt-0">
              <h2 class="text-[clamp(17px,2.2vw,22px)] font-extrabold tracking-[-0.02em] text-white [text-shadow:0_1px_14px_oklch(0.15_0.03_260/0.8)]">When is the best season?</h2>
              <p class="mt-2.5 text-[13.5px] leading-[1.65] text-white/90 [text-shadow:0_1px_12px_oklch(0.15_0.03_260/0.75)]">June through September for the high passes — long days, stable weather, open refuges. Shoulder months halve the crowds but add real weather risk above 2,500m.</p>
            </div>
          </div>
        </div>
        <div class="group relative grid flex-1 overflow-hidden rounded-[18px] bg-[linear-gradient(oklch(0.2_0.03_260/0.25),oklch(0.15_0.03_260/0.7)),url('https://images.unsplash.com/photo-1551632811-561732d1e306?q=80&w=1200&auto=format&fit=crop')] bg-cover bg-center outline-2 outline-offset-[3px] outline-transparent transition-[grid-template-columns,grid-template-rows,flex-grow,outline-color] duration-600 ease-[cubic-bezier(0.3,0.8,0.25,1)] grid-cols-[64px_0fr] has-checked:grid-cols-[64px_1fr] has-checked:grow-[3.2] [&:not(:has(:checked)):hover]:grow-[1.15] has-focus-visible:outline-tfa15-acc @max-tfa15fold:grid-cols-[1fr] @max-tfa15fold:grid-rows-[56px_0fr] @max-tfa15fold:has-checked:grid-cols-[1fr] @max-tfa15fold:has-checked:grid-rows-[56px_1fr] @max-tfa15fold:has-checked:grow-[1] motion-reduce:transition-none">
          <input id="tfa15-p2" type="radio" name="tfa15" class="absolute opacity-0 pointer-events-none">
          <label for="tfa15-p2" class="grid min-w-11 cursor-pointer items-end justify-items-center py-[18px] @max-tfa15fold:min-h-11 @max-tfa15fold:place-items-center @max-tfa15fold:justify-items-start @max-tfa15fold:px-5 @max-tfa15fold:py-0">
            <h3 class="[writing-mode:vertical-rl] rotate-180 text-[13.5px] font-bold uppercase tracking-[0.06em] text-white [text-shadow:0_1px_12px_oklch(0.15_0.03_260/0.85)] transition-colors duration-300 group-hover:text-tfa15-acc group-has-checked:text-tfa15-acc @max-tfa15fold:[writing-mode:horizontal-tb] @max-tfa15fold:rotate-0">Fitness level</h3>
          </label>
          <div class="grid min-w-0 items-end overflow-hidden @max-tfa15fold:min-h-0">
            <div class="w-[max(260px,26cqi)] translate-x-3.5 py-[22px] pl-2 pr-6 opacity-0 transition-[translate,opacity] delay-150 duration-500 ease-[cubic-bezier(0.3,0.8,0.25,1)] group-has-checked:translate-x-0 group-has-checked:opacity-100 motion-reduce:transition-none @max-tfa15fold:w-full @max-tfa15fold:px-5 @max-tfa15fold:pb-5 @max-tfa15fold:pt-0">
              <h2 class="text-[clamp(17px,2.2vw,22px)] font-extrabold tracking-[-0.02em] text-white [text-shadow:0_1px_14px_oklch(0.15_0.03_260/0.8)]">How fit do I need to be?</h2>
              <p class="mt-2.5 text-[13.5px] leading-[1.65] text-white/90 [text-shadow:0_1px_12px_oklch(0.15_0.03_260/0.75)]">Comfortable hiking 6–7 hours with a daypack, two days in a row. Our grade-2 routes need no technical skills; if you can do a hilly half-day hike smiling, twelve training weeks gets you there.</p>
            </div>
          </div>
        </div>
        <div class="group relative grid flex-1 overflow-hidden rounded-[18px] bg-[linear-gradient(oklch(0.2_0.03_260/0.25),oklch(0.15_0.03_260/0.7)),url('https://images.unsplash.com/photo-1501554728187-ce583db33af7?q=80&w=1200&auto=format&fit=crop')] bg-cover bg-center outline-2 outline-offset-[3px] outline-transparent transition-[grid-template-columns,grid-template-rows,flex-grow,outline-color] duration-600 ease-[cubic-bezier(0.3,0.8,0.25,1)] grid-cols-[64px_0fr] has-checked:grid-cols-[64px_1fr] has-checked:grow-[3.2] [&:not(:has(:checked)):hover]:grow-[1.15] has-focus-visible:outline-tfa15-acc @max-tfa15fold:grid-cols-[1fr] @max-tfa15fold:grid-rows-[56px_0fr] @max-tfa15fold:has-checked:grid-cols-[1fr] @max-tfa15fold:has-checked:grid-rows-[56px_1fr] @max-tfa15fold:has-checked:grow-[1] motion-reduce:transition-none">
          <input id="tfa15-p3" type="radio" name="tfa15" class="absolute opacity-0 pointer-events-none">
          <label for="tfa15-p3" class="grid min-w-11 cursor-pointer items-end justify-items-center py-[18px] @max-tfa15fold:min-h-11 @max-tfa15fold:place-items-center @max-tfa15fold:justify-items-start @max-tfa15fold:px-5 @max-tfa15fold:py-0">
            <h3 class="[writing-mode:vertical-rl] rotate-180 text-[13.5px] font-bold uppercase tracking-[0.06em] text-white [text-shadow:0_1px_12px_oklch(0.15_0.03_260/0.85)] transition-colors duration-300 group-hover:text-tfa15-acc group-has-checked:text-tfa15-acc @max-tfa15fold:[writing-mode:horizontal-tb] @max-tfa15fold:rotate-0">What is included</h3>
          </label>
          <div class="grid min-w-0 items-end overflow-hidden @max-tfa15fold:min-h-0">
            <div class="w-[max(260px,26cqi)] translate-x-3.5 py-[22px] pl-2 pr-6 opacity-0 transition-[translate,opacity] delay-150 duration-500 ease-[cubic-bezier(0.3,0.8,0.25,1)] group-has-checked:translate-x-0 group-has-checked:opacity-100 motion-reduce:transition-none @max-tfa15fold:w-full @max-tfa15fold:px-5 @max-tfa15fold:pb-5 @max-tfa15fold:pt-0">
              <h2 class="text-[clamp(17px,2.2vw,22px)] font-extrabold tracking-[-0.02em] text-white [text-shadow:0_1px_14px_oklch(0.15_0.03_260/0.8)]">What does the price include?</h2>
              <p class="mt-2.5 text-[13.5px] leading-[1.65] text-white/90 [text-shadow:0_1px_12px_oklch(0.15_0.03_260/0.75)]">Guides, refuge nights, breakfasts and dinners, luggage transfer between stages and safety kit. Flights, lunches and insurance are yours — full packing list on booking.</p>
            </div>
          </div>
        </div>
        <div class="group relative grid flex-1 overflow-hidden rounded-[18px] bg-[linear-gradient(oklch(0.2_0.03_260/0.25),oklch(0.15_0.03_260/0.7)),url('https://images.unsplash.com/photo-1522163182402-834f871fd851?q=80&w=1200&auto=format&fit=crop')] bg-cover bg-center outline-2 outline-offset-[3px] outline-transparent transition-[grid-template-columns,grid-template-rows,flex-grow,outline-color] duration-600 ease-[cubic-bezier(0.3,0.8,0.25,1)] grid-cols-[64px_0fr] has-checked:grid-cols-[64px_1fr] has-checked:grow-[3.2] [&:not(:has(:checked)):hover]:grow-[1.15] has-focus-visible:outline-tfa15-acc @max-tfa15fold:grid-cols-[1fr] @max-tfa15fold:grid-rows-[56px_0fr] @max-tfa15fold:has-checked:grid-cols-[1fr] @max-tfa15fold:has-checked:grid-rows-[56px_1fr] @max-tfa15fold:has-checked:grow-[1] motion-reduce:transition-none">
          <input id="tfa15-p4" type="radio" name="tfa15" class="absolute opacity-0 pointer-events-none">
          <label for="tfa15-p4" class="grid min-w-11 cursor-pointer items-end justify-items-center py-[18px] @max-tfa15fold:min-h-11 @max-tfa15fold:place-items-center @max-tfa15fold:justify-items-start @max-tfa15fold:px-5 @max-tfa15fold:py-0">
            <h3 class="[writing-mode:vertical-rl] rotate-180 text-[13.5px] font-bold uppercase tracking-[0.06em] text-white [text-shadow:0_1px_12px_oklch(0.15_0.03_260/0.85)] transition-colors duration-300 group-hover:text-tfa15-acc group-has-checked:text-tfa15-acc @max-tfa15fold:[writing-mode:horizontal-tb] @max-tfa15fold:rotate-0">Group size</h3>
          </label>
          <div class="grid min-w-0 items-end overflow-hidden @max-tfa15fold:min-h-0">
            <div class="w-[max(260px,26cqi)] translate-x-3.5 py-[22px] pl-2 pr-6 opacity-0 transition-[translate,opacity] delay-150 duration-500 ease-[cubic-bezier(0.3,0.8,0.25,1)] group-has-checked:translate-x-0 group-has-checked:opacity-100 motion-reduce:transition-none @max-tfa15fold:w-full @max-tfa15fold:px-5 @max-tfa15fold:pb-5 @max-tfa15fold:pt-0">
              <h2 class="text-[clamp(17px,2.2vw,22px)] font-extrabold tracking-[-0.02em] text-white [text-shadow:0_1px_14px_oklch(0.15_0.03_260/0.8)]">How big are the groups?</h2>
              <p class="mt-2.5 text-[13.5px] leading-[1.65] text-white/90 [text-shadow:0_1px_12px_oklch(0.15_0.03_260/0.75)]">Max 10, average 7, two certified guides per group. Solo travellers are half of every departure — the refuge table does the introductions by night two.</p>
            </div>
          </div>
        </div>
        <div class="group relative grid flex-1 overflow-hidden rounded-[18px] bg-[linear-gradient(oklch(0.2_0.03_260/0.25),oklch(0.15_0.03_260/0.7)),url('https://images.unsplash.com/photo-1476514525535-07fb3b4ae5f1?q=80&w=1200&auto=format&fit=crop')] bg-cover bg-center outline-2 outline-offset-[3px] outline-transparent transition-[grid-template-columns,grid-template-rows,flex-grow,outline-color] duration-600 ease-[cubic-bezier(0.3,0.8,0.25,1)] grid-cols-[64px_0fr] has-checked:grid-cols-[64px_1fr] has-checked:grow-[3.2] [&:not(:has(:checked)):hover]:grow-[1.15] has-focus-visible:outline-tfa15-acc @max-tfa15fold:grid-cols-[1fr] @max-tfa15fold:grid-rows-[56px_0fr] @max-tfa15fold:has-checked:grid-cols-[1fr] @max-tfa15fold:has-checked:grid-rows-[56px_1fr] @max-tfa15fold:has-checked:grow-[1] motion-reduce:transition-none">
          <input id="tfa15-p5" type="radio" name="tfa15" class="absolute opacity-0 pointer-events-none">
          <label for="tfa15-p5" class="grid min-w-11 cursor-pointer items-end justify-items-center py-[18px] @max-tfa15fold:min-h-11 @max-tfa15fold:place-items-center @max-tfa15fold:justify-items-start @max-tfa15fold:px-5 @max-tfa15fold:py-0">
            <h3 class="[writing-mode:vertical-rl] rotate-180 text-[13.5px] font-bold uppercase tracking-[0.06em] text-white [text-shadow:0_1px_12px_oklch(0.15_0.03_260/0.85)] transition-colors duration-300 group-hover:text-tfa15-acc group-has-checked:text-tfa15-acc @max-tfa15fold:[writing-mode:horizontal-tb] @max-tfa15fold:rotate-0">Cancellation</h3>
          </label>
          <div class="grid min-w-0 items-end overflow-hidden @max-tfa15fold:min-h-0">
            <div class="w-[max(260px,26cqi)] translate-x-3.5 py-[22px] pl-2 pr-6 opacity-0 transition-[translate,opacity] delay-150 duration-500 ease-[cubic-bezier(0.3,0.8,0.25,1)] group-has-checked:translate-x-0 group-has-checked:opacity-100 motion-reduce:transition-none @max-tfa15fold:w-full @max-tfa15fold:px-5 @max-tfa15fold:pb-5 @max-tfa15fold:pt-0">
              <h2 class="text-[clamp(17px,2.2vw,22px)] font-extrabold tracking-[-0.02em] text-white [text-shadow:0_1px_14px_oklch(0.15_0.03_260/0.8)]">What if I need to cancel?</h2>
              <p class="mt-2.5 text-[13.5px] leading-[1.65] text-white/90 [text-shadow:0_1px_12px_oklch(0.15_0.03_260/0.75)]">Free date changes until 30 days out, full refund minus deposit until 14, and the deposit converts to credit after that. Weather cancellations on our side refund everything.</p>
            </div>
          </div>
        </div>
      </div>

      <p class="mt-5 text-[12.5px] text-white/80">grid-cols-[0fr] → [1fr] plus a grow transition — demo 10's trick, rotated. Folds vertical in narrow containers.</p>
    </div>
  </div>
</section>
@import "tailwindcss";

@theme {
  --color-tfa15-bg: #1b1d2a;
  --color-tfa15-bg: oklch(0.2 0.02 260);
  --color-tfa15-acc: #ffc94d;
  --color-tfa15-acc: oklch(0.85 0.15 80);
  --font-tfa15-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
  /* Matches the CSS twin's @container (width < 720px) fold. The
       built-in 3xl is 768px, which stacked the panels while there was
       still room for the sideways layout. */
  --container-tfa15fold: 45rem;
}

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

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-tfa15-bg: #1b1d2a;
  --color-tfa15-bg: oklch(0.2 0.02 260);
  --color-tfa15-acc: #ffc94d;
  --color-tfa15-acc: oklch(0.85 0.15 80);
  --font-tfa15-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
  /* Matches the CSS twin's @container (width < 720px) fold. The
       built-in 3xl is 768px, which stacked the panels while there was
       still room for the sideways layout. */
  --container-tfa15fold: 45rem;
}

.tfa-15 {
  width: 100%;
  min-height: 100svh;
}
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&display=swap">

What changed in the port

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

  • Three :has() rules became three variants on the element they style: has-checked:, [&:not(:has(:checked)):hover]: and has-focus-visible:. This is the demo where the utility version is genuinely easier to read than the CSS — the panel now lists its own state machine.
  • The entire vertical fold is a @max-tfa15fold: variant layer instead of a second CSS block, which means the two layouts sit in the same class list and can be diffed by eye. It is long, and it is still the better trade.
  • [writing-mode:vertical-rl] is an arbitrary property because writing mode is not a design-scale value; sideways-lr would be semantically nicer but only reached Safari in 2024, and vertical-rl plus rotate-180 reads identically much further back.
  • UI upgrade from the CSS original: body copy moved from a muted oklch(0.88) token to full-opacity white at 90% with a per-element text-shadow, which holds 4.5:1 over the brightest part of every photo — the original's spine labels in particular washed out on the snow images.
  • UI upgrade: the focus ring is now driven by has-focus-visible: on the panel rather than a :has(:focus-visible) rule that only tinted the outline colour, so keyboard users get the same 2px accent ring the rest of the collection uses.
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 Horizontal FAQ Accordion with Sideways Expanding Panels
Source: https://codefronts.com/snippets/tailwind-css-faq-accordion/tailwind-horizontal-faq-accordion-sideways-panels/

The showpiece: five photo panels standing shoulder to shoulder, the active one unfolding sideways to reveal its answer while the others compress into spines with vertically-written titles. Demo 10's fr-unit trick rotated 90° — grid-cols-[64px_0fr] to [64px_1fr] — plus a grow-[3.2] transition, [writing-mode:vertical-rl] spines, and radio state, so it stays pure Tailwind.
## HTML
```html
<section class="tfa-15 w-full min-h-svh font-tfa15-sans text-white">
  <div class="@container grid min-h-svh w-full place-items-center bg-tfa15-bg px-5 py-12">
    <div class="w-[min(1020px,100%)]">
      <header>
        <h1 class="text-[clamp(26px,4.4vw,40px)] font-extrabold tracking-[-0.025em]">Plan your expedition</h1>
        <p class="mt-3 max-w-[54ch] text-[14.5px] leading-relaxed text-white/85">Five questions standing sideways — the open one unfolds. Arrow keys move between panels.</p>
      </header>

      <div class="mt-7 flex min-h-[420px] gap-2.5 @max-tfa15fold:min-h-0 @max-tfa15fold:flex-col">
        <div class="group relative grid flex-1 overflow-hidden rounded-[18px] bg-[linear-gradient(oklch(0.2_0.03_260/0.25),oklch(0.15_0.03_260/0.7)),url('https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?q=80&w=1200&auto=format&fit=crop')] bg-cover bg-center outline-2 outline-offset-[3px] outline-transparent transition-[grid-template-columns,grid-template-rows,flex-grow,outline-color] duration-600 ease-[cubic-bezier(0.3,0.8,0.25,1)] grid-cols-[64px_0fr] has-checked:grid-cols-[64px_1fr] has-checked:grow-[3.2] [&:not(:has(:checked)):hover]:grow-[1.15] has-focus-visible:outline-tfa15-acc @max-tfa15fold:grid-cols-[1fr] @max-tfa15fold:grid-rows-[56px_0fr] @max-tfa15fold:has-checked:grid-cols-[1fr] @max-tfa15fold:has-checked:grid-rows-[56px_1fr] @max-tfa15fold:has-checked:grow-[1] motion-reduce:transition-none">
          <input id="tfa15-p1" type="radio" name="tfa15" class="absolute opacity-0 pointer-events-none" checked>
          <label for="tfa15-p1" class="grid min-w-11 cursor-pointer items-end justify-items-center py-[18px] @max-tfa15fold:min-h-11 @max-tfa15fold:place-items-center @max-tfa15fold:justify-items-start @max-tfa15fold:px-5 @max-tfa15fold:py-0">
            <h3 class="[writing-mode:vertical-rl] rotate-180 text-[13.5px] font-bold uppercase tracking-[0.06em] text-white [text-shadow:0_1px_12px_oklch(0.15_0.03_260/0.85)] transition-colors duration-300 group-hover:text-tfa15-acc group-has-checked:text-tfa15-acc @max-tfa15fold:[writing-mode:horizontal-tb] @max-tfa15fold:rotate-0">When to go?</h3>
          </label>
          <div class="grid min-w-0 items-end overflow-hidden @max-tfa15fold:min-h-0">
            <div class="w-[max(260px,26cqi)] translate-x-3.5 py-[22px] pl-2 pr-6 opacity-0 transition-[translate,opacity] delay-150 duration-500 ease-[cubic-bezier(0.3,0.8,0.25,1)] group-has-checked:translate-x-0 group-has-checked:opacity-100 motion-reduce:transition-none @max-tfa15fold:w-full @max-tfa15fold:px-5 @max-tfa15fold:pb-5 @max-tfa15fold:pt-0">
              <h2 class="text-[clamp(17px,2.2vw,22px)] font-extrabold tracking-[-0.02em] text-white [text-shadow:0_1px_14px_oklch(0.15_0.03_260/0.8)]">When is the best season?</h2>
              <p class="mt-2.5 text-[13.5px] leading-[1.65] text-white/90 [text-shadow:0_1px_12px_oklch(0.15_0.03_260/0.75)]">June through September for the high passes — long days, stable weather, open refuges. Shoulder months halve the crowds but add real weather risk above 2,500m.</p>
            </div>
          </div>
        </div>
        <div class="group relative grid flex-1 overflow-hidden rounded-[18px] bg-[linear-gradient(oklch(0.2_0.03_260/0.25),oklch(0.15_0.03_260/0.7)),url('https://images.unsplash.com/photo-1551632811-561732d1e306?q=80&w=1200&auto=format&fit=crop')] bg-cover bg-center outline-2 outline-offset-[3px] outline-transparent transition-[grid-template-columns,grid-template-rows,flex-grow,outline-color] duration-600 ease-[cubic-bezier(0.3,0.8,0.25,1)] grid-cols-[64px_0fr] has-checked:grid-cols-[64px_1fr] has-checked:grow-[3.2] [&:not(:has(:checked)):hover]:grow-[1.15] has-focus-visible:outline-tfa15-acc @max-tfa15fold:grid-cols-[1fr] @max-tfa15fold:grid-rows-[56px_0fr] @max-tfa15fold:has-checked:grid-cols-[1fr] @max-tfa15fold:has-checked:grid-rows-[56px_1fr] @max-tfa15fold:has-checked:grow-[1] motion-reduce:transition-none">
          <input id="tfa15-p2" type="radio" name="tfa15" class="absolute opacity-0 pointer-events-none">
          <label for="tfa15-p2" class="grid min-w-11 cursor-pointer items-end justify-items-center py-[18px] @max-tfa15fold:min-h-11 @max-tfa15fold:place-items-center @max-tfa15fold:justify-items-start @max-tfa15fold:px-5 @max-tfa15fold:py-0">
            <h3 class="[writing-mode:vertical-rl] rotate-180 text-[13.5px] font-bold uppercase tracking-[0.06em] text-white [text-shadow:0_1px_12px_oklch(0.15_0.03_260/0.85)] transition-colors duration-300 group-hover:text-tfa15-acc group-has-checked:text-tfa15-acc @max-tfa15fold:[writing-mode:horizontal-tb] @max-tfa15fold:rotate-0">Fitness level</h3>
          </label>
          <div class="grid min-w-0 items-end overflow-hidden @max-tfa15fold:min-h-0">
            <div class="w-[max(260px,26cqi)] translate-x-3.5 py-[22px] pl-2 pr-6 opacity-0 transition-[translate,opacity] delay-150 duration-500 ease-[cubic-bezier(0.3,0.8,0.25,1)] group-has-checked:translate-x-0 group-has-checked:opacity-100 motion-reduce:transition-none @max-tfa15fold:w-full @max-tfa15fold:px-5 @max-tfa15fold:pb-5 @max-tfa15fold:pt-0">
              <h2 class="text-[clamp(17px,2.2vw,22px)] font-extrabold tracking-[-0.02em] text-white [text-shadow:0_1px_14px_oklch(0.15_0.03_260/0.8)]">How fit do I need to be?</h2>
              <p class="mt-2.5 text-[13.5px] leading-[1.65] text-white/90 [text-shadow:0_1px_12px_oklch(0.15_0.03_260/0.75)]">Comfortable hiking 6–7 hours with a daypack, two days in a row. Our grade-2 routes need no technical skills; if you can do a hilly half-day hike smiling, twelve training weeks gets you there.</p>
            </div>
          </div>
        </div>
        <div class="group relative grid flex-1 overflow-hidden rounded-[18px] bg-[linear-gradient(oklch(0.2_0.03_260/0.25),oklch(0.15_0.03_260/0.7)),url('https://images.unsplash.com/photo-1501554728187-ce583db33af7?q=80&w=1200&auto=format&fit=crop')] bg-cover bg-center outline-2 outline-offset-[3px] outline-transparent transition-[grid-template-columns,grid-template-rows,flex-grow,outline-color] duration-600 ease-[cubic-bezier(0.3,0.8,0.25,1)] grid-cols-[64px_0fr] has-checked:grid-cols-[64px_1fr] has-checked:grow-[3.2] [&:not(:has(:checked)):hover]:grow-[1.15] has-focus-visible:outline-tfa15-acc @max-tfa15fold:grid-cols-[1fr] @max-tfa15fold:grid-rows-[56px_0fr] @max-tfa15fold:has-checked:grid-cols-[1fr] @max-tfa15fold:has-checked:grid-rows-[56px_1fr] @max-tfa15fold:has-checked:grow-[1] motion-reduce:transition-none">
          <input id="tfa15-p3" type="radio" name="tfa15" class="absolute opacity-0 pointer-events-none">
          <label for="tfa15-p3" class="grid min-w-11 cursor-pointer items-end justify-items-center py-[18px] @max-tfa15fold:min-h-11 @max-tfa15fold:place-items-center @max-tfa15fold:justify-items-start @max-tfa15fold:px-5 @max-tfa15fold:py-0">
            <h3 class="[writing-mode:vertical-rl] rotate-180 text-[13.5px] font-bold uppercase tracking-[0.06em] text-white [text-shadow:0_1px_12px_oklch(0.15_0.03_260/0.85)] transition-colors duration-300 group-hover:text-tfa15-acc group-has-checked:text-tfa15-acc @max-tfa15fold:[writing-mode:horizontal-tb] @max-tfa15fold:rotate-0">What is included</h3>
          </label>
          <div class="grid min-w-0 items-end overflow-hidden @max-tfa15fold:min-h-0">
            <div class="w-[max(260px,26cqi)] translate-x-3.5 py-[22px] pl-2 pr-6 opacity-0 transition-[translate,opacity] delay-150 duration-500 ease-[cubic-bezier(0.3,0.8,0.25,1)] group-has-checked:translate-x-0 group-has-checked:opacity-100 motion-reduce:transition-none @max-tfa15fold:w-full @max-tfa15fold:px-5 @max-tfa15fold:pb-5 @max-tfa15fold:pt-0">
              <h2 class="text-[clamp(17px,2.2vw,22px)] font-extrabold tracking-[-0.02em] text-white [text-shadow:0_1px_14px_oklch(0.15_0.03_260/0.8)]">What does the price include?</h2>
              <p class="mt-2.5 text-[13.5px] leading-[1.65] text-white/90 [text-shadow:0_1px_12px_oklch(0.15_0.03_260/0.75)]">Guides, refuge nights, breakfasts and dinners, luggage transfer between stages and safety kit. Flights, lunches and insurance are yours — full packing list on booking.</p>
            </div>
          </div>
        </div>
        <div class="group relative grid flex-1 overflow-hidden rounded-[18px] bg-[linear-gradient(oklch(0.2_0.03_260/0.25),oklch(0.15_0.03_260/0.7)),url('https://images.unsplash.com/photo-1522163182402-834f871fd851?q=80&w=1200&auto=format&fit=crop')] bg-cover bg-center outline-2 outline-offset-[3px] outline-transparent transition-[grid-template-columns,grid-template-rows,flex-grow,outline-color] duration-600 ease-[cubic-bezier(0.3,0.8,0.25,1)] grid-cols-[64px_0fr] has-checked:grid-cols-[64px_1fr] has-checked:grow-[3.2] [&:not(:has(:checked)):hover]:grow-[1.15] has-focus-visible:outline-tfa15-acc @max-tfa15fold:grid-cols-[1fr] @max-tfa15fold:grid-rows-[56px_0fr] @max-tfa15fold:has-checked:grid-cols-[1fr] @max-tfa15fold:has-checked:grid-rows-[56px_1fr] @max-tfa15fold:has-checked:grow-[1] motion-reduce:transition-none">
          <input id="tfa15-p4" type="radio" name="tfa15" class="absolute opacity-0 pointer-events-none">
          <label for="tfa15-p4" class="grid min-w-11 cursor-pointer items-end justify-items-center py-[18px] @max-tfa15fold:min-h-11 @max-tfa15fold:place-items-center @max-tfa15fold:justify-items-start @max-tfa15fold:px-5 @max-tfa15fold:py-0">
            <h3 class="[writing-mode:vertical-rl] rotate-180 text-[13.5px] font-bold uppercase tracking-[0.06em] text-white [text-shadow:0_1px_12px_oklch(0.15_0.03_260/0.85)] transition-colors duration-300 group-hover:text-tfa15-acc group-has-checked:text-tfa15-acc @max-tfa15fold:[writing-mode:horizontal-tb] @max-tfa15fold:rotate-0">Group size</h3>
          </label>
          <div class="grid min-w-0 items-end overflow-hidden @max-tfa15fold:min-h-0">
            <div class="w-[max(260px,26cqi)] translate-x-3.5 py-[22px] pl-2 pr-6 opacity-0 transition-[translate,opacity] delay-150 duration-500 ease-[cubic-bezier(0.3,0.8,0.25,1)] group-has-checked:translate-x-0 group-has-checked:opacity-100 motion-reduce:transition-none @max-tfa15fold:w-full @max-tfa15fold:px-5 @max-tfa15fold:pb-5 @max-tfa15fold:pt-0">
              <h2 class="text-[clamp(17px,2.2vw,22px)] font-extrabold tracking-[-0.02em] text-white [text-shadow:0_1px_14px_oklch(0.15_0.03_260/0.8)]">How big are the groups?</h2>
              <p class="mt-2.5 text-[13.5px] leading-[1.65] text-white/90 [text-shadow:0_1px_12px_oklch(0.15_0.03_260/0.75)]">Max 10, average 7, two certified guides per group. Solo travellers are half of every departure — the refuge table does the introductions by night two.</p>
            </div>
          </div>
        </div>
        <div class="group relative grid flex-1 overflow-hidden rounded-[18px] bg-[linear-gradient(oklch(0.2_0.03_260/0.25),oklch(0.15_0.03_260/0.7)),url('https://images.unsplash.com/photo-1476514525535-07fb3b4ae5f1?q=80&w=1200&auto=format&fit=crop')] bg-cover bg-center outline-2 outline-offset-[3px] outline-transparent transition-[grid-template-columns,grid-template-rows,flex-grow,outline-color] duration-600 ease-[cubic-bezier(0.3,0.8,0.25,1)] grid-cols-[64px_0fr] has-checked:grid-cols-[64px_1fr] has-checked:grow-[3.2] [&:not(:has(:checked)):hover]:grow-[1.15] has-focus-visible:outline-tfa15-acc @max-tfa15fold:grid-cols-[1fr] @max-tfa15fold:grid-rows-[56px_0fr] @max-tfa15fold:has-checked:grid-cols-[1fr] @max-tfa15fold:has-checked:grid-rows-[56px_1fr] @max-tfa15fold:has-checked:grow-[1] motion-reduce:transition-none">
          <input id="tfa15-p5" type="radio" name="tfa15" class="absolute opacity-0 pointer-events-none">
          <label for="tfa15-p5" class="grid min-w-11 cursor-pointer items-end justify-items-center py-[18px] @max-tfa15fold:min-h-11 @max-tfa15fold:place-items-center @max-tfa15fold:justify-items-start @max-tfa15fold:px-5 @max-tfa15fold:py-0">
            <h3 class="[writing-mode:vertical-rl] rotate-180 text-[13.5px] font-bold uppercase tracking-[0.06em] text-white [text-shadow:0_1px_12px_oklch(0.15_0.03_260/0.85)] transition-colors duration-300 group-hover:text-tfa15-acc group-has-checked:text-tfa15-acc @max-tfa15fold:[writing-mode:horizontal-tb] @max-tfa15fold:rotate-0">Cancellation</h3>
          </label>
          <div class="grid min-w-0 items-end overflow-hidden @max-tfa15fold:min-h-0">
            <div class="w-[max(260px,26cqi)] translate-x-3.5 py-[22px] pl-2 pr-6 opacity-0 transition-[translate,opacity] delay-150 duration-500 ease-[cubic-bezier(0.3,0.8,0.25,1)] group-has-checked:translate-x-0 group-has-checked:opacity-100 motion-reduce:transition-none @max-tfa15fold:w-full @max-tfa15fold:px-5 @max-tfa15fold:pb-5 @max-tfa15fold:pt-0">
              <h2 class="text-[clamp(17px,2.2vw,22px)] font-extrabold tracking-[-0.02em] text-white [text-shadow:0_1px_14px_oklch(0.15_0.03_260/0.8)]">What if I need to cancel?</h2>
              <p class="mt-2.5 text-[13.5px] leading-[1.65] text-white/90 [text-shadow:0_1px_12px_oklch(0.15_0.03_260/0.75)]">Free date changes until 30 days out, full refund minus deposit until 14, and the deposit converts to credit after that. Weather cancellations on our side refund everything.</p>
            </div>
          </div>
        </div>
      </div>

      <p class="mt-5 text-[12.5px] text-white/80">grid-cols-[0fr] → [1fr] plus a grow transition — demo 10's trick, rotated. Folds vertical in narrow containers.</p>
    </div>
  </div>
</section>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-tfa15-bg: #1b1d2a;
  --color-tfa15-bg: oklch(0.2 0.02 260);
  --color-tfa15-acc: #ffc94d;
  --color-tfa15-acc: oklch(0.85 0.15 80);
  --font-tfa15-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
  /* Matches the CSS twin's @container (width < 720px) fold. The
       built-in 3xl is 768px, which stacked the panels while there was
       still room for the sideways layout. */
  --container-tfa15fold: 45rem;
}

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

How this works

Two animations, one curve. Every panel is a grid of a fixed 64px spine plus a fraction-unit body; the checked panel's fraction opens from 0fr to 1fr while its flex-grow travels 1→3.2. flex-grow is a plain number, so it transitions too, letting the active panel claim more of the strip while siblings share the rest.

The state relationships are all has-*. The radio lives inside the panel, so the panel styles itself with has-checked:, invites with [&:not(:has(:checked)):hover]:, and shows its focus ring with has-focus-visible:. In CSS these were three :has() rules a long way from the markup; here they read as a list of conditions on the element they affect.

The fold is the honest part. Horizontal disclosure is a display pattern for three to six visual items on wide canvases, not an information pattern. Rather than pretending spines work on phones, @max-tfa15fold: variants rebuild the whole thing as a normal vertical accordion: rows instead of columns, horizontal writing mode, full-width bodies.

Make it yours

  • Panel count: three to six. Beyond that spines go sliver-thin.
  • Greed: has-checked:grow-[3.2] is how much of the strip the open panel claims.
  • Images: one background-image utility per panel; the gradient overlay keeps spine text readable over any photo.
  • Vertical fold: the @max-tfa15fold: layer is a complete second layout — customise it like an ordinary accordion.

Gotchas — read before shipping

  • min-w-0 on the expanding body is the horizontal twin of demo 10's min-h-0. Without it the fr column refuses to close fully.
  • Animating width instead of the grid track plus grow reflows text every frame; the fr version lets the browser crop a clipped body instead of rewrapping.
  • [writing-mode:vertical-rl] without the 180° rotation reads bottom-to-top for Latin labels. Always pair them.
  • Radios in one group give arrow-key navigation for free — but make the label fill the whole spine so the hit target is not just the text.

Browser support

ChromeSafariFirefoxEdge
111+16.4+128+111+

grid-template-columns interpolation matches demo 10's floors and flex-grow transitions are ancient; the real floor is :has() (Chrome 105 / Safari 15.4 / Firefox 121), which drives every state here.

Techniques used in this demo

Utilitiesfirst-class utility or variant

Search CodeFronts

Loading…