DEV Community

Cover image for Creating Modern Accordion Components with CSS and HTML only
Tomas Rezac for Ciklum CZ&SK

Posted on • Edited on

Creating Modern Accordion Components with CSS and HTML only

Welcome to the first instalment of a series dedicated to crafting common components using only modern CSS and HTML.

Note: I am the author of Sugar.css, a minimalistic CSS Framework built with the latest CSS. You can explore a more advanced implementation of a similar accordion on Sugar.css.


Assignment

What are the essential features of a proper Accordion?

  • Toggle content on user input or programmatically
  • Accessibility (toggle on Enter and Space)
  • Disable access to accordion content (by keyboard) when the accordion is collapsed
  • Stacking multiple accordions after each other
  • Auto close other accordions in the group when one is opened

Toggling Content

Gone are the days when the only way to toggle styles permanently was through a label with a hidden checkbox. For the past few years, we've been able to use a combination of details and summary HTML elements to achieve this. The details element hides all its content by default, except for a summary element if placed as a direct child. The summary serves as a toggle button; if not present, the text details is added as a default toggle. By clicking the toggle, the rest of the hidden content is revealed. Let's observe the default behavior and design:

Accessibility

All accessibility features are built-in; the summary has a default tabindex and can be toggled by Space and Enter keys, so no additional work is needed here.

Disabling Access to Content When Collapsed

While this functionality should work out of the box, there's an exception with Safari. If the details element is collapsed and contains focusable elements like input or button, tabbing in Safari will be consumed by those hidden elements. To ensure consistent accessibility across browsers, a simple JavaScript solution is required. The content is wrapped, and the inert attribute needs to be set to the wrapper once the details is collapsed.

Styling

Let's apply some CSS to enhance the appearance. First, we'll remove the original triangle indicator. This can be done differently in various browsers, but the following CSS accomplishes this:

summary::marker,
summary::-webkit-details-marker {
  display: none;
}

summary {
  list-style:none;
}
Enter fullscreen mode Exit fullscreen mode

Next, we'll style the summary to resemble an accordion header and prepare it for a new chevron:

summary {
  list-style: none;
  display: flex;
  gap: 1rem;
  align-items: center;
  justify-content: space-between;
  cursor: pointer;
  padding-block: var(--padding);
  font-weight:bold;
}

details {
  --padding: 0.75rem;
  --border-width: 0.1rem;
  --chevron-size: 0.8rem;

  font-family: system-ui;
  font-size: 1rem;
}
Enter fullscreen mode Exit fullscreen mode

To implement the new chevron for the base accordion, we'll create a rotated box with just two borders. The state of the opened accordion is selected by details[open]:

details summary:after {
  content: '';
  margin-inline-end: var(--padding);
  width: var(--chevron-size);
  height: var(--chevron-size);
  border: solid currentColor;
  border-width: 0 0 var(--border-width) var(--border-width);
  transform: rotate(-45deg) translateY(-30%);
  transition: transform 0.3s;
  flex-shrink: 0;
}

details[open] summary:after {
  transform: rotate(45deg);
}
Enter fullscreen mode Exit fullscreen mode

Lastly, we'll add separators between accordions if there are more consecutive ones:

details:not(:last-of-type) {
  margin-bottom: var(--padding);
  padding-bottom: var(--padding);
  border-bottom: var(--border-width) solid gray;
}
Enter fullscreen mode Exit fullscreen mode

Grouping Accordions

Another useful feature of details is its acceptance of a name attribute. All details with the same name behave as a group. When you open one, the others in the same group automatically close.

Check out the result

Additional styles like colours and spacings can make it more vivid


Conclusion

As demonstrated, details and summary are fully capable of replacing JavaScript-driven accordions. They make implementation easier and provide immediate accessibility (with the exception of Safari, which requires a workaround for a specific edge case).

However, there's one potential drawback: the lack of animation support. If animation is applied to collapsed content within details, it runs only once when opened and cannot be rerun when opened next time. This limitation may need to be considered based on the specific design and functionality requirements of your project.

Next time we will check the dialog element. See you soon.

Top comments (0)