Open demo

CSS code

HTML
<article class="xcard">
  <details open>
    <summary>
      <span class="ic" aria-hidden="true"><svg viewBox="0 0 24 24"><path d="M4 7h16M4 12h16M4 17h10"/></svg></span>
      <span><span class="ttl">What is included in the Team plan</span><span class="hint">Seats, storage and support</span></span>
      <svg class="chev" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 9l6 6 6-6"/></svg>
    </summary>
    <div class="panel"><div class="inner">
      Everything in Starter, plus the controls a team needs once more than a couple of people
      depend on the account.
      <ul><li>Up to 25 seats with per-seat permissions</li>
        <li>1 TB of shared storage</li>
        <li>Audit log and SSO</li></ul>
    </div></div>
  </details>
</article>

<article class="xcard">
  <details>
    <summary>
      <span class="ic" aria-hidden="true"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M12 11v5M12 8h.01"/></svg></span>
      <span><span class="ttl">How billing works when seats change</span><span class="hint">Proration and mid-cycle changes</span></span>
      <svg class="chev" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 9l6 6 6-6"/></svg>
    </summary>
    <div class="panel"><div class="inner">
      Adding a seat charges the remaining days of the cycle immediately. Removing one credits the
      unused portion against your next invoice rather than refunding it.
    </div></div>
  </details>
</article>
CSS
/* Expanding card built on <details>/<summary>: opening and closing work with no script, from the
   keyboard (Enter/Space) and with find-in-page. The panel is animated on ::details-content: its rows go
   from 0fr to 1fr and content-visibility is transitioned with allow-discrete. Chromium animates opening
   and closing, Safari animates opening only, and browsers without ::details-content snap open and shut. */
.xcard{width:400px;max-width:100%;overflow:hidden;background:#fff;border:1px solid #e9ecf1;border-radius:16px;
  transition:box-shadow .18s}
.xcard:hover{box-shadow:0 12px 30px -20px rgba(16,24,40,.26)}
.xcard svg{display:block}
.xcard summary{list-style:none;cursor:pointer;padding:18px 20px;display:flex;align-items:center;gap:14px}
.xcard summary::-webkit-details-marker{display:none}
.xcard summary:focus-visible{outline:2px solid #4f46e5;outline-offset:-2px;border-radius:16px}
.xcard .ic{width:38px;height:38px;border-radius:11px;background:#eef2ff;color:#4f46e5;
  display:grid;place-items:center;flex-shrink:0}
.xcard .ic svg{width:19px;height:19px;stroke:currentColor;fill:none;stroke-width:2}
.xcard .ttl{display:block;font-size:.96rem;font-weight:700}
.xcard .hint{display:block;font-size:.81rem;color:#667085;margin-top:2px}
.xcard .chev{margin-left:auto;width:18px;height:18px;flex-shrink:0;stroke:#667085;fill:none;stroke-width:2.2;
  transition:transform .25s}
.xcard details[open] .chev{transform:rotate(180deg)}
.xcard details::details-content{display:grid;grid-template-rows:0fr;
  transition:grid-template-rows .28s ease,content-visibility .28s allow-discrete}
.xcard details[open]::details-content{grid-template-rows:1fr}
.xcard .panel{overflow:hidden;min-height:0}
.xcard .inner{padding:0 20px 20px 72px;font-size:.87rem;color:#667085;line-height:1.65}
.xcard .inner ul{margin:11px 0 0;padding-left:18px;display:flex;flex-direction:column;gap:6px}
@media (prefers-reduced-motion:reduce){
  .xcard,.xcard .chev,.xcard details::details-content{transition:none}
}

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<article class="card xcard">
  <details open>
    <summary class="d-flex align-items-center">
      <span class="ic flex-shrink-0" aria-hidden="true"><svg viewBox="0 0 24 24"><path d="M4 7h16M4 12h16M4 17h10"/></svg></span>
      <span><span class="ttl d-block">What is included in the Team plan</span><span class="hint d-block">Seats, storage and support</span></span>
      <svg class="chev ms-auto flex-shrink-0" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 9l6 6 6-6"/></svg>
    </summary>
    <div class="panel"><div class="inner">
      Everything in Starter, plus the controls a team needs once more than a couple of people
      depend on the account.
      <ul class="d-flex flex-column"><li>Up to 25 seats with per-seat permissions</li>
        <li>1 TB of shared storage</li>
        <li>Audit log and SSO</li></ul>
    </div></div>
  </details>
</article>

<article class="card xcard">
  <details>
    <summary class="d-flex align-items-center">
      <span class="ic flex-shrink-0" aria-hidden="true"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M12 11v5M12 8h.01"/></svg></span>
      <span><span class="ttl d-block">How billing works when seats change</span><span class="hint d-block">Proration and mid-cycle changes</span></span>
      <svg class="chev ms-auto flex-shrink-0" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 9l6 6 6-6"/></svg>
    </summary>
    <div class="panel"><div class="inner">
      Adding a seat charges the remaining days of the cycle immediately. Removing one credits the
      unused portion against your next invoice rather than refunding it.
    </div></div>
  </details>
</article>
CSS
/* Bootstrap .card around a native <details>, so no bundle JS is needed (Bootstrap's .collapse would need it).
   The panel is animated on ::details-content (rows 0fr to 1fr): Chromium animates opening and closing,
   Safari animates opening only, and browsers without ::details-content snap open and shut. */
.xcard{--bs-card-border-color:#e9ecf1;--bs-card-border-radius:16px;width:400px;max-width:100%;overflow:hidden;
  transition:box-shadow .18s}
.xcard:hover{box-shadow:0 12px 30px -20px rgba(16,24,40,.26)}
.xcard svg{display:block}
.xcard summary{list-style:none;padding:18px 20px;gap:14px}
.xcard summary::-webkit-details-marker{display:none}
.xcard summary:focus-visible{outline:2px solid #4f46e5;outline-offset:-2px;border-radius:16px}
.xcard .ic{width:38px;height:38px;border-radius:11px;background:#eef2ff;color:#4f46e5;display:grid;place-items:center}
.xcard .ic svg{width:19px;height:19px;stroke:currentColor;fill:none;stroke-width:2}
.xcard .ttl{font-size:.96rem;font-weight:700}
.xcard .hint{font-size:.81rem;color:#667085;margin-top:2px}
.xcard .chev{width:18px;height:18px;stroke:#667085;fill:none;stroke-width:2.2;transition:transform .25s}
.xcard details[open] .chev{transform:rotate(180deg)}
.xcard details::details-content{display:grid;grid-template-rows:0fr;
  transition:grid-template-rows .28s ease,content-visibility .28s allow-discrete}
.xcard details[open]::details-content{grid-template-rows:1fr}
.xcard .panel{overflow:hidden;min-height:0}
.xcard .inner{padding:0 20px 20px 72px;font-size:.87rem;color:#667085;line-height:1.65}
.xcard .inner ul{margin:11px 0 0;padding-left:18px;gap:6px}
@media (prefers-reduced-motion:reduce){
  .xcard,.xcard .chev,.xcard details::details-content{transition:none}
}

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<article class="w-[400px] max-w-full overflow-hidden rounded-2xl border border-[#e9ecf1] bg-white transition-shadow duration-[180ms] hover:shadow-[0_12px_30px_-20px_rgba(16,24,40,.26)] motion-reduce:transition-none">
  <details class="group details-content:grid details-content:grid-rows-[0fr] details-content:transition-[grid-template-rows,content-visibility] details-content:transition-discrete details-content:duration-[280ms] details-content:ease-[ease] open:details-content:grid-rows-[1fr] motion-reduce:details-content:transition-none" open>
    <summary class="flex cursor-pointer list-none items-center gap-3.5 rounded-2xl px-5 py-[18px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#4f46e5] [&::-webkit-details-marker]:hidden">
      <span class="grid size-[38px] shrink-0 place-items-center rounded-[11px] bg-[#eef2ff] text-[#4f46e5]" aria-hidden="true"><svg class="block size-[19px] fill-none stroke-current stroke-2" viewBox="0 0 24 24"><path d="M4 7h16M4 12h16M4 17h10"/></svg></span>
      <span><span class="block text-[.96rem] font-bold">What is included in the Team plan</span><span class="mt-0.5 block text-[.81rem] text-[#667085]">Seats, storage and support</span></span>
      <svg class="ml-auto block size-[18px] shrink-0 fill-none stroke-[#667085] stroke-[2.2] transition-transform duration-[250ms] group-open:rotate-180 motion-reduce:transition-none" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 9l6 6 6-6"/></svg>
    </summary>
    <div class="min-h-0 overflow-hidden"><div class="pr-5 pb-5 pl-[72px] text-[.87rem] leading-[1.65] text-[#667085]">
      Everything in Starter, plus the controls a team needs once more than a couple of people
      depend on the account.
      <ul class="mt-[11px] flex list-disc flex-col gap-1.5 pl-[18px]"><li>Up to 25 seats with per-seat permissions</li>
        <li>1 TB of shared storage</li>
        <li>Audit log and SSO</li></ul>
    </div></div>
  </details>
</article>

<article class="w-[400px] max-w-full overflow-hidden rounded-2xl border border-[#e9ecf1] bg-white transition-shadow duration-[180ms] hover:shadow-[0_12px_30px_-20px_rgba(16,24,40,.26)] motion-reduce:transition-none">
  <details class="group details-content:grid details-content:grid-rows-[0fr] details-content:transition-[grid-template-rows,content-visibility] details-content:transition-discrete details-content:duration-[280ms] details-content:ease-[ease] open:details-content:grid-rows-[1fr] motion-reduce:details-content:transition-none">
    <summary class="flex cursor-pointer list-none items-center gap-3.5 rounded-2xl px-5 py-[18px] focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[#4f46e5] [&::-webkit-details-marker]:hidden">
      <span class="grid size-[38px] shrink-0 place-items-center rounded-[11px] bg-[#eef2ff] text-[#4f46e5]" aria-hidden="true"><svg class="block size-[19px] fill-none stroke-current stroke-2" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M12 11v5M12 8h.01"/></svg></span>
      <span><span class="block text-[.96rem] font-bold">How billing works when seats change</span><span class="mt-0.5 block text-[.81rem] text-[#667085]">Proration and mid-cycle changes</span></span>
      <svg class="ml-auto block size-[18px] shrink-0 fill-none stroke-[#667085] stroke-[2.2] transition-transform duration-[250ms] group-open:rotate-180 motion-reduce:transition-none" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 9l6 6 6-6"/></svg>
    </summary>
    <div class="min-h-0 overflow-hidden"><div class="pr-5 pb-5 pl-[72px] text-[.87rem] leading-[1.65] text-[#667085]">
      Adding a seat charges the remaining days of the cycle immediately. Removing one credits the
      unused portion against your next invoice rather than refunding it.
    </div></div>
  </details>
</article>

About this set

Two cards that expand in place to show more detail, one open and one closed, as used for plan comparisons, FAQs and settings explanations. Each card header has an icon tile, a title, a one-line hint and a chevron that turns over when the card is open. They are built on the native details and summary elements, so opening and closing works with no JavaScript, from the keyboard with Enter or Space, and with find in page, and the open state is exposed to assistive technology by the browser. The panel animates on the ::details-content pseudo-element: its grid rows go from 0fr to 1fr, and content-visibility is transitioned with allow-discrete so the content stays visible while it closes. Chromium browsers animate both opening and closing, Safari animates opening, and browsers without ::details-content open and close instantly, which is a safe fallback. The Bootstrap version wraps the same details in a .card, which avoids needing the Bootstrap bundle for .collapse; the Tailwind version uses the details-content:, open: and group-open: variants.

What’s included

  • Native details and summary, no JavaScript
  • Grid-rows animation on ::details-content
  • Chevron rotates with the open state
  • Works with Enter, Space and find in page
  • Animations switched off under reduced motion

Accessibility

The summary is the disclosure control, so its title and hint form the accessible name and the browser reports expanded or collapsed. The icon and chevron are aria-hidden. The summary shows a 2px indigo outline on keyboard focus. The grey hint and chevron were darkened to meet contrast, and every transition, including the panel animation, is removed under prefers-reduced-motion.

Customise it

The animation length is the .28s on details::details-content (details-content:duration-[280ms] in Tailwind). The icon tile uses #eef2ff and #4f46e5, and the 72px left padding on .inner lines the text up with the title.