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>

This tag is the container. Its a combination of tags that provides us the required output.

The other tag that comes along with this is the <summary> tag.

<details> 
    <summary>
    <!-- accordion title -->
    </summary>
    <!-- accordion contents -->
</details>
Image: Simple accordion using <details> and <summary> tag.

Steps to acheive

Lets take a simple html structure like the below.

HTML:

accordion.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.

Image: Simple html view

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.

Image: Click triggers the details tag to expand and reveal the contents inside

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

accordion.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

accordion.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?