CSS Accordion
A comprehensive guide to creating a Accordion with just HTML and CSS. There is no need of JS anywhere.
The beauty lies within HTML5 tags 🍕
HTML5 tags has a lot of super powers unexplored. One of the is the <details>
tag. Proper usage of these can limit the use of scripts inside the page.
<details>
<!-- more content-->
</details>
The other tag that comes along with this is the <summary>
tag.
<details>
<summary>
<!-- accordion title -->
</summary>
<!-- accordion contents -->
</details>

Steps to acheive
Lets take a simple html structure like the below.
HTML:
<h3> Simple Accordion</h3>
<div class="accordion">
<details>
<summary><span>Step 1</span> Trip information <i></i> </summary>
<p>Trip type : One Way </p>
<p>From: Chennai </p>
<p>To: Dubai </p>
<p>Departure: 12 Aug,2020</p>
<p>Passengers count: 2</p>
<p>Return: </p>
</details>
<details>
<summary><span>Step 2</span>Flight information <i></i> </summary>
<p>Flight ID: </p>
<p>Flight name: </p>
<p>Flight Timings: </p>
<p>Seat status: </p>
</details>
<details>
<summary ><span>Step 3</span>Payment information <i></i></summary>
<p>Card type: </p>
<p>Card name: </p>
<p>Card Validity:</p>
<p>Payment status:</p>
</details>
</div>
This piece of code gives u a visual structure like the below.

This is the basic of the entire concept. Clicking on the <summary> tag which holds the accordion title, will toggle the accordion content individually for each details tag.
They work independent of each other, unless it is handled by a script.
The <details> tag has the property to act like a toggle functionality for the contents other than the <summary> tag. This gives us n number of possibilites to create our desired UI functionality. And it is not restricted to just a accordion feature. In this example I've planned to use it as a check list for a train ticket booking system. Lets dive back in now.

How it works?
On clicking the title of the <details>, ( which is actually the <summary> ), the browser returns the <details> with an attribute called open
. This attribute plays the most part in styling the entire accordion.
Further to add to the visual clarity, I'm using font icons. Line Icons is my favourite, so I've used those.
Below is a formatted HTML with class names to differentiate active and completed steps.
HTML
<div class="accordion">
<details>
<summary class="active">
<span>Step 1</span> Trip information <i></i> </summary>
<p class="complete">Trip type : One Way </p>
<p class="complete">From: Chennai </p>
<p class="complete">To: Dubai </p>
<p class="active">Departure: 12 Aug,2020</p>
<p>Passengers count: 2</p>
<p>Return: </p>
</details>
<details>
<summary><span>Step 2</span>Flight information <i></i> </summary>
<p>Flight ID: </p>
<p>Flight name: </p>
<p>Flight Timings: </p>
<p>Seat status: </p>
</details>
<details>
<summary ><span>Step 3</span>Payment information <i></i></summary>
<p>Card type: </p>
<p>Card name: </p>
<p>Card Validity:</p>
<p>Payment status:</p>
</details>
</div>
Now comes the CSS part. This mostly revolves around the attribute part of the <details>.
CSS
details{
background: #253448;
margin:0;
}
details[open]{
padding-bottom: 10px;
border-bottom: 1px solid #465f80;
}
summary{
margin-bottom:0px;
padding:25px 20px 20px;
color: #b1c1ca;
display: block;
background:#1b2939;
}
details[open] summary{
border-bottom: 1px solid #465f80;
margin-bottom: 10px;
}
details p{
padding:0;
transition: all 0.2s ease-in;
transition-property: padding;
margin: 0;
color: #697e99;
font-size:0.875em;
}
details[open] p{
padding:5px 20px;
transition: all 0.2s cubic-bezier(0.23, 1, 0.32, 1);
transition-property: padding-top;
}
details summary::before,details p::before{
content:"\ea54";
font-family: Lineicons;
padding-right:15px;
color:#697e99;
}
details summary.active::before,details p.active::before{
content:"\ea1d";
font-family: Lineicons;
padding-right:15px;
}
details p.complete{
color: rgb(141, 253, 237);
}
details .complete::before{
color:rgb(141, 253, 237);
}
details p.active, details .active::before{
color: rgb(253, 141, 229);
}
details summary span{
position: absolute;
font-size: 0.65em;
text-transform:uppercase;
top:12px;
color:#999;
text-indent:3px;
}
summary i{
float:right;
font-style: normal;
opacity:0.5;
transition: all 0.2s ease-in;
color: #fff;
}
summary:hover i,details[open] summary i{
opacity:1;
transition: all 0.2s ease-in;
}
summary i::before{
content: "\ea27";
font-family: Lineicons;
}
details[open] summary i::before{
content: "\ea22";
font-family: Lineicons;
}
This will give you the desired output as per the image below.

Now a further addition to the feature, to make the title of each section float on top while scrolling, we need to add a small piece. This is added to the summary tag in the css.
summary{
position: sticky;
top: 0;
}
Demo
The demo can be found in the link below.
Demo🍕
Thank you for reading it.
Last updated
Was this helpful?