Popover, Anchor, Select: When the Browser Builds Your UI
Posted on: 10/5/2026 1:20:58 AM
Table of contents
- 1. Why do tooltips, menus and selects need so much JavaScript?
- 2. The map: every problem now has a native primitive
- 3. The top layer and the Popover API: the foundation of every overlay
- 4. Invoker Commands: wiring buttons to actions in HTML
- 5. Anchor Positioning: no more computing coordinates in JavaScript
- 6. Customizable Select: you can finally style the select element
- 7. Interest Invokers: tooltips and hover cards done right
- 8. Open/close animations without an animation library
- 9. Browser support (October 2026)
- 10. Adoption strategy: three-tier progressive enhancement
- 11. Measuring the impact of the migration
- Conclusion
Open the package.json of any frontend project and count how many libraries exist just to do the "small" things: one library to compute tooltip coordinates, one for dropdowns, one for modals plus a focus trap, a "click outside to close" hook, a Portal component to escape overflow: hidden, and a never-ending z-index: 9999 war. Each is only a few KB, but together they add up to tens of KB of JavaScript running on the main thread, along with countless bugs around keyboards, screen readers and hydration.
In 2026, the browser has quietly taken back most of this work. The Popover API reached Baseline in early 2025, Invoker Commands (the command/commandfor attributes) reached Baseline in December 2025, CSS Anchor Positioning has been available in all three engines since Firefox 147 shipped on January 13, 2026, and in mid-September 2026 Safari 27 became the second engine to support customizable select — the <select> element can finally be styled with CSS. This article dissects each primitive, how they combine into complete tooltips, menus, dialogs and dropdowns, the real browser support picture as of October 2026, and a safe migration strategy for production projects.
1. Why do tooltips, menus and selects need so much JavaScript?
A dropdown looks simple, but to get it right it has to solve at least seven hard problems, and until recently the browser helped with none of them:
- Escaping the stacking context: a menu inside a card with
overflow: hiddenor atransformgets clipped. The classic fix is a "portal" — moving the menu's DOM to the end of<body>— which then requires syncing its position with JavaScript. - Positioning and collision handling: computing coordinates from
getBoundingClientRect(), updating on scroll and resize, flipping upward near the bottom of the viewport, shifting left near the right edge. - Light dismiss: click outside to close, press Esc to close, but clicking inside the menu must not close it.
- Focus management: trap focus inside a modal when it opens, return focus to the right button when it closes; the rest of the page must become inert to both mouse and keyboard.
- ARIA semantics:
aria-expandedhas to flip at the right moment, and the relationship between button and content has to be declared so screen readers understand it. - The "only one" rule: opening menu B must close menu A, unless B is a submenu of A.
- Enter/exit animations: you cannot transition an element out of
display: none, so you reach for an animation library or hand-rolledsetTimeoutcalls.
Every UI library solves these seven problems its own way, with varying degrees of completeness. The result: on the same page, library A's tooltip closes on Esc while library B's dropdown doesn't; C's modal restores focus correctly while D's doesn't.
The hidden cost of JavaScript overlays
Beyond bundle size, every scroll/resize listener and every position recalculation runs on the main thread — exactly where INP (Interaction to Next Paint) is decided. In server-rendered apps, these components also wait for hydration before they work: a user who taps the menu button before JavaScript finishes loading sees nothing happen. If you are optimizing INP, see also Core Web Vitals 2026: Optimizing LCP, INP and CLS.
2. The map: every problem now has a native primitive
The beauty of the new generation of APIs is that they are not one giant "component" but small, composable pieces. Each problem above is solved by its own browser primitive:
flowchart LR
subgraph P["Problems every overlay faces"]
P1["Clipped by overflow, z-index wars"]
P2["Compute coordinates, flip at edges"]
P3["Click outside, Esc to close"]
P4["Focus, ARIA, only one menu open"]
P5["Wire a button to an action"]
P6["Show tooltip on hover or focus"]
P7["Style a value-picking dropdown"]
P8["Open and close animations"]
end
subgraph N["Native browser primitives"]
N1["Top layer: popover, dialog"]
N2["CSS Anchor Positioning"]
N3["Light dismiss: popover auto, closedby"]
N4["Popover stack, focus return, aria-expanded"]
N5["Invoker Commands: command, commandfor"]
N6["Interest Invokers: interestfor, popover hint"]
N7["Customizable select: base-select"]
N8["starting-style, allow-discrete"]
end
P1 --> N1
P2 --> N2
P3 --> N3
P4 --> N4
P5 --> N5
P6 --> N6
P7 --> N7
P8 --> N8
style N1 fill:#e94560,stroke:#fff,color:#fff
style N2 fill:#e94560,stroke:#fff,color:#fff
style N3 fill:#2c3e50,stroke:#fff,color:#fff
style N4 fill:#2c3e50,stroke:#fff,color:#fff
style N5 fill:#2c3e50,stroke:#fff,color:#fff
style N6 fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style N7 fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style N8 fill:#f8f9fa,stroke:#e94560,color:#2c3e50
These pieces did not arrive at once. The timeline shows why 2026 is the year the set became complete:
@starting-style.appearance: base-select) together.interestfor). Firefox 144 and then Safari 26.2 ship Invoker Commands, making it Baseline on December 12, 2025.:open, hint popovers) and a continuation of Anchor Positioning.3. The top layer and the Popover API: the foundation of every overlay
The single most important concept is the top layer: a special rendering layer that sits above the entire page regardless of any ancestor's z-index, overflow or transform. Previously only modal <dialog> elements and fullscreen elements could get there. The Popover API opens that door to any element with a single HTML attribute — which means no more portals: the menu's DOM lives right next to its button, in natural reading order, yet renders above everything.
<button popovertarget="user-menu">Account ▾</button>
<div id="user-menu" popover>
<a href="/profile">Profile</a>
<a href="/settings">Settings</a>
<a href="/logout">Sign out</a>
</div>
Not a single line of JavaScript, yet the browser already handles all of this:
- Promotes
#user-menuto the top layer when opened and hides it when closed. - Light dismiss: clicking outside or pressing Esc closes it.
- Exposes the correct
aria-expandedstate for the button in the accessibility tree. - When the popover closes while focus is inside it, focus returns to the previously focused element — usually the button that opened it.
- Manages the popover stack: opening another popover closes the old one, unless the new one was opened from a button inside the old one (nested submenus just work).
Popovers come in three modes that differ in how they close and how they relate to other popovers:
| Value | Light dismiss | Relationship to other popovers | Use for |
|---|---|---|---|
popover / popover="auto" | Yes | Opening a new one closes unrelated auto popovers | Menus, dropdowns, date pickers, pickers |
popover="manual" | No | Independent; must be closed by a button or JavaScript | Toasts, notifications, persistent panels |
popover="hint" | Yes | Opening a hint does not close open auto popovers; it only closes other hints | Tooltips, hover cards, short hints |
A popover is not a "menu" in the ARIA sense
The popover attribute assigns no role. Don't rush to add role="menu": that role promises screen reader users that items can be navigated with arrow keys, and if you don't implement that navigation yourself, the experience is worse than having no role at all. For simple navigation menus, a plain list of links or buttons inside the popover is the most accessible choice. Declarative arrow-key navigation is being standardized through the focusgroup attribute — Chrome has already run an origin trial for it.
4. Invoker Commands: wiring buttons to actions in HTML
popovertarget can only control popovers. Invoker Commands generalize the idea: any <button> can issue a command to another element through two attributes, commandfor (the target's id) and command (the action). The built-in commands currently are show-popover, hide-popover, toggle-popover, show-modal, close and request-close. The feature became Baseline on December 12, 2025 (Chrome 135, Firefox 144, Safari 26.2).
<button commandfor="confirm-delete" command="show-modal">Delete project</button>
<dialog id="confirm-delete" closedby="any">
<h2>Delete project "Apollo"?</h2>
<p>This action cannot be undone.</p>
<button commandfor="confirm-delete" command="request-close">Cancel</button>
<form method="dialog">
<button value="confirm">Delete permanently</button>
</form>
</dialog>
That snippet produces a complete confirmation modal: the background is dimmed via ::backdrop and becomes inert, focus moves into the dialog, Esc closes it, clicking outside also closes it (thanks to closedby="any"), and focus returns to the "Delete project" button afterward. The difference between close and request-close: the latter fires a cancel event first, giving you a chance to intercept (for example, when a form has unsaved data).
sequenceDiagram actor U as User participant B as commandfor button participant BR as Browser participant D as dialog U->>B: Click, Enter or Space B->>BR: command = show-modal BR->>D: Fire command event, cancelable BR->>D: showModal, promote to top layer BR-->>BR: Rest of the page becomes inert BR->>D: Focus the first focusable element U->>BR: Press Esc or click the backdrop BR->>D: Fire cancel, then close BR->>B: Return focus to the opening button
For app-specific behavior you can define custom commands, which must start with two dashes. The browser still handles wiring the button to its target and keyboard accessibility; you only write the logic:
<button commandfor="gallery" command="--next">Next photo ›</button>
<div id="gallery">...</div>
<script>
gallery.addEventListener('command', (e) => {
if (e.command === '--next') showNextPhoto();
// e.source is the button that issued the command
});
</script>
The biggest win is not the lines of code saved but the fact that the button works as soon as the HTML is parsed, without waiting for JavaScript to load and hydrate. With built-in commands, the button that opens a dialog works from the very first frame.
closedby is not in Safari yet
The closedby attribute (any / closerequest / none) has been available since Chrome 134 and Firefox 141, but as of October 2026 Safari still doesn't support it — on Safari, a modal closes only via Esc, not by clicking the backdrop. It is part of the "Dialogs and popovers" focus area in Interop 2026, so support is likely coming. Meanwhile, never design a flow that relies solely on backdrop clicks to close: always provide a clear "Cancel" button.
5. Anchor Positioning: no more computing coordinates in JavaScript
The top layer solves "floating above everything", but a popover appears in the middle of the screen by default. To pin a menu right below its button we need CSS Anchor Positioning: declare one element as an anchor, then position another element relative to that anchor's geometry. Tracking scroll, resize and flipping is all handled by the layout engine, with zero listeners.
Four core concepts:
anchor-name: --anchor-nameon the anchor element.position-anchor: --anchor-nameon the positioned element, telling it which anchor to follow.position-area: divides the space around the anchor into a 3×3 grid and places the element in one or more cells, e.g.bottom,top span-right,right. This is the most concise syntax for 90% of cases.- The
anchor()andanchor-size()functions: used intop/left/width... when you need fine control, e.g.top: anchor(bottom)ormin-width: anchor-size(width).
.account-btn { anchor-name: --account; }
#user-menu {
position-anchor: --account;
position-area: bottom span-right; /* below the button, aligned to its left edge */
inset: auto; /* drop the popover's default inset: 0 */
margin: 4px 0 0;
min-width: anchor-size(width); /* at least as wide as the button */
position-try-fallbacks: flip-block, flip-inline;
}
A valuable detail: when a popover is opened via popovertarget or commandfor, the invoking button becomes the popover's implicit anchor. The spec is being refined so that declaring position-area alone makes the popover attach to whichever button opened it, with no anchor names needed — perfect for a table with hundreds of "⋯" buttons sharing one menu. During the transition, though, declaring anchor-name/position-anchor explicitly remains the safest approach.
Flipping automatically at viewport edges
position-try-fallbacks lists fallback options for when the base position overflows its containing block: flip-block (flip top/bottom), flip-inline (flip left/right), or a named option defined with @position-try. The position-try-order property (e.g. most-height) prioritizes the option with the most available space — handy for long menus.
@position-try --left-side {
position-area: left;
margin: 0 8px 0 0;
}
.tooltip {
position-area: bottom;
position-try-fallbacks: flip-block, --left-side;
position-try-order: most-height;
}
flowchart TD S["Apply the base position
position-area: bottom"] --> C1{"Does it overflow
the containing block?"} C1 -->|No| OK["Render at the base position"] C1 -->|Yes| ORD["Reorder the fallback list
by position-try-order"] ORD --> T1["Try each option in turn
flip-block, --left-side..."] T1 --> FOUND{"Any option
without overflow?"} FOUND -->|Yes| USE["Use the first option that fits
anchored container query knows it flipped"] FOUND -->|No| BASE["Fall back to the base position
or hide via position-visibility"] style S fill:#f8f9fa,stroke:#e94560,color:#2c3e50 style USE fill:#e94560,stroke:#fff,color:#fff style OK fill:#2c3e50,stroke:#fff,color:#fff style BASE fill:#f8f9fa,stroke:#e94560,color:#2c3e50
The last problem that used to require JavaScript: once a tooltip has flipped from bottom to top, its arrow still points the wrong way. Since Chrome 143, anchored container queries solve this: turn the positioned element into a query container with container-type: anchored, then query which fallback is in use:
.tooltip {
position-area: bottom;
position-try-fallbacks: flip-block;
container-type: anchored;
}
.tooltip::before { content: "▲"; position: absolute; bottom: 100%; }
@container anchored(fallback: flip-block) {
.tooltip::before { content: "▼"; bottom: auto; top: 100%; }
}
Baseline, but the spec is still "alive"
Anchor Positioning is in all three engines, yet it remains a carryover focus area in Interop 2026, aimed at clarifying the spec and improving reliability. Safari 27 alone changed the default value of position-anchor from auto to normal, renamed the anchors-visible/anchors-valid keywords to anchor-visible/anchor-valid (the old names remain temporarily supported), and started accounting for anchor transforms. Test in all three browsers before shipping, especially when anchors live inside animated elements.
6. Customizable Select: you can finally style the select element
<select> has long been CSS's oldest embarrassment: you could barely change the look of the dropdown list, let alone put icons or colors in each option. As a result, nearly every design system rebuilt dropdowns from divs, losing keyboard support, typeahead, autofill, mobile behavior and native form integration along the way. State of HTML 2024 found styling form controls (especially select) to be the number-one pain point, with 1,029 responses — 33% of participants.
Customizable select lets you keep a real <select> — with full semantics, form submission and keyboard behavior — while opening its entire rendering to CSS. You opt in with appearance: base-select on both the select and the ::picker(select) pseudo-element:
<label for="status">Status</label>
<select id="status" name="status">
<button><selectedcontent></selectedcontent></button>
<option value="todo"><span class="dot todo" aria-hidden="true"></span>To do</option>
<option value="doing"><span class="dot doing" aria-hidden="true"></span>In progress</option>
<option value="done"><img src="/icons/check.svg" alt="">Done</option>
</select>
@supports (appearance: base-select) {
select, ::picker(select) { appearance: base-select; }
select { border-radius: 10px; padding: 8px 12px; }
select::picker-icon { transition: rotate .2s; }
select:open::picker-icon { rotate: 180deg; }
::picker(select) {
border-radius: 12px;
box-shadow: 0 12px 32px rgb(0 0 0 / .12);
}
option { display: flex; align-items: center; gap: 8px; padding: 8px 12px; }
option:checked { font-weight: 600; }
option::checkmark { content: "✓"; }
}
The pieces to remember:
| Piece | Role |
|---|---|
appearance: base-select | Opts into customizable mode; required on both select and ::picker(select) |
<button> as the first child | Replaces the select's default button rendering |
<selectedcontent> | Automatically clones the selected option's content (icons included) into the button |
::picker(select) | The whole drop-down — essentially a popover in the top layer, pre-anchored to the button |
::picker-icon, ::checkmark | The button's arrow and the current option's checkmark |
:open, option:checked | Style based on the open state and the selected option |
Because the picker is a popover anchored to the button, you can use the same position-area and position-try-fallbacks from section 5 to change where it opens. Top layer, anchor and select are really one unified system.
WebKit's "golden rule": always put text in options
On June 15, 2026, the WebKit team published a post stressing a single rule: every option must have text content or an accessible text attribute. Never ship options that are just a color swatch or an icon. The reason is twofold: screen readers, braille displays and voice control software need text in the accessibility tree; and in older browsers the parser drops unknown tags inside select (such as <button> and <img>), keeping only the text. An option without text becomes an empty row. Use alt="" or aria-hidden="true" for decorative icons.
Two important limitations. First, this is not a combobox: there is no search field, no async data loading, no chip-style multi-select yet. Second, MDN warns that some JavaScript frameworks may block or break this new structure and that it can cause hydration failures with server-side rendering — test thoroughly with your framework before adopting it in a design system.
7. Interest Invokers: tooltips and hover cards done right
Tooltips are the hardest component to get right: they must appear on hover and on keyboard focus, delay just enough not to flicker when the pointer sweeps past, stay open while the user moves from the trigger to the tooltip content, and on touch screens there is... no hover. Interest Invokers encode all of that in the interestfor attribute: the browser detects "user interest" via hover, keyboard focus, a special hotkey, or a long-press on touch screens.
<a href="/u/designer" interestfor="card-designer">@designer</a>
<div id="card-designer" popover="hint">
<img src="/avatars/designer.webp" alt="">
<strong>Designer</strong> · 128 posts
</div>
a[interestfor] { interest-delay: 400ms 150ms; } /* show delay, hide delay */
a:interest-source { text-decoration-thickness: 2px; }
#card-designer:interest-target { outline: 2px solid #e94560; }
#card-designer { position-area: bottom; margin-top: 6px; }
Combined with popover="hint", the hover card won't close an open menu, and it is anchored to the link via the implicit anchor. The catch: as of October 2026, Interest Invokers are Chromium-only (since Chrome 142); Firefox is tracking it in its bug tracker and Safari has shown no signal yet. An interestfor polyfill is available on npm in the meantime.
8. Open/close animations without an animation library
The seventh problem — transitioning out of display: none — is solved by the pair @starting-style (which defines the "before it appears" state) and transition-behavior: allow-discrete (which allows transitioning discrete properties such as display). @starting-style has been Baseline since August 2024.
[popover] {
opacity: 0;
translate: 0 -6px;
transition: opacity .18s, translate .18s,
overlay .18s allow-discrete,
display .18s allow-discrete;
}
[popover]:popover-open { opacity: 1; translate: 0 0; }
@starting-style {
[popover]:popover-open { opacity: 0; translate: 0 -6px; }
}
@media (prefers-reduced-motion: reduce) {
[popover] { transition: none; }
}
The overlay property keeps the element in the top layer while the exit animation runs; in browsers that don't support it, the exit animation gets cut short but functionality is unaffected — progressive enhancement at work. For richer transitions between page states, see View Transitions API.
9. Browser support (October 2026)
| Feature | Chrome / Edge | Firefox | Safari | Status |
|---|---|---|---|---|
| Popover (auto / manual) | 116 | 125 | 17 | Baseline since Jan 2025 |
popover="hint" | 133 | 149 (partial) | Not yet (in Technology Preview) | Limited |
| Invoker Commands | 135 | 144 | 26.2 | Baseline since Dec 2025 |
dialog closedby | 134 | 141 | Not yet | Limited |
| Anchor Positioning | 125 | 147 | 26 | In all 3 engines since Jan 2026, spec still maturing |
| Anchored container queries | 143 | Not yet | Not yet | Early |
| Customizable select | 135 | Nightly, behind flag | 27 | 2 of 3 engines |
| Interest Invokers | 142 | Not yet | Not yet | Chromium only, polyfill available |
@starting-style | 117 | 129 | 17.5 | Baseline since Aug 2024 |
::details-content | 131 | 143 | 18.4 | Baseline since Sep 2025 |
Read the table as two groups: the Baseline group (popover, invoker commands, anchor positioning, @starting-style) can be used directly in most products today; the rest needs a progressive enhancement strategy.
10. Adoption strategy: three-tier progressive enhancement
A common mistake is waiting until "everything is Baseline", or conversely, rewriting the whole design system in one sprint. A more sustainable approach splits the work into three tiers:
- Tier 0 — semantic HTML: buttons are
<button>, value pickers are<select>, dialogs are<dialog>. This tier works in every browser. - Tier 1 — Baseline: popover,
commandfor, anchor positioning,@starting-style. Use directly; no fallback needed for modern browsers. - Tier 2 — still rolling out: customizable select,
closedby,popover="hint",interestfor, anchored container queries. Wrap in@supportsor feature-detect in JavaScript; load polyfills when needed; the experience in unsupported browsers must remain usable, just less polished.
const probe = document.createElement('div');
probe.popover = 'hint';
const supports = {
popover: HTMLElement.prototype.hasOwnProperty('popover'),
hint: probe.popover === 'hint',
invokers: 'commandForElement' in HTMLButtonElement.prototype,
interest: 'interestForElement' in HTMLButtonElement.prototype,
closedBy: 'closedBy' in HTMLDialogElement.prototype,
anchor: CSS.supports('anchor-name: --a'),
baseSelect: CSS.supports('appearance', 'base-select'),
};
if (!supports.interest) {
await import('/vendor/interestfor-polyfill.js'); // load only when needed
}
When deciding component by component in your design system, the following decision tree helps avoid both extremes, "a library for everything" and "native at all costs":
flowchart TD Q["Which component are you building?"] --> T["Tooltip, hover card"] Q --> M["Action menu, dropdown"] Q --> D["Confirmation dialog, form"] Q --> S["Pick one value
from a short list"] Q --> C["Combobox with search, async,
multi-select, thousands of items"] T --> T1["popover hint + interestfor
polyfill for Firefox, Safari"] M --> M1["popover auto + commandfor
+ anchor positioning"] D --> D1["dialog + command show-modal
closedby where supported"] S --> S1["select + base-select
wrapped in supports"] C --> C1["Keep a headless library
but built on popover + anchor"] style Q fill:#2c3e50,stroke:#fff,color:#fff style M1 fill:#e94560,stroke:#fff,color:#fff style D1 fill:#e94560,stroke:#fff,color:#fff style S1 fill:#f8f9fa,stroke:#e94560,color:#2c3e50 style T1 fill:#f8f9fa,stroke:#e94560,color:#2c3e50 style C1 fill:#f8f9fa,stroke:#e94560,color:#2c3e50
When should you keep a library?
- Combobox / autocomplete: a text input with suggestions, list filtering and API-loaded data — no native primitive yet.
- Very long lists: picking among thousands of items needs virtualization; customizable select renders every option.
- Complex application menus following the
role="menu"pattern with arrow-key navigation, typeahead and multi-level submenus — at least untilfocusgroupships widely. - Legacy browser requirements: if a significant share of your users are on old, un-updated iOS versions, even tier 1 needs a fallback.
Even when you keep a library, the 2026 trend is for headless libraries to move onto popover and anchor positioning under the hood. When choosing a new library, prefer one that "stands on the shoulders" of native primitives rather than reimplementing the top layer with portals.
11. Measuring the impact of the migration
Moving to native primitives is a UI architecture change, so measure it with data rather than gut feeling:
- JavaScript size: compare the bundle before and after removing positioning, modal, focus-trap and portal libraries.
- p75 INP from real users (RUM): focus on interactions such as opening menus, opening modals and picking values — that's where less JavaScript shows most clearly.
- Time to interactive controls: for server-rendered pages, measure the gap between HTML being visible and the menu button actually responding; with Invoker Commands, that gap approaches zero.
- Accessibility testing: run axe/Lighthouse and, more importantly, test with a real keyboard and screen readers (VoiceOver, NVDA) — focus and ARIA bugs usually drop sharply because the browser handles them.
- Overlay-related UI bugs: z-index issues, clipped menus, misplaced tooltips — track them in your issue tracker for a few sprints after the migration.
Conclusion
For more than a decade, every frontend team had to reinvent tooltips, dropdowns and modals. 2026 is when that stops being the default: the browser now provides the top layer, light dismiss, focus management, anchor-based positioning, declarative button commands and even a styleable select. Key takeaways:
- Popover + Invoker Commands + Anchor Positioning is a Baseline trio that's enough to build high-quality menus, dropdowns and modals with almost no JavaScript.
- Customizable select is in Chrome and Safari 27; adopt it now as progressive enhancement with
@supports, and always keep text in options. - Interest Invokers, closedby and hint popovers are still rolling out — pair them with polyfills or fallbacks, and don't bet critical flows on them.
- Less JavaScript means better UX: buttons work from the first frame, INP improves, and accessibility is consistent across components.
- Libraries don't disappear, but their role changes: they're for comboboxes, large lists and complex menus, and they should be built on the native primitives themselves.
A small exercise for your next sprint: pick one overlay component in your design system — usually the dropdown menu — rebuild it with popover and anchor positioning, then compare bundle size, INP and lines of code. The results are usually convincing enough for the whole team to keep going.
References
- WebKit — WebKit Features for Safari 27.0
- WebKit — The golden rule of Customizable Select
- web.dev — Interop 2026: Continuing to improve the web for developers
- web.dev — New to the web platform in January 2026
- Chrome for Developers — Detect fallback positions with anchored container queries from Chrome 143
- Chrome for Developers — New in Chrome 142
- Chrome for Developers — Request for developer feedback: focusgroup
- MDN — Customizable select elements
- MDN — Invoker Commands API
- MDN — Using interest invokers
- MDN — HTMLDialogElement: closedBy property
- W3C — CSS Anchor Positioning Module Level 1
- InfoQ — HTML Invoker Commands (January 2026)
- Web Platform DX — web-features explorer: Customizable select
- Web Platform DX — web-features explorer: Invoker commands
- State of HTML 2024 — Forms
Disclaimer: The opinions expressed in this blog are solely my own and do not reflect the views or opinions of my employer or any affiliated organizations. The content provided is for informational and educational purposes only and should not be taken as professional advice. While I strive to provide accurate and up-to-date information, I make no warranties or guarantees about the completeness, reliability, or accuracy of the content. Readers are encouraged to verify the information and seek independent advice as needed. I disclaim any liability for decisions or actions taken based on the content of this blog.