How to Build a CSS‑Only Responsive Accordion (No JavaScript Needed)
Read this article in clean Markdown format for LLMs and AI context.If you’re tired of adding a little bit of JavaScript just to hide and show some text, you’re in the right place. At CSS Tricks Reference we love keeping things simple, and today I’ll show you a pure‑CSS accordion that works on any screen size. No extra scripts, no extra weight – just plain CSS and a tiny bit of HTML. Let’s get started.
Why a CSS‑Only Accordion?
Accordions are great for FAQs, product specs, or any place where you want to keep the page tidy. Using only CSS means:
- Faster load time – the browser doesn’t have to download a separate file.
- Fewer bugs – no JavaScript to break on older browsers.
- Easy to maintain – you can change the look by editing one CSS file.
That’s why I keep a CSS‑only version in my toolbox and share it on CSS Tricks Reference whenever I need a quick solution.
The Basic Idea
The trick is to use the HTML <input type="checkbox"> element and the :checked pseudo‑class. When the checkbox is checked, we show the hidden panel. With a little help from display, max-height, and overflow, we can animate the opening and closing.
Step 1: Set Up the HTML
Here’s the minimal markup you need. Put this inside the body of your page.
<div class="accordion">
<div class="item">
<input type="checkbox" id="acc1" />
<label for="acc1" class="title">What is CSS?</label>
<div class="content">
<p>CSS stands for Cascading Style Sheets. It tells the browser how to display HTML.</p>
</div>
</div>
<div class="item">
<input type="checkbox" id="acc2" />
<label for="acc2" class="title">Why use Flexbox?</label>
<div class="content">
<p>Flexbox makes it easy to align items in a row or column without a lot of extra code.</p>
</div>
</div>
</div>
A few notes:
- Each accordion section is a
.item. - The hidden
<input>is what we’ll use to toggle the panel. - The
<label>is the clickable title. Because it’s linked to the input viafor, clicking the label checks the box. - The
.contentholds the hidden text.
Step 2: Hide the Checkboxes
We don’t want the checkboxes to appear on the page. Just hide them with CSS.
.accordion input {
position: absolute;
opacity: 0;
pointer-events: none;
}
Now the checkboxes are still there for the browser, but they’re invisible and can’t be clicked directly.
Step 3: Style the Title
Let’s make the title look like a button. This is where CSS Tricks Reference likes to keep things clean and readable.
.accordion .title {
display: block;
padding: 0.75rem 1rem;
background: #f0f0f0;
cursor: pointer;
border: 1px solid #ddd;
font-weight: bold;
}
Feel free to change the colors to match your site. The cursor: pointer tells users they can click it.
Step 4: Hide the Content by Default
We’ll start with the content hidden. Using max-height: 0 and overflow: hidden lets us animate the opening later.
.accordion .content {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease;
background: #fafafa;
border-left: 1px solid #ddd;
border-right: 1px solid #ddd;
border-bottom: 1px solid #ddd;
padding: 0 1rem;
}
Notice we still give it a little side padding so the text doesn’t touch the edge.
Step 5: Show the Content When Checked
Now the magic part. When the hidden checkbox is checked, we want the sibling .content to expand.
.accordion input:checked ~ .content {
max-height: 200px; /* big enough for most content */
padding-top: 0.75rem;
padding-bottom: 0.75rem;
}
Why max-height: 200px? Because we need a value for the transition. If your content is taller, just increase the number or use max-height: 1000px. The transition will still look smooth.
Step 6: Make It Responsive
The accordion already works on any screen, but let’s add a tiny tweak so the titles wrap nicely on small devices.
@media (max-width: 600px) {
.accordion .title {
font-size: 0.9rem;
padding: 0.6rem 0.8rem;
}
}
That’s all the responsive part. The accordion will shrink its text a bit on phones, keeping the layout clean.
Step 7: Add a Little Arrow Indicator
A small arrow helps users see which sections are open. We can use a pseudo‑element on the label.
.accordion .title::after {
content: "▸";
float: right;
transition: transform 0.3s ease;
}
.accordion input:checked + .title::after {
transform: rotate(90deg);
}
The arrow points right when closed and rotates down when open. Simple, but it feels nice.
Step 8: Put It All Together
Here’s the full CSS you can copy into your stylesheet. I like to keep everything in one place for quick testing.
/* Hide the real checkbox */
.accordion input {
position: absolute;
opacity: 0;
pointer-events: none;
}
/* Title styling */
.accordion .title {
display: block;
padding: 0.75rem 1rem;
background: #f0f0f0;
cursor: pointer;
border: 1px solid #ddd;
font-weight: bold;
}
/* Arrow indicator */
.accordion .title::after {
content: "▸";
float: right;
transition: transform 0.3s ease;
}
/* Content hidden by default */
.accordion .content {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease;
background: #fafafa;
border-left: 1px solid #ddd;
border-right: 1px solid #ddd;
border-bottom: 1px solid #ddd;
padding: 0 1rem;
}
/* Show content when checked */
.accordion input:checked ~ .content {
max-height: 200px;
padding-top: 0.75rem;
padding-bottom: 0.75rem;
}
/* Rotate arrow when open */
.accordion input:checked + .title::after {
transform: rotate(90deg);
}
/* Small screen tweaks */
@media (max-width: 600px) {
.accordion .title {
font-size: 0.9rem;
padding: 0.6rem 0.8rem;
}
}
Drop the HTML from Step 1 into your page, link this CSS, and you’ve got a fully functional accordion that works on phones, tablets, and desktops. No JavaScript, no extra weight, just clean CSS.
A Quick Personal Note
I first tried a JavaScript accordion for a client project and spent an hour hunting down a tiny bug that only appeared on Safari. After that, I promised myself I’d keep a pure‑CSS version handy. Now I pull it out whenever a quick FAQ section is needed. It’s saved me a lot of headaches, and I love sharing the trick on CSS Tricks Reference because it’s something anyone can copy and use right away.
Wrap‑Up
Building a responsive accordion with only CSS is easier than you might think. The key is the hidden checkbox and the :checked selector. With a few lines of styling you get a smooth, accessible component that works everywhere. Next time you need an accordion, give this method a try. It’ll keep your page light and your code simple – exactly the kind of solution we love at CSS Tricks Reference.
- → Modern CSS Techniques: Using Variables and Calc for Dynamic Layouts @codecrafthub
- → Building a Responsive Navigation Bar with Flexbox and CSS Grid @codecrafthub
- → Build Keyboard‑Friendly Anchor Navigation with Pure CSS and ARIA @toggleanchors
- → Boost Your First Paint: Practical CSS Techniques to Cut Load Time by 40% @codecanvas
- → Design Systems Explained: How to Create Consistent UI Across Projects @pixelcraftstudio