DEV Community

Saba beigi
Saba beigi

Posted on

CSS Only Accordion

Accordions don't even need to have fancy JavaScript plugins. Surely we can do it simply in Vanilla JavaScript, but sometimes it's best to even look at other solutions.

Today we will look into doing a CSS-only accordion with the input hack.
There are multiple ways of doing it with CSS. But today, we will look into just the input hack.For the HTML part we are going to use the following:

<div class="accordion">
  <input type="checkbox" id="tab1" />
  <label class="accordion-label" for="tab1">Item 1</label>
  <div class="accordion-content">
    Lorem ipsum dolor sit amet consectetur, adipisicing elit. Ipsum, reiciendis!
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

This will generate one accordion for us. As you can see, we use a checkbox and a label. The label will be our accordion title
CSS for the Accordion:

input {
  position: absolute;
  opacity: 0;
  z-index: -1;
}
.accordion {
  margin: 10px;
  border-radius: 5px;
  overflow: hidden;
  box-shadow: 0 4px 4px -2px rgba(0, 0, 0, 0.5);
}
.accordion-label {
  display: flex;
  justify-content: space-between;
  padding: 1em;
  font-weight: bold;
  cursor: pointer;
  background: #333;
  color: #fff;
}
.accordion-content {
  max-height: 0;
  padding: 0 1em;
  background: white;
  transition: all 0.35s;
}
input:checked ~ .accordion-content {
  max-height: 100vh;
  padding: 1em;
}
Enter fullscreen mode Exit fullscreen mode

Let's loop through this in more detail step by step:

input {
position: absolute;
opacity: 0;
z-index: -1;
}

We don't need the input visible, so we give it a postion: absolute; and z-index: -1 to hide it. We set the opacity: 0 so it's not visible to the user.
.accordion {
margin: 10px;
border-radius: 5px;
overflow: hidden;
box-shadow: 0 4px 4px -2px rgba(0, 0, 0, 0.5);
}

For the main accordion styling, we do some simple styling.

We set a margin of 10px to give it some space. Then we make the corners rounded with border-radius: 5px;. Then we also set the overflow: hidden to not make the accordion content show before clicking the label. Lastly, we set a nice box-shadow to give it a clean effect.
.accordion-label {
display: flex;
padding: 1em;
font-weight: bold;
cursor: pointer;
background: #333;
color: #fff;
}

The label we give a display: flex to make full width. Then we add some padding, make the font bold, add a cursor: pointer, and add some color to make it pop.
.accordion-content {
max-height: 0;
padding: 0 1em;
background: white;
transition: all 0.35s;
}

We set the content div to have a max-height: 0 give it a small padding, and add a transition to make it animated once it opens.
input:checked ~ .accordion-content {
max-height: 100vh;
padding: 1em;
}

No for the magic, once the input is checked we set the max-height: 100vh (100% of the viewport) and add the overall padding to the content div.

The ~ is a general sibling selector it will select a sibling that follows the first one.

See the following Codepen for a demo:

Or see this example a bit more styled and more options:

Top comments (2)

Collapse
 
frankwisniewski profile image
Frank Wisniewski

The checkbox hack can be used for many things. I prefer the native HTML variant here

<!DOCTYPE html>
<html lang=de>
  <meta charset=UTF-8>
  <title>details</title>
  <link rel=stylesheet 
   href="https://unpkg.com/@picocss/pico@latest/css/pico.min.css">
  <div class=container >
   <h1>Details</h1>
   <details>
    <summary>Read more</summary>
    <p>Lorem ipsum dolor sit amet, consectetur 
       adipisicing elit. Eligendi incidunt sequi 
       iure deleniti nemo necessitatibus explicabo 
       soluta illum dignissimos consectetur!</p>
  </details>
  </div>
Enter fullscreen mode Exit fullscreen mode
Collapse
 
sababg profile image
Saba beigi

thanks