Zach’s ugly mug (his face) Zach Leatherman

Add Responsive-Friendly Enhancements to <details> with <details-utils>

February 08, 2022

I use <details>. I use <details> a lot. It is one of my favorite HTML elements.

Over time I’ve collected a bunch of add-on utilities to enhance <details> with new features and functionality. They’ve been super useful in a bunch of long-standing production implementations at Netlify:

I’ve decided to finally package those <details> helpers up and formally release them as a web component!


	<!-- you can have one or more <details> elements in here -->

At time of writing, this web component adds five new responsive-friendly enhancements to one or more <details> elements nestled inside:

  • Force open/closed
  • Click outside to close
  • Close on esc
  • Animate open/closed
  • Toggle root element class

Force open/closed

In this example, the <details> is forced open when viewport is wider than 48em.

<details-utils force-open="(min-width: 48em)" force-restore>
	<details open></details>

I’ve gotten a lot of mileage out of the above example, specifically to drive navigation that is always visible at a certain breakpoint (think a collapsible menu at small viewport versus sidebar, e.g.

Alternatively, force-close is also available. The optional force-restore attribute will restore previous state when the force-open or force-close media queries do not match.

The media query is optional, and using it as a bare attribute allows control of the state pre and post JavaScript.

<!-- closed without JS, open with JS -->
<details-utils force-open>

<!-- open without JS, closed with JS -->
<details-utils force-close>
	<details open></details>

Click outside to close

If you click anywhere on the document (outside of the <details> content), the <details> will be closed. This is useful when you want to absolutely position the <details> content (maybe to make a little custom dropdown 😱)

<details-utils close-click-outside>

You can scope this with a media query as well:

<details-utils close-click-outside="(min-width: 48em)">

Add your own bonus close button inside of the content (to complement <summary>):

/* Hide button without JS */
details-utils:not(:defined) [data-du-close-click] {
	display: none;
<details-utils close-click-outside>
	<details id="my-details">
		<button type="button" aria-controls="my-details" data-du-close-click>Close</button>

Close on esc

Closes the <details> when the esc key is hit on the keyboard. Media query is optional.

<details-utils close-esc="(max-width: 767px)">

Animate open/close

<details-utils animate>

Animates the height of the content when opening and closing the <details>. Ignored automatically if (prefers-reduced-motion) is detected.

Just a full disclosure, the configuration around this one is pretty limited (re: easing and timing). Also this doesn’t support media query scoping yet (not for any technical reason, just haven’t run into this use case yet). Open to contributions here!

Toggle class on root element

<details-utils toggle-document-class="my-class-name">

Adds a class to your <html> element when the <details> is open and removes it when the <details> is closed.


Wiring up and combining each of these enhancements to <details> really can go a long way in building a lot of complex user interface elements in a pretty straightforward way. In my humble opinion, the super long list of things I’ve built using this is proof of that. I hope you can get some useful mileage out of them too!

< Newer
Full Time Open Source Development for Eleventy, sponsored by Netlify
Older >
Migrating my 16+ year old web site to Netlify in a few short days

Zach Leatherman IndieWeb Avatar for a builder for the web and the creator/maintainer of IndieWeb Avatar for https://www.11ty.devEleventy (11ty), an award-winning open source site generator. At one point he became entirely too fixated on web fonts. He has given 81 talks in nine different countries at events like Beyond Tellerrand, Smashing Conference, Jamstack Conf, CSSConf, and The White House. Formerly part of CloudCannon, Netlify, Filament Group, NEJS CONF, and NebraskaJS. Learn more about Zach »


Aymen LoukilLynn FisherBaldur BjarnasonBaldur BjarnasonSøren BirkemeyerSteve FaulknerMartin SchneiderKewish FagoeJess Peck 🐍🤖Bruce AndersonVéronique BouvierIndieWeb Avatar for https://www.alvinashcraft.comtreb0r.eth ∞Веб-стандартыWeb StandardsAdactio LinksEmmanuel 🌱IndieWeb Avatar for https://www.bram.usMatt BiilmannFriday Front-EndChris HeilmannIndieWeb Avatar for https://ic1technologies.comJoulseそめ全部入りHTML太郎IndieWeb Avatar for AchourStefan MateiIndieWeb Avatar for https://cloudfour.comDavid BissetIndieWeb Avatar for https://www.gakglobal.comCOMMENTSENSE


Alex RussellAlecChris 🍋🎙Alex DraperMark 🎨Francis Rubio  (Archon Collector)aaron hansTracy Lee | ladyleetbertrandkellerJustin Fagnani⚡️ Salma | whitep4nth3rMatt BiilmannJake DohmJoe GaffeyNetlifyRyan MulliganEmmanuel 🌱Matheus RichardArpitDavid Hund ✌myfMuriel SilveiraMatt Ström▇▇▇Brett EvansYavorskiFlorian GeierstangerMai Tấn Lợitreb0r.eth ∞GriepEric WallaceLiam FiddlerLachlan CampbellnicMatthias Westonloafing loafJordan RunningZearinRobert SpierJordan Finneran玲Peter RushforthMartin SchneiderJake Dohm𝕕𝔾𝕣𝕒𝕞𝕞𝕒𝕥𝕚𝕜𝕠MayankJoe GaffeyMichael PPeter HironakaEvren CaglayanMatthew PhillipsKewish FagoePatrick HaugJelmer de MaatAlex DraperAleksandr HovhannisyanZeeshanKΞNNETH🌟 💉💉💉SteinErik SkotkjerraColin FahrionBjörn RixmanJakub IwanowskimuanMike AparicioInsetBruce AndersonBaldur BjarnasonSideshow CharlesJeremy WynnOren ElbaumjkRyan MulliganJess Peck 🐍🤖Emmanuel DEMEYSteve LeeBregt🌸🌕⭐🌕🌸Chase McCoyMarc GörtzLeonardo MatosSadegh BaratiSøren BirkemeyerZac SkalkoSteve FaulknerGaël PoupardLynn FisherConnor Bär 🐼dies das 🦂 contentAymen Loukilfred
  1. Aymen Loukil


    And Twitter doesn't correctly displays your post title

  2. Zach Leatherman


    Fix is building—thanks! (although Twitter’s cache might be sticky for a bit)

  3. Bregt


    Cool. I haven't used this element until recently, but notice issues with a11y regarding headings in <summary> etc. It put me off, but then saw some examples on Github and now yours. I should reconsider.

  4. Peter Hironaka


    I just found out about details not too long ago 🤟🏽 so good

  5. Zach Leatherman


    Thanks Peter!

  6. Michael 🧐 Fairchild


    This is awesome! Thank you! The Toggle Document Class example is rendered as a modal dialog but is missing required modal dialog semantics for #a11y, and content behind the open modal is still findable/interactive with keyboard/sr, which fails several WCAG SC. Thoughts?

  7. Zach Leatherman


    Ah, very fair point. I’m going to remove that example for now until I get a better story there—thank you!

  8. Steve Lee


    FYI, doesn't effect your code but we recently found out the the JAWS screen reader strips out all tags from the Summary, mapping it to text. That's actually one response to some annoying spec problems. Also avoids some confusing possibilities allowed.

  9. Michael 🧐 Fairchild


    Good point. Here is some evidence of that… (heading semantics are stripped in JAWS and a couple other combinations)

  10. Steve Lee


    The spec allows links but then you end up with two actions; expand/collapse and navigate, which is confusing visually and semantically unavailable on the a11y APIS :( There's an issue with FS.

  11. Steve Lee


    That said, it's one of the few "controls" that can be nicely styled with CSS :) Just as well as the browser defaults are rather naff imho.

  12. Thomas Steiner


    Oh, nice! The “Tweak” menu of SVGcode ( is essentially this, but it hides the outer `summary` when the viewport is large enough. Resize the window to test. Your force-open behavior also reminds me of @briankardell’s `spicy-section`.

  13. CheloXL


    Why not <details is=enhanced>?

  14. Thomas Steiner


    Safari doesn't support it.

  15. Andrew Rico


    Ty brother

  16. Eric Eggert


    I have no idea how web components work… But could that not just be data attributes (or classes)? *sigh* I really need to catch up.

  17. Zach Leatherman


    The huge benefit of web components (imo, and especially from a jQuery mindset) is that you don’t need to do any queryselectoring to find and init the elements (the platform gives you that for free). So yes, they could be data attrs but then I’d have to find and init them manually

  18. Thomas Steiner


    That's right, but it's extra code. It would be wonderful if it were supported directly, but @webkit has decided to WONTFIX the bug… unfortunately.

  19. David Larlet

    David Larlet

    @nhoizey @accessiblestef oui je suis ça de près 👍 Le sautillement ça doit être ouverture combinée au scroll ?

  20. Nicolas Hoizey

    Nicolas Hoizey

    @dav oui, c’est ça, le problèmene se poserait pas sans scroll.@accessiblestef

  21. David Larlet

    David Larlet

    @nhoizey merci pour le retour 🙇

  22. Nicolas Hoizey

    Nicolas Hoizey

    @dav de rien, merci pour ce site ! 🙏

  23. Nicolas Hoizey


    Are you also in charge of content, and fan of X-Men? 😅

  24. Zach Leatherman


    No and yes 😇 Loved the old cartoons growing up

  25. Nicolas Hoizey


    Just saw 2 movies, I guess I'll have to see more when Marvel starts mixing them with the Avengers in the coming Multiverse… 😅 I guess you can tell the right person there's a typo?

  26. Zach Leatherman


    ahaha thank you for being very clear—I somehow did not even connect that was a typo 😅 I’ll let the team know, thank you!

  27. Nicolas Hoizey



  28. Greg Whitworth


    How interested would Netlify be to get engaged in Open UI given your creation of web components and driving the direction/utilization in prod of these components for feedback?

  29. Zach Leatherman


    Whew, good question. I’m super focused on Eleventy open source right now and I’m wary to split time there

  30. Greg Whitworth


    definitely didn't mean you specifically, I know @soMelanieSaid is there but unsure who owns all of what. So if this component maps to <selectmenu> it could be tested or even converted to oui-selectmenu

  31. @DavidDarnes @zachleat I thought I'd seen this somewhere - should have known to check Zach's stuff!

Shamelessly plug your related post

These are webmentions via the IndieWeb and

Sharing on social media?

This is what will show up when you share this post on Social Media:

How did you do this? I automated my Open Graph images. (Peer behind the curtain at the test page)