Tailwind v4MIT licensed

Expandable Read More Tailwind Blockquote

A long quote clamped to three lines with a fade, expanding on a native <details> toggle — no JavaScript. Utilities handle the clamp release (group-has-[[open]]/card:line-clamp-none), the label swap and the chevron; a six-line CSS block adds the smooth height animation via ::details-content + interpolate-size, which have no Tailwind variant.

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="tbq-24 w-full min-h-svh grid place-items-center bg-tbq24-bg px-5 py-14 font-tbq24-serif text-tbq24-ink" aria-label="Expandable read more blockquote demo">
  <div class="grid w-full justify-items-center gap-7">
    <figure class="group/card flex w-full max-w-[540px] flex-col rounded-[18px] border border-black/8 bg-tbq24-card p-[clamp(24px,4vw,34px)] shadow-[0_2px_6px_oklch(0.35_0.03_45/0.06),0_16px_40px_oklch(0.35_0.03_45/0.09)]">
      <p class="-order-2 mb-3.5 font-tbq24-sans text-[11.5px] font-bold tracking-[0.16em] uppercase text-tbq24-acc-ink">From “The Craftsman” · Richard Sennett</p>
      <details class="group/d contents">
        <summary class="order-1 mt-3 inline-flex min-h-11 cursor-pointer list-none items-center gap-2.5 self-start rounded-lg pe-1 font-tbq24-sans text-[13.5px] font-semibold text-tbq24-acc-ink hover:underline hover:underline-offset-3 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tbq24-acc [&::-webkit-details-marker]:hidden">
          <span class="group-open/d:hidden">Read the full quote</span>
          <span class="hidden group-open/d:inline">Show less</span>
          <span aria-hidden="true" class="grid size-7 place-items-center rounded-full bg-tbq24-acc/12 transition-transform duration-300 group-open/d:rotate-180 motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="14" height="14"><path d="M4 6.2 8 10l4-3.8" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
        </summary>
        <blockquote>
          <p class="pt-[0.6em] text-[17.5px] leading-[1.68] text-tbq24-quiet text-pretty">It is the ability to focus on the work rather than ourselves that makes craft possible at all — and every workshop, digital or wooden, is finally an argument for patience over speed.</p>
        </blockquote>
      </details>
      <blockquote class="relative -order-1 after:pointer-events-none after:absolute after:inset-x-0 after:bottom-0 after:h-[1.7em] after:bg-linear-to-b after:from-transparent after:to-tbq24-card after:transition-opacity after:duration-300 group-has-[[open]]/card:after:opacity-0">
        <p class="line-clamp-3 text-[17.5px] leading-[1.68] text-tbq24-quiet text-pretty group-has-[[open]]/card:line-clamp-none">Craftsmanship names an enduring, basic human impulse: the desire to do a job well for its own sake. It cuts a far wider swath than skilled manual labor; it serves the programmer, the doctor, the artist, and the parent alike — anyone whose practice improves through the discipline of critique.</p>
      </blockquote>
    </figure>
    <p aria-hidden="true" class="rounded-full border border-black/10 bg-white px-3.5 py-2 font-tbq24-mono text-[11.5px] text-tbq24-mut">&lt;details&gt; · line-clamp-3 · group-has-[[open]]: · ::details-content</p>
  </div>
</section>
@import "tailwindcss";

@theme {
  --color-tbq24-bg: #f8f2f0;
  --color-tbq24-bg: oklch(0.965 0.007 40);
  --color-tbq24-card: #ffffff;
  --color-tbq24-card: oklch(1 0 0);
  --color-tbq24-ink: #281f1c;
  --color-tbq24-ink: oklch(0.25 0.015 45);
  --color-tbq24-quiet: #4a403c;
  --color-tbq24-quiet: oklch(0.38 0.015 45);
  --color-tbq24-mut: #6b615c;
  --color-tbq24-mut: oklch(0.5 0.015 45);
  --color-tbq24-acc: #bd5833;
  --color-tbq24-acc: oklch(0.58 0.14 40);
  --color-tbq24-acc-ink: #9c4022;
  --color-tbq24-acc-ink: oklch(0.49 0.13 38);
  --font-tbq24-serif: 'Newsreader', Georgia, serif;
  --font-tbq24-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
  --font-tbq24-mono: 'JetBrains Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
   stage is sized before the browser build compiles. */

.tbq-24 {
  width: 100%;
  min-height: 100svh;
}
/* ::details-content has no Tailwind variant, and interpolate-size is what lets block-size reach auto. */

@supports (interpolate-size: allow-keywords) {
  .tbq-24 {
    interpolate-size: allow-keywords;
  }

  .tbq-24 details::details-content {
    block-size: 0;
    overflow: hidden;
    transition: block-size 0.45s cubic-bezier(0.2, 0.7, 0.2, 1), content-visibility 0.45s allow-discrete;
  }

  .tbq-24 details[open]::details-content {
    block-size: auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  .tbq-24 details::details-content {
    transition: none;
  }
}

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-tbq24-bg: #f8f2f0;
  --color-tbq24-bg: oklch(0.965 0.007 40);
  --color-tbq24-card: #ffffff;
  --color-tbq24-card: oklch(1 0 0);
  --color-tbq24-ink: #281f1c;
  --color-tbq24-ink: oklch(0.25 0.015 45);
  --color-tbq24-quiet: #4a403c;
  --color-tbq24-quiet: oklch(0.38 0.015 45);
  --color-tbq24-mut: #6b615c;
  --color-tbq24-mut: oklch(0.5 0.015 45);
  --color-tbq24-acc: #bd5833;
  --color-tbq24-acc: oklch(0.58 0.14 40);
  --color-tbq24-acc-ink: #9c4022;
  --color-tbq24-acc-ink: oklch(0.49 0.13 38);
  --font-tbq24-serif: 'Newsreader', Georgia, serif;
  --font-tbq24-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
  --font-tbq24-mono: 'JetBrains Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
   stage is sized before the browser build compiles. */

.tbq-24 {
  width: 100%;
  min-height: 100svh;
}
/* ::details-content has no Tailwind variant, and interpolate-size is what lets block-size reach auto. */

@supports (interpolate-size: allow-keywords) {
  .tbq-24 {
    interpolate-size: allow-keywords;
  }

  .tbq-24 details::details-content {
    block-size: 0;
    overflow: hidden;
    transition: block-size 0.45s cubic-bezier(0.2, 0.7, 0.2, 1), content-visibility 0.45s allow-discrete;
  }

  .tbq-24 details[open]::details-content {
    block-size: auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  .tbq-24 details::details-content {
    transition: none;
  }
}
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:ital,opsz,wght@0,6..72,400..700;1,6..72,400..700&family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600;700&display=swap">

What changed in the port

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

  • .card:has(details[open]) .preview p{-webkit-line-clamp:none} became group-has-[[open]]/card:line-clamp-none on the paragraph; the label swap and chevron use the named group-open/d: variant.
  • ::details-content and interpolate-size stayed in CSS — exactly the split the Tailwind FAQ collection documents: utilities for everything except one pseudo-element.
  • UI upgrade from the CSS original: bug fix — the original only set the root's width/min-height inside @supports (interpolate-size…), so Safari and Firefox lost the full-bleed stage; the root rule is now unconditional. The kicker also no longer jumps below the preview (-order-2).
  • UI upgrade: the chevron sits in a tinted 28px disc, the toggle row is 44px, and link colour darkened to acc-ink (4.9:1 on white, was 3.8:1).
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: Expandable Read More Tailwind Blockquote
Source: https://codefronts.com/snippets/tailwind-css-blockquotes/expandable-read-more-tailwind-blockquote/

A long quote clamped to three lines with a fade, expanding on a native <details> toggle — no JavaScript. Utilities handle the clamp release (group-has-[[open]]/card:line-clamp-none), the label swap and the chevron; a six-line CSS block adds the smooth height animation via ::details-content + interpolate-size, which have no Tailwind variant.
## HTML
```html
<section class="tbq-24 w-full min-h-svh grid place-items-center bg-tbq24-bg px-5 py-14 font-tbq24-serif text-tbq24-ink" aria-label="Expandable read more blockquote demo">
  <div class="grid w-full justify-items-center gap-7">
    <figure class="group/card flex w-full max-w-[540px] flex-col rounded-[18px] border border-black/8 bg-tbq24-card p-[clamp(24px,4vw,34px)] shadow-[0_2px_6px_oklch(0.35_0.03_45/0.06),0_16px_40px_oklch(0.35_0.03_45/0.09)]">
      <p class="-order-2 mb-3.5 font-tbq24-sans text-[11.5px] font-bold tracking-[0.16em] uppercase text-tbq24-acc-ink">From “The Craftsman” · Richard Sennett</p>
      <details class="group/d contents">
        <summary class="order-1 mt-3 inline-flex min-h-11 cursor-pointer list-none items-center gap-2.5 self-start rounded-lg pe-1 font-tbq24-sans text-[13.5px] font-semibold text-tbq24-acc-ink hover:underline hover:underline-offset-3 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-tbq24-acc [&::-webkit-details-marker]:hidden">
          <span class="group-open/d:hidden">Read the full quote</span>
          <span class="hidden group-open/d:inline">Show less</span>
          <span aria-hidden="true" class="grid size-7 place-items-center rounded-full bg-tbq24-acc/12 transition-transform duration-300 group-open/d:rotate-180 motion-reduce:transition-none"><svg viewBox="0 0 16 16" width="14" height="14"><path d="M4 6.2 8 10l4-3.8" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
        </summary>
        <blockquote>
          <p class="pt-[0.6em] text-[17.5px] leading-[1.68] text-tbq24-quiet text-pretty">It is the ability to focus on the work rather than ourselves that makes craft possible at all — and every workshop, digital or wooden, is finally an argument for patience over speed.</p>
        </blockquote>
      </details>
      <blockquote class="relative -order-1 after:pointer-events-none after:absolute after:inset-x-0 after:bottom-0 after:h-[1.7em] after:bg-linear-to-b after:from-transparent after:to-tbq24-card after:transition-opacity after:duration-300 group-has-[[open]]/card:after:opacity-0">
        <p class="line-clamp-3 text-[17.5px] leading-[1.68] text-tbq24-quiet text-pretty group-has-[[open]]/card:line-clamp-none">Craftsmanship names an enduring, basic human impulse: the desire to do a job well for its own sake. It cuts a far wider swath than skilled manual labor; it serves the programmer, the doctor, the artist, and the parent alike — anyone whose practice improves through the discipline of critique.</p>
      </blockquote>
    </figure>
    <p aria-hidden="true" class="rounded-full border border-black/10 bg-white px-3.5 py-2 font-tbq24-mono text-[11.5px] text-tbq24-mut">&lt;details&gt; · line-clamp-3 · group-has-[[open]]: · ::details-content</p>
  </div>
</section>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-tbq24-bg: #f8f2f0;
  --color-tbq24-bg: oklch(0.965 0.007 40);
  --color-tbq24-card: #ffffff;
  --color-tbq24-card: oklch(1 0 0);
  --color-tbq24-ink: #281f1c;
  --color-tbq24-ink: oklch(0.25 0.015 45);
  --color-tbq24-quiet: #4a403c;
  --color-tbq24-quiet: oklch(0.38 0.015 45);
  --color-tbq24-mut: #6b615c;
  --color-tbq24-mut: oklch(0.5 0.015 45);
  --color-tbq24-acc: #bd5833;
  --color-tbq24-acc: oklch(0.58 0.14 40);
  --color-tbq24-acc-ink: #9c4022;
  --color-tbq24-acc-ink: oklch(0.49 0.13 38);
  --font-tbq24-serif: 'Newsreader', Georgia, serif;
  --font-tbq24-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
  --font-tbq24-mono: 'JetBrains Mono', ui-monospace, monospace;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
   stage is sized before the browser build compiles. */

.tbq-24 {
  width: 100%;
  min-height: 100svh;
}
/* ::details-content has no Tailwind variant, and interpolate-size is what lets block-size reach auto. */

@supports (interpolate-size: allow-keywords) {
  .tbq-24 {
    interpolate-size: allow-keywords;
  }

  .tbq-24 details::details-content {
    block-size: 0;
    overflow: hidden;
    transition: block-size 0.45s cubic-bezier(0.2, 0.7, 0.2, 1), content-visibility 0.45s allow-discrete;
  }

  .tbq-24 details[open]::details-content {
    block-size: auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  .tbq-24 details::details-content {
    transition: none;
  }
}
```

How this works

Native disclosure, custom layout. display:contents on the <details> lets its summary and content join the card's flex column, so order-1 can put the toggle after the text while the source keeps summary first (as HTML requires).

<figure class="group/card flex flex-col">
  <details class="group/d contents"><summary class="order-1 …">…</summary>…</details>
  <blockquote class="-order-1"><p class="line-clamp-3
    group-has-[[open]]/card:line-clamp-none">

The animation is the one thing that stays CSS. ::details-content is a pseudo-element Tailwind has no variant for, and interpolate-size: allow-keywords is what lets block-size animate to auto. Browsers without it open instantly — still correct.

Make it yours

  • Clamp more lines: line-clamp-5.
  • Button style toggle: give the summary rounded-full bg-tbq24-acc px-4 text-white.
  • Start open: add the open attribute to <details>.

Gotchas — read before shipping

  • Keep the kicker at -order-2 — once the preview uses -order-1 it would otherwise jump above the kicker.
  • interpolate-size is inherited: setting it on .tbq-24 scopes it to the demo instead of the whole page.
  • Text hidden in a closed <details> is still findable with Ctrl-F in Chrome (auto-expands), which is a feature, not a bug.

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 111+.

The height animation needs ::details-content + interpolate-size (Chrome 131); elsewhere the panel opens instantly. :has() is Firefox 121+.

Techniques used in this demo

Utilitiesfirst-class utility or variant

Search CodeFronts

Loading…