How to create an Unfold (reveal) effect in Elementor using CSS (without JavaScript)
A button with an SVG chevron, the text “expand / collapse”, a partially visible panel, and a gradient overlay in the closed state — all implemented in CSS using the :has() selector.
The unfold effect is when a block does not disappear completely, but remains partially visible by default, then smoothly expands upward on click. When the animation finishes, the state changes: the icon rotates, and the label next to it switches from “expand” to “collapse”.
In the closed state, a soft gradient overlay is added at the bottom.
Below is an implementation that works in Elementor purely with CSS and uses the :has() selector (supported in modern browsers).
What to prepare in Elementor
Structure (minimum 3 elements)
Build a layout inside a single parent container:
Parent (wrapper) — a Container / Section with the CSS class:
unfold-wrap
Control button — an HTML widget that contains a checkbox and a label, with classes:
unfold-toggle and unfold-trigger
Content panel — a Container with the class:
unfold-panel
Important: the checkbox + label and the panel must be inside the same .unfold-wrap; otherwise the CSS‑based state logic will not work.
Setup steps
Step 1. Add the parent class
In Elementor, on the parent container / section (the one wrapping both the button and the panel), go to:
Advanced → CSS Classes, and add:
unfold-wrap
Step 2. Add the button (HTML widget)
Add an HTML widget above the container holding the panel content. Insert the following code (example with an SVG chevron):
<div>
<input class="unfold-toggle" type="checkbox" id="unfold-1">
<label class="unfold-trigger" for="unfold-1">
<!-- SVG chevron -->
<svg class="unfold-chevron" viewBox="0 0 24 24" aria-hidden="true">
<path d="M6.7 9.2a1 1 0 0 1 1.4 0L12 13.1l3.9-3.9a1 1 0 1 1 1.4 1.4l-4.6 4.6a1 1 0 0 1-1.4 0l-4.6-4.6a1 1 0 0 1 0-1.4Z"/>
</svg>
<span class="unfold-text unfold-text-close">show</span>
<span class="unfold-text unfold-text-open">hide</span>
</label>
</div> Logic explanation
When the checkbox is not checked, the text with class .unfold-text-close is shown (in your CSS this text is visible by default).
When the checkbox is checked, CSS uses :has() to switch visibility: the open text appears and the closed text is hidden.
Step 3. Add the panel class
Select the container that should hold the content to expand, and under Advanced → CSS Classes, add:
unfold-panel
Step 4. Insert the CSS
Go to Appearance → Customize → Additional CSS in your theme customizer, and paste the CSS code there.
The provided CSS already includes:
- Smooth max-height animation (for unfolding and collapsing),
- A bottom gradient overlay in the closed state,
- SVG chevron rotation on opening,
- Switching the label between “expand / collapse” text via :has(),
- Responsive max-height values defined in media queries.
CSS code:
/* === UNFOLD === */
.unfold-wrap {
--unfold-max: 900px;
--bg: #fff;
--btn-bg: #fff;
--btn-h-bg: #EBEBEB;
--text: #111;
--text-h: #111;
--border: 1px solid #d7d7d7;
--border-h: 1px solid #EBEBEB;
text-align: center;
position: relative;
}
/* Accessible hidden input */
.unfold-toggle {
position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); border: 0;
}
/* Button */
.unfold-trigger {
display: inline-flex; align-items: center; justify-content: center; gap: 8px;
cursor: pointer; user-select: none;
padding: 10px 16px; margin: 0 auto 20px;
background: var(--btn-bg); color: var(--text);
border-radius: 999px; border: var(--border);
transition: .2s;
}
.unfold-trigger:hover {
background: var(--btn-h-bg); color: var(--text-h); border: var(--border-h);
}
/* Icon & Text */
.unfold-chevron { width: 18px; height: 18px; flex-shrink: 0; fill: currentColor; transition: .35s; }
.unfold-text { font-size: 15px; font-weight: 500; line-height: 1.2; }
.unfold-text-open { display: none; }
/* Panel & Gradient */
.unfold-panel { max-height: 200px; overflow: hidden; position: relative; transition: .45s; }
.unfold-panel::after {
content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 72px; pointer-events: none;
background: linear-gradient(to bottom, rgba(0,0,0,0), var(--bg));
transition: .25s;
}
/* Responsive */
@media (max-width: 1024px) { .unfold-panel { max-height: 250px; } }
@media (max-width: 767px) {
.unfold-panel { max-height: 200px; }
.unfold-trigger { padding: 9px 14px; margin-bottom: 16px; }
.unfold-chevron { width: 16px; height: 16px; }
}
/* Toggle Logic */
@supports selector(:has(*)) {
.unfold-wrap:has(.unfold-toggle:checked) .unfold-panel { max-height: var(--unfold-max); }
.unfold-wrap:has(.unfold-toggle:checked) .unfold-panel::after { opacity: 0; }
.unfold-wrap:has(.unfold-toggle:checked) .unfold-chevron { transform: rotate(180deg); }
.unfold-wrap:has(.unfold-toggle:checked) .unfold-text-open { display: inline; }
.unfold-wrap:has(.unfold-toggle:checked) .unfold-text-close { display: none; }
} Share post: