Skip to main content

Project 03 · Beginner

Accordion

A list of questions where clicking one shows its answer. You'll build it three ways, each adding one idea: first with no JavaScript, then with a button that toggles each answer, then keeping only one answer open.

  • 4 HTML ideas
  • 4 CSS ideas
  • 6 JavaScript ideas
  • 3 ways to build it

Why build it

Showing and hiding content is how you build FAQ pages, collapsible sections in long articles, filter groups in a shop's sidebar, and expandable rows on a settings page. You'll also know when the browser's own details element is enough, and when to write JavaScript for something it can't do, like keeping only one section open.

Skills you'll earn

  • Show and hide content with details and summary, with no JavaScript at all
  • Build toggle buttons that tell screen readers whether they're open, with aria-expanded
  • Find every matching element and run the same code on each, with querySelectorAll and forEach
  • Keep only one section open at a time by closing the rest first

01

Try it

Play with it first, then read the code that makes it work.

3 ways to build it

The browser's own <details> element opens and closes each answer, with no JavaScript at all. Several answers can be open at once.

Result0px
New tab (opens in a new tab)
Download
<!doctype html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>Accordion</title>
		<link rel="stylesheet" href="style.css" />
	</head>
	<body>
		<main class="faq">
			<h1 class="faq-title">How a web page works</h1>

			<div class="accordion">
				<!-- <details> hides everything except its <summary> until it's opened. -->
				<details class="accordion-item">
					<!-- <summary> is the clickable part, and works with a keyboard for free. -->
					<summary class="accordion-trigger">
						What does HTML do?
						<span class="accordion-icon" aria-hidden="true">+</span>
					</summary>
					<div class="accordion-panel">
						<p>
							HTML gives the page its structure: headings, paragraphs, buttons,
							and links. It says what each thing is.
						</p>
					</div>
				</details>

				<details class="accordion-item">
					<summary class="accordion-trigger">
						What does CSS do?
						<span class="accordion-icon" aria-hidden="true">+</span>
					</summary>
					<div class="accordion-panel">
						<p>
							CSS decides how everything looks: colours, sizes, spacing, and
							where things sit on the screen.
						</p>
					</div>
				</details>

				<details class="accordion-item">
					<summary class="accordion-trigger">
						What does JavaScript do?
						<span class="accordion-icon" aria-hidden="true">+</span>
					</summary>
					<div class="accordion-panel">
						<p>
							JavaScript makes the page respond. It listens for things like clicks
							and key presses, then changes the page to match.
						</p>
					</div>
				</details>
			</div>
		</main>
	</body>
</html>

02

How it works

The ideas behind it, one at a time, each next to the code that does it.

3 ways to build it

The browser's own <details> element opens and closes each answer, with no JavaScript at all. Several answers can be open at once.

HTMLthe structure

  1. 01

    Let <details> and <summary> do the work

    <details> is an HTML element that hides its content until someone opens it. The <summary> inside it stays visible and works as the clickable question. Clicking it, or pressing Enter or Space when it has focus, shows or hides the rest. The browser handles all of this, including telling screen readers whether it's open or closed, so this way needs no JavaScript.

    				<!-- <details> hides everything except its <summary> until it's opened. -->
    				<details class="accordion-item">
    					<!-- <summary> is the clickable part, and works with a keyboard for free. -->
    					<summary class="accordion-trigger">
    						What does HTML do?
    						<span class="accordion-icon" aria-hidden="true">+</span>
    					</summary>
    					<div class="accordion-panel">
    						<p>
    							HTML gives the page its structure: headings, paragraphs, buttons,
    							and links. It says what each thing is.
    						</p>
    					</div>
    				</details>

CSSthe look

  1. 02

    Swap the built-in arrow for your own icon

    Browsers draw a small triangle next to every <summary> to show it can open. This design uses its own + icon, so the triangle has to go. list-style: none removes it in most browsers, because they draw it like a list bullet. Safari draws it as ::-webkit-details-marker instead, so a second rule hides that with display: none.

    	/* Hide the browser's own arrow; the + icon replaces it. */
    	list-style: none;
    }
    
    /* Safari draws its arrow differently, so it needs its own rule. */
    .accordion-trigger::-webkit-details-marker {
    	display: none;
    }
  2. 03

    Style the open state with [open]

    An attribute is extra information written in an element's tag, like class or href. The browser adds the open attribute to <details> while it's showing, and removes it when it closes. CSS can select elements by attribute with square brackets, so .accordion-item[open] .accordion-icon rotates the + by 45 degrees into a ×, with no JavaScript.

    /* The browser adds [open] to <details> while it's showing: + turns into ×. */
    .accordion-item[open] .accordion-icon {
    	transform: rotate(45deg);
    }

03

Wrap up

Track your progress, then go deeper or keep going.

Take it further

Once it works, try these on your own. Each one uses what you've just learned, plus one new idea.

  1. Challenge 01

    Animate the panels opening and closing, and skip the animation for reduced motion.

  2. Challenge 02

    Add Expand all and Collapse all buttons.

  3. Challenge 03

    Open the panel named in the page's address, like #panel-css, when the page loads.

Articles that go further into ideas from this project.

Finished Accordion?

Mark it done to track your progress.

You finished Accordion!

0 of 15 projects done.

Go deeper

The full article explains each idea in more depth, why the code is written this way, and more than fits on this page.

Read the article (opens in a new tab)