LEARNING OBJECTIVES โต
- Understand why animating
<details>height was historically difficult due to discretedisplaytransitions. - Master the CSS Grid
0frto1frtransition technique for zero-JS accordion animations. - Explore cutting-edge CSS features:
interpolate-size: allow-keywords,::details-content, and@starting-style. - Design accessible, polished disclosure widgets with animated chevrons and high-contrast focus rings.
๐ The Mental Model & Story (Intuitive Foundation)
Imagine an antique Venetian window blind. When closed, the slats are pulled tightly together, occupying almost no vertical height. When you pull the cord, the slats slide downward in a smooth, continuous mechanical glide until the window is fully uncovered.
For over a decade, web developers trying to animate the native <details> element felt like they were trying to operate a broken blind:
- The moment you clicked
<summary>, the contents would snap instantly onto the screen like a light switch flipping on (0pxto500pxin0ms). - In CSS, you cannot traditionally transition from
height: 0toheight: autobecause the browser's layout engine cannot calculate intermediate mathematical interpolation values between a fixed number and an unresolved keyword (auto).
Modern CSS provides three revolutionary techniques to solve this:
- The CSS Grid Row Trick (
grid-template-rows: 0fr -> 1fr): A mathematically interpolatable layout container that smoothly reveals content. ::details-content: A native pseudo-element targeting the internal slot of<details>.interpolate-size: allow-keywords&@starting-style: The modern CSS standard enabling direct transitions between0andauto.
CSS Grid 0fr -> 1fr Animation Pipeline:
[details:not([open])] .content-wrapper
+--------------------------------------------------------+
| grid-template-rows: 0fr; (Height = 0px, Hidden) |
| [ Inner container has min-height: 0; overflow: hidden ]|
+--------------------------------------------------------+
|
| CSS Transition (0.35s ease-out)
v
[details[open]] .content-wrapper
+--------------------------------------------------------+
| grid-template-rows: 1fr; (Height = Auto Content Fit) |
| [ Inner container smoothly expands and reveals text ] |
+--------------------------------------------------------+
Technical Deep Dive & Specifications
Method 1: The Production-Standard CSS Grid Technique
Because browser engines can interpolate between fractional grid tracks (fr), placing the disclosure content inside a single-column CSS Grid with a collapsing row creates a seamless height animation without any fixed max-height guesswork.
<details class="animated-details">
<summary>What is our SLA guarantee?</summary>
<div class="grid-expander">
<div class="inner-content">
<p>We guarantee 99.99% uptime backed by financial service credits.</p>
</div>
</div>
</details>
/* Container Grid */
.animated-details .grid-expander {
display: grid;
grid-template-rows: 0fr;
transition: grid-template-rows 0.35s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Expand on Open */
.animated-details[open] .grid-expander {
grid-template-rows: 1fr;
}
/* Inner wrapper MUST have min-height: 0 and overflow: hidden */
.animated-details .inner-content {
min-height: 0;
overflow: hidden;
}
[!IMPORTANT] The
.inner-contentchild must setmin-height: 0;andoverflow: hidden;. By default, grid items havemin-height: auto, which prevents the grid track from shrinking down to0fr.
Method 2: Modern Standard interpolate-size: allow-keywords
In the CSS Values and Units Module Level 4, the W3C introduced the interpolate-size property. When enabled on the root or component, browsers can interpolate sizing calculations directly to and from intrinsic sizing keywords like auto, min-content, and max-content.
/* Enable intrinsic keyword interpolation */
:root {
interpolate-size: allow-keywords;
}
/* Modern direct height transition */
details::details-content {
opacity: 0;
height: 0;
overflow: hidden;
transition: height 0.3s ease, opacity 0.3s ease, content-visibility 0.3s allow-discrete;
}
details[open]::details-content {
opacity: 1;
height: auto; /* Interpolates smoothly from 0 to auto! */
}
Method 3: @starting-style & transition-behavior: allow-discrete
When an element transitions from display: none to display: block (or enters the DOM), @starting-style defines the initial CSS properties before the first paint frame:
details::details-content {
transition: opacity 0.4s ease, transform 0.4s ease;
transition-behavior: allow-discrete;
opacity: 0;
transform: translateY(-8px);
}
details[open]::details-content {
opacity: 1;
transform: translateY(0);
}
@starting-style {
details[open]::details-content {
opacity: 0;
transform: translateY(-8px);
}
}
Modern Styling Architecture Matrix
| Technique | Browser Support | JS Required? | Handles Dynamic Heights? | Overflow Clipping Needed? |
|---|---|---|---|---|
CSS Grid 0fr to 1fr |
100% Modern Browsers (Chrome, Firefox, Safari, Edge) | 0% (Pure CSS) | โ Yes (Adapts to any height) | Yes (overflow: hidden) |
max-height Transition (Legacy) |
All Browsers | 0% | โ No (Timing feels fast/slow, hardcoded values) | Yes |
interpolate-size: allow-keywords |
Chrome 129+, Edge 129+, Safari/Firefox (in progress) | 0% | โ Yes (Native engine interpolation) | No |
| JavaScript Web Animations API | All Browsers | โ ๏ธ Yes (Requires JS event handlers) | โ Yes | Handled by script |
๐ป Interactive Code Playground
Starter Code
Line-by-Line Code Breakdown
- Lines 28โ36: Removes default browser triangles using standard
list-style: noneand WebKit vendor resets. - Lines 44โ58: Animates the chevron icon using
transform: rotate(180deg)with a smoothcubic-beziertiming function. - Lines 60โ67: Defines the CSS Grid transition engine. When closed,
grid-template-rows: 0frcollapses the grid track to zero height. Whendetails[open]is applied, it transitions to1fr. - Lines 68โ71: Sets
min-height: 0;andoverflow: hidden;on.grid-inner, allowing the grid row to collapse completely without children overflowing. - Lines 90โ98: Wraps the disclosed text in the two-tier
.grid-wrapper > .grid-innerhierarchy to execute the pure CSS animation cleanly.
Expected Browser Render Output
- Collapsed State: A sleek dark slate panel displaying the question title and a downward-pointing gray chevron.
- Hover / Focus: Hovering lightens the row background. Tabbing onto the summary reveals a bright cyan focus ring.
- Expansion: Clicking the summary smoothly slides the text down from 0px to its natural content height while the chevron rotates 180ยฐ into an upward cyan arrow in perfect synchronization.
๐๏ธ Hands-On Exercise
๐ฏ The Challenge: Build a Complete Animated Pricing Feature Accordion
Build a 3-item animated feature FAQ for a SaaS subscription page:
- Create three `