Zach’s ugly mug (his face)

Zach Leatherman

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

February 08, 2022 #3 Popular Check out all the web components.

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!

This is a web component—I have others! Check out all the web components.
Zach’s ugly mug (his face)

Zach is a builder for the web with IndieWeb Avatar for https://www.netlify.comNetlify. He created the IndieWeb Avatar for https://www.11ty.devEleventy site generator and is still fixated on web fonts. His public speaking résumé includes talks in eight different countries at events like Jamstack Conf, Beyond Tellerrand, Smashing Conference, CSSConf, and The White House. He is an emeritus of Filament Group, NEJS CONF, and still helps out with nebraskajs’s AvatarNebraskaJS. Read more about Zach »

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


David BissetStefan MateiMehdi Achour全部入りHTML太郎そめJoulseChris HeilmannFriday Front-EndMatt BiilmannEmmanuel 🌱Bramus!Adactio LinksAlvin A.Web StandardsВеб-стандартыtreb0r.eth ∞Véronique BouvierBruce AndersonJess Peck 🐍🤖Kewish FagoeMartin SchneiderSteve FaulknerSøren BirkemeyerBaldur BjarnasonBaldur BjarnasonLynn FisherAymen Loukil


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. 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 it could be tested or even converted to oui-selectmenu

  2. Zach Leatherman


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

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

  4. Nicolas Hoizey



  5. 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!

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

  7. Zach Leatherman


    nO AND yEs 😇 LovED The oLd CARTooNs GroWinG Up

  8. Nicolas Hoizey


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

  9. Nicolas Hoizey

    Nicolas Hoizey

    @dav de rien, merci pour ce site ! 🙏

  10. David Larlet

    David Larlet

    @nhoizey merci pour le retour 🙇

  11. Nicolas Hoizey

    Nicolas Hoizey

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

  12. David Larlet

    David Larlet

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

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

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

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

  16. Andrew Rico


    Ty brother

  17. Thomas Steiner


    Safari doesn't support it.

  18. CheloXL


    Why not ?

  19. 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`.

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

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

  22. Michael 🧐 Fairchild


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

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

  24. Zach Leatherman


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

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

  26. Zach Leatherman


    Thanks Peter!

  27. Peter Hironaka


    i just foUNd ouT aboUt DEtaIls NOT toO LonG AGO 🤟🏽 So gOOD

  28. Bregt


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

  29. Zach Leatherman


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

  30. Aymen Loukil


    And Twitter doesn't correctly displays your post title

    Social Card Image Preview

    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)