Create a CSS toggle button with the <details> element
Tags: html, css, details, toggle
Published: 2023-06-29 10:32:18

<h2>Overview</h2>
<p>If for some reason you can't use JavaScript, the following workaround is your best bet to create a toggle button. The <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details"><code>&lt;details&gt;</code></a> HTML element creates a disclosure widget to hide and show content. We're going to (ab)use the <code>&lt;details&gt;</code> element and some CSS, so let's call it the "details hack".</p>
<h2>How it works</h2>
<p>Here's a basic example.</p>
<h3>CSS</h3>

```
details[open] summary {
  color: red;
}
```
<h3>HTML</h3>

```
<details>
  <summary>Toggle</summary>
</details>
```
<h3>Result</h3>
{% codepen https://codepen.io/mori79/pen/wvQJQeJ %}
<p>Clicking the <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/summary"><code>&lt;summary&gt;</code></a> element toggles the <code>&lt;details&gt;</code>' <code>open</code> attribute and the <code>&lt;summary&gt;</code>'s style. You can also toggle the style of the <code>&lt;details&gt;</code>' next siblings.</p>
<h3>CSS</h3>

```
details[open] summary {
  color: red;
}

details[open] ~ p {
  color: blue;
}
```
<h3>HTML</h3>

```
<details>
  <summary>Toggle</summary>
</details>
<p>Hello, world!</p>
```
<h3>Result</h3>
{% codepen https://codepen.io/mori79/pen/KKrWrXQ %}
<p>An advantage of this method over the <a href="https://css-tricks.com/the-checkbox-hack/">checkbox hack</a> is that the button is keyboard accessible.</p>
<h3>Notes</h3>
- The <code>&lt;summary&gt;</code>'s contents can be any heading content, plain text, or HTML that can be used within a paragraph.
- The <code>&lt;summary&gt;</code>'s <code>display</code> default value is <code>list-item</code>. To remove the list item's triangle <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/::marker"><code>::marker</code></a>, change the value to <code>inline-flex</code>, for example.
```
summary {
  display: inline-flex;
}
```
Alternatively, you may use one of the following rules:
```
summary {
  list-style: none;
}
```
```
summary::marker {
  content: none;
}
```
<h2>More examples</h2>
<p>The following demos show the details hack's potential and give you an idea of how to use it.</p>
<h3>Replace an element</h3>
<h4>CSS</h4>

```
summary {
  display: inline-block;
}

span {
  display: inline-block;
  padding: 8px 24px;
  border-radius: 10px;
  background: linear-gradient(#eee, #ddd);
  color: #333;
  font: bold 72px monospace;
  text-shadow: 0 1px white;
}

#on,
details[open] #off {
  display: none;
}

details[open] #on {
  display: inline-block;
}
```
<h4>HTML</h4>

```
<details>
  <summary><span id="off">0</span><span id="on">1</span></summary>
</details>
```
<h4>Result</h4>
{% codepen https://codepen.io/mori79/pen/wvQJQZp %}
<h3>Replace an element with transition</h3>
<h4>CSS</h4>

```
summary {
  display: inline-flex;
  cursor: pointer;
}

img {
  transition: 0.3s linear;
}

[alt="Light off"] {
  position: absolute;
}

[alt="Light on"],
details[open] [alt="Light off"] {
  visibility: hidden;
  opacity: 0;
}

details[open] [alt="Light on"] {
  visibility: visible;
  opacity: 1;
}
```
<h4>HTML</h4>

```
<details>
  <summary><img src="light-off.png" width="100" height="180" alt="Light off"><img src="light-on.png" width="100" height="180" alt="Light on"></summary>
</details>
```
<h4>Result</h4>
{% codepen https://codepen.io/mori79/pen/oNQZQKx %}
<h3>A toggle switch</h3>
<h4>CSS</h4>

```
summary {
  display: inline-block;
  padding: 16px 32px;
  border-radius: 16px;
  background: radial-gradient(circle 12px, white 100%, transparent calc(100% + 1px)) #ccc -16px;
  transition: 0.3s ease-in-out;
}

details[open] summary {
  background-color: dodgerBlue;
  background-position: 16px;
}
```
<h4>HTML</h4>
```
<details>
  <summary></summary>
</details>
```
<h4>Result</h4>
{% codepen https://codepen.io/mori79/pen/YzRZdKp %}
<h3>Multiple buttons</h3>
<h4>CSS</h4>

```
details,
summary {
  display: inline-flex;
}

summary {
  padding: 8px 12px;
  border-radius: 5px;
  background: linear-gradient(#eee, #ddd);
  color: #333;
  font: bold 1rem monospace;
  text-shadow: 0 1px white;
}

details#italic summary,
details#italic[open] ~ p {
  font-style: italic;
}

details#underline summary,
details#underline[open] ~ p {
  text-decoration: underline;
}

details#theme {
  float: right;
}

details#theme summary::before {
  content: '☀️';
  margin-right: 0.5em;
}

details[open]:not(#theme) summary {
  background: dodgerBlue;
  color: white;
  text-shadow: 0 1px black;
}

details#theme[open] summary::before {
  content: '🌙';
}

details#bold[open] ~ p {
  font-weight: bold;
}

details#theme[open] ~ p {
  background: #333;
  color: white;
}

p {
  font: 1em/1.5 Arial;
  padding: 1em;
  border: 1px solid #dedede;
  border-radius: 5px;
}
```
<h4>HTML</h4>

```
<details id="bold">
  <summary>B</summary>
</details>

<details id="italic">
  <summary>I</summary>
</details>

<details id="underline">
  <summary>U</summary>
</details>

<details id="theme">
  <summary>Theme</summary>
</details>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
```
<h4>Result</h4>
{% codepen https://codepen.io/mori79/pen/WNYpLbK %}