



























This is a redress of my 2019 post Link + Disclosure Widget Navigation, except (as the title implies), I’ve modified it to use native HTML popovers instead of ARIA or HTML disclosure widgets.
Popover has the benefit of using appropriate HTML structure and semantics while removing the need for scripting and ARIA. I use some ARIA here regardless.
popover vs. Disclosure Widgets
ARIA-based disclosure widgets (<button aria-expanded>) require script to work. HTML-based disclosure widgets (<details> / <summary>) expand when there is a hit for in-page searches (in two engines), have inconsistent exposure to accessibility APIs (across browsers and over time), and in my experience confuddle teams with styling overrides. I have a 2020 post going into some detail on each.
The popover feature requires CSS for positioning. Cross-browser anchor positioning support only came about recently. Because popovers appear on the top layer, you have to be careful with anything that uses z-index. Only use this pattern if all the dialogs on your site are already using the native HTML <dialog> element, otherwise overlapping issues happen.
Embedded below or visit it directly at Codepen. There’s also a debug version.
See the Pen Link + Popover Nav by Adrian Roselli (@aardrian) on CodePen.
The navigation lives in a <nav> as a list with nested lists.
<header>
<nav id="Nav">
<ul>
[…]
</ul>
</nav>
</header>
The links are links. They work with a keyboard, assistive technology knows what to do with them, and links are generally well understood by users.
I identify that the current parent page is the About page and the current page is Job Postings by using aria-current="page". I also use that as my CSS selector and you should too.
<li>
<a href="[…]" id="Item02" aria-current="page">About</a>
[…]
<ul id="SubItem02" popover>
[…]
<li><a href="[…]" aria-current="page">Job Postings</a></li>
</ul>
</li>
As my older pattern, the <button> element is the trigger. Unlike my older pattern, it doesn’t use aria-expanded.
Instead it uses popovertarget, which brings the programmatic state aria-expanded for free. The value of popovertarget must be the id of the content whose appearance you want to control (the popover content). The popover content needs the popover attribute for this to work.
No CSS or JavaScript is needed to make this content appear or disappear.
<button type="button" id="btnItem02" aria-labelledby="Item02" popovertarget="SubItem02">
<svg […]>[…]</svg>
</button>
<ul id="SubItem02" popover>
[…]
</ul>
This is the second place I still use ARIA. To avoid text duplication and auto-translation issues, I use aria-labelledby to reference the text of the preceding link. Screen reader users hear / feel a different control type and that it’s expandable, which has proven to be sufficient context. For voice users, saying the visible text presents them with the option to choose the link or the button.
<a href="[…]" id="Item02" aria-current="page">About</a>
<button type="button" id="btnItem02" aria-labelledby="Item02" popovertarget="SubItem02">
<svg […]>[…]</svg>
</button>
You must place the popover content immediately after the popover trigger, otherwise you risk reading order and focus order problems for users. The popover feature does not automatically do any focus management.
It comes for free with popover.
It comes for free with popover.
You’ll have to write your own.
Not all of these styles will work for you, but these may matter:
z-index to sit in front of them.color-scheme: light dark just so I could more easily see styling gaps, but I don’t recommend that for real-life use.:popover-open when the popover appears / disappears. It honors user motion preferences.There is a button on the demo to remove all styles from the page, making it easier to see how this will perform as raw HTML, for easy testing, or for CSS Naked Day.
I haven’t played with popovers much. Positioning it to work across Firefox, Chromium, and Safari while also not overflowing the window or falling apart with text direction changes proved to be a challenge. I welcome suggestions on improvements.
My goal was to have the popover appear to the right edge of the parent list item and just below the button — for left-to-right languages — and in a corresponding location for other language text directions.
[popover] {
inset: auto;
position-anchor: auto;
inset-block-start: anchor(self-end);
inset-inline-end: calc(anchor(self-end) - 1em);
}
I flailed about trying different values from the spec and struggled to understand logical properties with anchor positioning. As it is, the popover positioning falls apart with the vertical writing modes, but I can’t be sure if that’s my code or browser bugs (¿Por qué no los dos?).
There are reasons I built this pattern.
Early in 2017 I filed an issue against ARIA Authoring Practices (APG) requesting a change to the menu navigation pattern. Despite a great deal of feedback in agreement, it continues to languish. In late 2017 I wrote Don’t Use ARIA Menu Roles for Site Nav and started actively campaigning against the APG pattern. In 2019, Sarah Higley proposed a disclosure-only APG pattern and then a disclosure and link pattern proposal in 2020.
HTML (via Open-UI) has since stepped in to fill some gaps, so here we are.
Standard disclaimers apply: may not work for your audience, likely has bugs, support can change, new features may moot this, my design sense is poor, yes you have to write script to get whatever custom interactions you think are nifty but which probably annoy users, who even writes code anymore, using [insert random element here] in a way that’s not mentioned in this post is your problem not mine, etc.
And if you have more experience with multilingual popover anchor positioning, please share!
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。