Collapsible content
Etch is a component library for builders who care about craft. Every part is shaped by hand, tested against real content, and tuned until it feels inevitable.
The Read More pattern is small but easy to get wrong. The trick is honest motion. Heights animate between measured pixel values, not keyword values that browsers refuse to interpolate. The mask fades the bottom of the text so the cutoff feels intentional rather than accidental.
When the content is shorter than the threshold, the trigger hides itself. When the content grows past the threshold (a resize, a font swap, a late image decode), the trigger comes back. The component tracks user intent, so an expanded section stays expanded across reflows.
Accessibility is built in. The trigger has a real aria-controls relationship to its content, the expanded state is announced, and reduced-motion users get an instant toggle instead of an animation.
Short content (trigger hides itself)
One paragraph. The component measures this and hides the trigger after a stabilization window.
Default expanded
This component renders in the expanded state on first paint. Useful when you want the same markup to be open by default on desktop and collapsed on mobile. Toggle the attribute with a media query or a small bit of script.
The trigger still works. Click it to collapse the content back down, and the component will remember the user's choice across reflows.
Long enough to actually need a trigger. If the content fits within the threshold, the trigger hides itself regardless of this setting.
Overlay trigger
In overlay mode, the trigger floats over the bottom of the truncated content instead of sitting below it. The content's own mask fade handles the backdrop, so the label stays legible against the text underneath.
Tune the fade with --mask-amount. A larger value extends the fade further up, giving the trigger more breathing room over the text.
Expand this and the trigger drops back into normal flow below the content with the regular trigger gap restored.
Overlay trigger (centered vertically)
Same overlay mode, but the trigger sits at the vertical center of the collapsed element instead of pinned to the bottom. Set data-trigger-position="overlay-center" to opt in.
Push --mask-amount higher so the fade extends further up the element, giving the centered button enough quiet space around it to read as the focal point.
When expanded, the trigger drops back to the bottom in normal flow with the regular trigger gap restored, same as the standard overlay mode.
Long label change
When the two labels differ a lot in length, the trigger animates its width between them. The "more" label slides out as the "less" label slides in, and the surrounding text reflows around the new width instead of snapping.
This is the same transition the centered trigger uses by default. It's just more visible when the labels are dramatically different sizes.
One more paragraph so the content actually clips and the trigger has something to do.
Left-aligned trigger
The trigger alignment is configurable via --trigger-align. Here it sits on the left edge instead of the default center. The gap between content and trigger is also tightened with --trigger-gap.
Useful for blog post excerpts, comment threads, or anywhere a centered trigger feels too formal.
One more paragraph to push the content past the threshold so the trigger actually shows up.