DEV Community

Cover image for Accordion Component With Only CSS [No Javascript]
Navdeep Mishra
Navdeep Mishra

Posted on

Accordion Component With Only CSS [No Javascript]

Hi Web Dev's, πŸ‘‹ We all know how much good web dev is that's why we are doing this. When it comes to web design it's a very important skill you must have. Creating component using core technologies improves your core skills.
Today in this tutorial I'll sharing how I created a simple accordion component with Neomorphism design using only Html and CSS.

Without wasting time, Let's start -

If you are not familiar with what is accordion then checkout this - MUI Accordion Component.

For creating the accordion component we need the basic skeleton first our HTML

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap" rel="stylesheet">


  <title>Document</title>
</head>
<body>
  <main class="container">
  <div class="accordion">
    <div class="accordion__head">
    <p class="accordion__title">
      Hey there, I am a accordion title      
    </p>
    <div class="accordion__opener"> 
        <input type="checkbox" id="accordion-opener-input" checked>
      <label for="accordion-opener-input">
          <i class="fa-solid fa-caret-up"></i>
          </label>
    </div>
    </div>
     <div class="accordion__description">
      <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. </p>
    </div>
    </div>

  </div>
  </main>
  <script src="https://kit.fontawesome.com/31571152d6.js" crossorigin="anonymous"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

We'll not go in details of html structure. Here I used the good old trick to check for the open and close state like we do for switch. I have used the input type checkbox to toggle between open and closed states.

Now let's come to the heart of the web. The CSS Style.

*{
  margin:0;
  padding:0;
}
*,*::before,*::after{
  box-sizing:border-box;
}
img {
  max-width:100%;
  display:block;
}

:root{
  --clr-primary: #d9d9d9;
  --clr-secondary:#fafafa;
  --clr-clear:#ffffff;
  --clr-grey: #6d6d6d;
  --clr-dark:#1e1e1e;
  --ff-base:'Inter', sans-serif;

  --fw-regular: 400;

  --fs-200:0.875rem;
  --fs-300:1rem;
  --fs-400:1.125rem;
  --fs-500:1.375rem;
  --fs-600:1.75rem;
  --fs-700:3.25rem;

}
html{
  color-scheme: light dark;
}
body{
  font-family:var(--ff-base);
  font-size: var(--fs-300);
  line-height:1.5;
  font-weight: var(--fw-regular);
  height:100vh;

}
main {
  display:flex;
  justify-content:center;
  align-items:flex-start;
  height:80%;
  padding-top:4rem;
}
.accordion{
  font-size:inherit;
  padding: 1.2em 2em;
  border-radius:.5em;
  max-width:30rem;
  width:100%;
  box-shadow:  10px 10px 30px #000000,
             -10px -10px 30px #1f1f1f;
  transition: box-shadow .5s ease;
}
.accordion:hover{
  box-shadow:  10px 10px 20px #000000,
             -10px -10px 20px #1f1f1f;
}
.accordion__head{
  display:flex;
  justify-content:space-between;
}
.accordion__title{
  display:inline-block;
}
.accordion__opener{
  display:inline;
  margin-left:.5rem;

}
.accordion__opener input{
  display:none;
}
.accordion__opener label{
  cursor:pointer;
}
.accordion__opener label i {
/*   transform: rotate(90deg); */
  display:inline-block;
  transition: transform .4s ease;

}
.accordion__description{
  overflow:hidden;
  margin-top:0;
  display:grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .5s, margin-top .5s; 
  color: var(--clr-grey);

}
.accordion__description p {
  overflow: hidden;
}
.accordion__opener input:checked + label i{
  transform: rotate(180deg);
}
.accordion__head:has(.accordion__opener input:checked) + :is(.accordion__description){
  margin-top: 10px;
  grid-template-rows: 1fr;
}

@media (prefers-color-scheme: light){
  body{
    background: #e0e0e0;
  }
  .accordion{
    background: #e0e0e0;
box-shadow:  20px 20px 60px #bebebe,
             -20px -20px 60px #ffffff;
  }
  .accordion:hover{
    background: #e0e0e0;
    box-shadow:  20px 20px 30px #bebebe,
             -20px -20px 30px #ffffff;
  }
}
Enter fullscreen mode Exit fullscreen mode

Here I have used the basic Css normalization for removing default styling of few things. Also declared few variables for reusing properties and making our life easier.πŸ˜†

Now what's different here? In most of the tutorial for creating the css only accordion, you'll find out that they we mentioning the max-width property. Which is not good sometime when you don't know how much height your content can have.
In this I have used the css grid trick. With css grid-template-row, I am manipulating the height and achieving the same functionality without mentioning max-width on the description. You can use max-width trick as well if your use case requires that.

Also I have used the *BEM Naming convention for Css * which is a standard for writing the Css classes.

For generating the Neomorphism styles I have used a Neomorphism style generator. Link is in the resources section.

Checkout the Codepen here - CSS Only Accordion Component

Useful Resources:

BEM Convention - Checkout
Neomorphism Generator - Checkout

Feel free to discuss more about the article in the comments below😎
Thanks for reading.
Please like and share.

Follow for more post on #webdev

Top comments (2)

Collapse
 
chlorophyllkid profile image
Christopher Voigt

Why not use details + summary as HTML tags?

Collapse
 
navdeepm20 profile image
Navdeep Mishra

That's true. I will try with that as well. πŸ˜