More Details on `details`

Avatar of Geoff Graham
Geoff Graham on

A lot of chatter around the ol’ <details> and <summary> elements lately! I saw Lea Verou recently tweet an observation about the element’s display behavior and that sorta splintered into more observations and usage notes from folks, including a revived discussion on whether <summary> should be allowed to contain interactive elements or not.

There are a lot of dots to connect and I’ll do my best here to do exactly that.

Can we change the display of elements nested in the <details> element?

Super weird! If we crack open DevTools, the user agent stylesheet tells us <details> is a displayed as a block element.

Notice the required <summary> element and the two additional <div>s in there. We can override the display, right?

What we might expect is that <details> now has an explicit height of 40vh and three rows where the third row takes up the remaining space leftover from the first two. Like this:

Open details element with a summary of foo and two child elements, one yellow and one blue. The blue element takes up the rest of the space left by summary and the first child.

Ugh, but the third row doesn’t… do… that.

Open details element with a summary of foo and two child elements, one yellow and one blue. The summary and two child elements are all the same height.

Apparently what we’re dealing with is a grid container that is unable to apply grid behavior to its grid items. But the HTML spec tells us:

The details element is expected to render as a block box. The element is also expected to have an internal shadow tree with two slots.

(Emphasis mine)

And a little later:

The details element’s second slot is expected to have its style attribute set to “display: block; content-visibility: hidden;” when the details element does not have an open attribute. When it does have the open attribute, the style attribute is expected to be removed from the second slot.

(Emphasis mine, again)

So, the spec says the second slot — the two additional <div>s from the example — are only coerced into being block elements when <details> is closed. When it’s open — <details open> — they should conform to the grid display that overrides the user agent styling… right?

That’s the debate. I get that slots are set to display: contents by default, but jamming nested elements into slots and removing the ability to style them seems off. Is it a spec issue that the contents are slots, or a browser issue that we cannot override their display even though they are in the box tree? Smarter people can enlighten me but it seems like an incorrect implementation.

Is <details> a container or an interactive element?

Lots of folks are using <details> to toggle menus open and closed. It’s a practice popularized by GitHub.

DevTools open with the details element highlighted in orange.

Seems reasonable. The spec sure allows it:

The details element represents a disclosure widget from which the user can obtain additional information or controls.

(Emphasis mine)

Alright, so we might expect that <details> is the container (it has an implicit role=group) and <summary> is an interactive element that sets the container’s open state. Makes sense since <summary> has an implcit button role in some contexts (but no corresponding WAI-ARIA role).

But Melanie Sumner did some digging that not only seems to contradict that, but leads to the conclusion that using <details> as a menu probably ain’t the best thing. See what happens when <details> is rendered without the <summary> element:

It does exactly what the spec suggests when it’s missing a <summary> — it makes its own:

The first summary element child of the element, if anyrepresents the summary or legend of the details. If there is no child summary element, the user agent should provide its own legend (e.g. “Details”).

(Emphasis mine)
DevTools open with the summary markup highlighted in orange.

Melanie ran that through an HTML validator and — surprise! — it’s invalid:

Error, element details is missing a required instance of child element summary.

So, <details> requires the <summary>. And when <summary> is missing, <details> creates it’s own, though it’s relayed as invalid markup. It’s all hunky-dory and valid when <summary> is there:

Success message from the W3C HTML validator with the markup for a details element and summary that contains a link element.

All of which leads to a new question: why is <summary> given an implcit button role when <details> is what appears to be the interactive element? Perhaps this is another case where the browser implementation is incorrect? Then again, the spec does categorize both as interactive elements. You can see how utterly confusing all of this becomes.

Either way, Melanie’s ultimate conclusion that we ought to avoid using <details> for menus is based on how assistive tech reads and announces <details> that contain interactive elements. The element is announced, but there is no mention of interactive controls beyond that until you, er, interact with <details>. Only then will something like a list of links be announced.

Besides, content inside a collapsed <details> is excluded from in-page searching (except in Chromium browsers, which can access the collapsed content at the time of writing), making things even more difficult to find.

Should <summary> allow interactive elements?

That’s the question posed in this open thread. The idea is that something like this would be invalid:

<details>
  <summary><a href="...">Link element</a></summary>
</details>

<!-- or -->

<details>
  <summary><input></summary>
</details>

Scott O’Hara sums up nicely why this is an issue:

The link is not discoverable at all to JAWS when navigating with its virtual cursor. If navigating to the summary element via the Tab key, JAWS announces “example text, button” as the name and role of the element. If hitting Tab key again, JAWS again announces “example text, button” even though keyboard focus is on the link.

[…]

There is more I could go on about with the various problems different AT have with the content model for summary… but that would just extend this comment out beyond what is necessary. tldr; the summary content model produces very inconsistent and sometimes just flat out broken experiences for people using AT.

Scott opened tickets to correct this behavior in Chromium and WebKit. Thanks, Scott!

Yet, it’s valid HTML:

Success message from the W3C validator with details markup.

Scott goes further in a separate blog post. For example, he explains how slapping role=button on <summary> might seem like a reasonable fix to ensure it is consistently announced by assistive tech. That would also settle the debate over whether <summary> should allow interactive elements because buttons cannot contain interactive elements. The only problem is that Safari then treats <summary> as a standard button, which loses its expanded and collapsed states. So, the correct role is announced, but now its state is not. 🙃

Where do we go now?

Are you scared to use <details>/<summary> with all of these issues and inconsistencies? I sure am, but only insofar as to make sure that what’s in it provides the right sort of experience and expectations for users.

I’m just glad these conversations are happening and that they’re taking place in the open. Because of that, you can comment on Scott’s three proposed solutions for how the content model for <summary> is defined, upvote his tickets, and report your own issues and use cases while you’re at it. Hopefully, the better we understand how the elements are used and what we expect them to do, the better they are implemented.