Home » Blog » Tutorials » How to create an Unfold (reveal) effect in Elementor using CSS (without JavaScript)

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:

Leave a Reply

Your email address will not be published. Required fields are marked *