Disclosure widget

Examples

Jump to section titled: Examples

HTML only

Summary

This is detail and summary with only the browser's own styles. The details and summary HTML elements have been fully supported in modern browsers since January 2020.




HTML with custom CSS

Summary

If you don't include a summary the browser adds one with the word "details".

The details and summary HTML elements have been fully supported in modern browsers since January 2020.

Lorem ipsum dolor, sit amet consectetur adipisicing elit. Nulla provident quia accusamus nostrum error possimus odit explicabo illo optio itaque hic ipsa ipsum amet iusto, esse magni consequuntur, inventore id!

Lorem ipsum dolor sit, amet consectetur adipisicing elit. Consequatur, voluptas ipsa culpa velit facere laudantium eveniet, quaerat tempore molestiae optio blanditiis. Deserunt ad amet minus quidem nemo officia, beatae repudiandae.

HTML

Jump to section titled: HTML
Copy 👋<div class="disclosure-1">
<details>
<summary>
  <!-- hides the icon from screen readers -->
   <span aria-hidden="true">
     <svg xmlns="http://www.w3.org/2000/svg" 
     viewBox="0 0 80 80" focusable="false">
       <path d="M70.3 13.8L40 66.3 9.7 13.8z"></path>
     </svg>
   </span>
      Summary
</summary>

<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit.
 Nulla provident quia accusamus nostrum error possimus odit 
 explicabo illo optio itaque hic ipsa ipsum amet iusto,
 esse magni consequuntur, inventore id!</p>

 <p>Lorem ipsum dolor, sit amet consectetur adipisicing elit.
 Nulla provident quia accusamus nostrum error possimus odit 
 explicabo illo optio itaque hic ipsa ipsum amet iusto,
 esse magni consequuntur, inventore id!</p>
</details>
</div>

CSS

Jump to section titled: CSS
Copy 👋/* This is in my CSS reset.
It is needed to animate the opening of <details> */

html {
  interpolate-size: allow-keywords;
}
/*----------------------------------------------*/

 .disclosure-1 details*{
 margin: 0;
 }

 .disclosure-1 details > *{
  padding-inline: var(--space-m); 
  font-size: var(--step-0);     
 }

 .disclosure-1 details li{  
  font-size: var(--step-0);     
 }

 .disclosure-1 details > p strong{
 color: var(--brand);
 }

 .disclosure-1 details{
 background-color: var(--shade);
 overflow: hidden; 
 }

 @media (prefers-reduced-motion: no-preference) {
 .disclosure-1 details::details-content{
 transition: block-size .6s,
 content-visibility .6s;
 transition-behavior: allow-discrete; 
 }
 }

 .disclosure-1 details::details-content{
 block-size: 0;
 }


 /* Fixed height (rather than auto) to add scroll */
 .disclosure-1 details[open]::details-content{
 block-size: 15rem; 
 overflow-x: auto;
 }

 .disclosure-1 summary{
  font-size:var(--step-1); 
  font-weight: 700;
  padding: var(--space-s); 
  cursor: pointer;  
 }

  /* Stying for the custom marker.
 The animation is minor rotate is not wrapped in the 
 prefers-reduced-motion media query above.    
   */
  
 .disclosure-1 summary::marker {
  content:'';   
 }

 /* Hides the marker on Safari. 
 Thanks to daveden.co.uk */
 .disclosure-1 summary::-webkit-details-marker {
    display: none;
 }


 .disclosure-1 details[open] summary svg {
  transform: rotate(90deg);
 }

 .disclosure-1 summary span {
  display: inline-block; 
  transform: rotate(270deg);
  vertical-align: middle;  
 }

  .disclosure-1 summary svg {  
  inline-size: 1.4rem;
  block-size: 1.4rem;    
  transition: transform 0.20s ease-in;
  transform-origin: center 50%; 
  fill: var(--brand); 
 }

 /* Outline for high contrast themes */
 .disclosure-1 details {
 outline: 0.4rem solid transparent;
 }

An earlier way to animate the opening of a panel. It only works on open when the page is first loaded. It was used when there was nothing better.

Copy 👋@keyframes details-show {
  from {
    opacity:0;
    transform: translateY(-1rem);
  }
}

details[open] > *:not(summary) {
  animation: details-show 0.8s  ease-out;
}

JS

Jump to section titled: JS

This snippet is to open <details> when CSS is not working in @media print.

Copy 👋window.addEventListener('beforeprint', function() {
	document.querySelectorAll('details').forEach(details => {
		details.open = true;
	});
});