DEV Community

Morteza Mirmojarabian
Morteza Mirmojarabian

Posted on • Originally published at mori.pages.dev

Create a CSS toggle button with the <details> element

Overview

If for some reason you can't use JavaScript, the following workaround is your best bet to create a toggle button. The <details> HTML element creates a disclosure widget to hide and show content. We're going to (ab)use the <details> element and some CSS, so let's call it the "details hack".

How it works

Here's a basic example.

CSS

details[open] summary {
  color: red;
}
Enter fullscreen mode Exit fullscreen mode

HTML

<details>
  <summary>Toggle</summary>
</details>
Enter fullscreen mode Exit fullscreen mode

Result

Clicking the <summary> element toggles the <details>' open attribute and the <summary>'s style. You can also toggle the style of the <details>' next siblings.

CSS

details[open] summary {
  color: red;
}

details[open] ~ p {
  color: blue;
}
Enter fullscreen mode Exit fullscreen mode

HTML

<details>
  <summary>Toggle</summary>
</details>
<p>Hello, world!</p>
Enter fullscreen mode Exit fullscreen mode

Result

An advantage of this method over the checkbox hack is that the button is keyboard accessible.

Notes

  • The <summary>'s contents can be any heading content, plain text, or HTML that can be used within a paragraph.
  • The <summary>'s display default value is list-item. To remove the list item's triangle ::marker, change the value to inline-flex, for example.
summary {
  display: inline-flex;
}
Enter fullscreen mode Exit fullscreen mode

Alternatively, you may use one of the following rules:

summary {
  list-style: none;
}
Enter fullscreen mode Exit fullscreen mode
summary::marker {
  content: none;
}
Enter fullscreen mode Exit fullscreen mode

More examples

The following demos show the details hack's potential and give you an idea of how to use it.

Replace an element

CSS

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;
}
Enter fullscreen mode Exit fullscreen mode

HTML

<details>
  <summary><span id="off">0</span><span id="on">1</span></summary>
</details>
Enter fullscreen mode Exit fullscreen mode

Result

Replace an element with transition

CSS

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;
}
Enter fullscreen mode Exit fullscreen mode

HTML

<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>
Enter fullscreen mode Exit fullscreen mode

Result

A toggle switch

CSS

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;
}
Enter fullscreen mode Exit fullscreen mode

HTML

<details>
  <summary></summary>
</details>
Enter fullscreen mode Exit fullscreen mode

Result

Multiple buttons

CSS

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;
}
Enter fullscreen mode Exit fullscreen mode

HTML

<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>
Enter fullscreen mode Exit fullscreen mode

Result

Top comments (0)