Live demo

The simplest use of Panel: a block of text with a "Show more" button that reveals additional content below. The panel starts closed by default and expands vertically when triggered.

Note that when a trigger and panel are adjacent (siblings of a same parent, but the panel can be anywhere before or after the trigger button), and the trigger has a data-panel-trigger attribute, you no longer need to create ID’s, because Panel automatically does that for you.

Additional content that was hidden. It can be as long as needed. The panel animates to its natural height. If we make this text long, it might wrap to multiple lines.

HTML
<button data-panel-trigger>Show more</button>

<div data-panel>
	<div class="panel-wrapper">
		<p>Additional content that was hidden. It can be as long as needed. The panel animates to its natural height. If we make this text long, it might wrap to multiple lines.</p>
	</div>
</div>

This is the generated HTML:

HTML
<button aria-controls="panel-1" aria-expanded="false">Show more</button>

<div id="panel-1" data-panel inert>
	<div class="panel-wrapper">
		<p>Additional content that was hidden. It can be as long as needed. The panel animates to its natural height. If we make this text long, it might wrap to multiple lines.</p>
	</div>
</div>

The button gets an aria-expanded attribute that reflects the open/closed state of the panel, and the panel gets an inert attribute that hides it from assistive technologies when it’s closed.

Changing the trigger

In the below example, the button label changes between "Show more" and "Show less" using an aria-expanded-driven CSS rule. No JavaScript required.

Additional content that was hidden. It can be as long as needed. The panel animates to its natural height. If we make this text long, it might wrap to multiple lines.

HTML
<button data-panel-trigger>
	<span class="when-closed">Show more</span>
	<span class="when-open">Show less</span>
</button>
<div data-panel>
	<div class="panel-wrapper">
		<p>Additional content that was hidden. It can be as long as needed. The panel animates to its natural height. If we make this text long, it might wrap to multiple lines.</p>
	</div>
</div>
CSS
button[aria-expanded="false"] .when-open,
button[aria-expanded="true"] .when-closed { display: none; }