Topic 2.6
Built-in Interactive Elements
In one line
details/summary give you an open-and-close section, dialog gives you a real popup window, and the popover attribute makes menus and tips that appear on top; all with keyboard support and accessibility built in, often with no JavaScript.
Think of it like this
Furniture that comes with its own hinges. A cupboard door (details) opens and closes when you pull the handle. A pop-up shop window (dialog) is a counter that opens in front of everything; while it's open you deal only with it, and you close it when done. A sticky note (popover) you put on top of your work and flick away with a tap anywhere else. You don't build the hinges; they come with the furniture.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Disclosure widget
- A control that shows or hides content when you activate it, like
details. - summary
- The always-visible label of a
detailselement; clicking it opens or closes the rest. - Modal
- A popup that blocks the rest of the page until it's closed.
- Non-modal
- A popup that leaves the rest of the page usable.
- Top layer
- A special layer drawn above the whole page, used by modal dialogs and popovers. No z-index can cover it.
- Inert
- Can't be clicked, focused or read by assistive tech. The page behind a modal dialog is inert.
- Light dismiss
- Closing a popover by clicking outside it or pressing Escape.
- Keyboard focus
- Which element receives keys right now;
Tabmoves it. Focused elements usually show an outline. - ::backdrop
- A CSS pseudo-element: the layer drawn behind a modal dialog or popover, over the rest of the page.
Step by step
01Make an FAQ with details
Each question is a summary; the answer follows it. The browser draws a triangle marker and handles mouse, keyboard and screen readers (announced as a button that is collapsed or expanded).
<details>
<summary>Is Hectal free?</summary>
<p>Yes, every course is free.</p>
</details>
<details open>
<summary>Do I need to install anything?</summary>
<p>No, examples run in your browser.</p>
</details>02Turn it into an accordion
Give the details the same name. Now only one can be open at a time.
<details name="faq" open><summary>Question 1</summary><p>Answer 1</p></details>
<details name="faq"><summary>Question 2</summary><p>Answer 2</p></details>03Open a modal dialog
A modal needs one line of JavaScript: showModal(). Everything else (top layer, backdrop, inert page, Escape, focus moving in) is the browser's work. The form with method="dialog" closes it and reports which button was pressed.
<button id="del">Delete file</button>
<dialog id="ask">
<form method="dialog">
<p>Delete this file?</p>
<button value="cancel">Cancel</button>
<button value="yes">Delete</button>
</form>
</dialog>
<script>
const ask = document.getElementById("ask");
document.getElementById("del").onclick = () => ask.showModal();
ask.onclose = () => console.log(ask.returnValue);
</script>04Make a popover with no JavaScript
Put popover on the element and popovertarget on a button pointing at its id. The button toggles it; clicking anywhere else closes it.
<button popovertarget="menu">Menu</button>
<div id="menu" popover>
<a href="/">Home</a><br>
<a href="/html">HTML course</a>
</div>05Style the open states
CSS can style each state: details[open], dialog::backdrop, [popover]:popover-open, and dialog:modal for a modal dialog. You'll learn these selectors in the CSS course.
details[open] summary { font-weight: bold; }
dialog::backdrop { background: rgb(0 0 0 / 0.5); }
[popover] { border-radius: 8px; }06Choose the right one
Use the decision flow below. If none fits, you may need a custom widget, which is much more work to make accessible.
Try it yourself
- 1
Make the FAQ non-exclusive
In the first example, predict the second console line if you remove both
name="faq"attributes. Run it:After opening the second: true true. Both can be open now. - 2
Try the modal's keyboard behaviour
In the dialog example, click Delete file, then press
Tabseveral times. Focus cycles inside the dialog and never reaches the page behind. PressEscape: the console logsClosed with:followed by the last return value, because Escape doesn't change it. - 3
Make the popover manual
In the popover example, change
popovertopopover="manual". Predict the last console line, then run. Open the menu and click outside: it stays open. Click the button again to close it.
Code & diagrams
Same name, so opening the second closed the first. The toggle event arrives a moment later (it is queued, not fired instantly). Click the summaries yourself too.
Preview
Console
Nothing logged yet.Expected console output
Start: true false
After opening the second: false true
toggle event, second is open: trueThe script opens and closes it once to show the API. Click Delete file to open it yourself: try Escape, Cancel and Delete.
Preview
Console
Nothing logged yet.Expected console output
open: true | modal: true
open after close: false
Closed with: cancelClick the button to open it, then click outside or press Escape to dismiss it (light dismiss).
Preview
Console
Nothing logged yet.Expected console output
Shown at start: false
After showPopover: true
Popover type: autoBreak it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Use show() when you need a modal
In the dialog example, replace dlg.showModal() in the click handler with dlg.show(), then click Delete file and press Escape or Tab.
Break #2
Call showModal on a dialog that is already open
Add the open attribute to the <dialog> in the HTML and keep the dlg.showModal() line in the script.
Myth vs fact
Myth
You need a JavaScript library for accordions, modals and dropdown menus.
Fact
details, dialog and popover cover the common cases natively, including keyboard and screen-reader behaviour.
Myth
Adding the open attribute to a dialog makes it modal.
Fact
The open attribute opens it non-modally. Only showModal() makes it modal with a backdrop, inert page and Escape handling.
Myth
A popover is the same as a modal dialog.
Fact
A popover doesn't make the page inert and is meant to be dismissed lightly. Use a modal dialog when the user must respond.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
The top layer sits outside the normal stacking contexts, so
overflow: hiddenon an ancestor and z-index wars can't clip or cover a modal dialog or popover. This is the main reason to prefer them over absolutely positioneddivs. - ▸
Inside a modal, the browser sets the rest of the document inert. Modal dialogs also get the implicit
aria-modal="true". Initial focus goes to the element withautofocus, or else the first focusable element; for long text, consider focusing the dialog itself. - ▸
Exclusive accordions (
details name) became Baseline in 2024. Newer additions such ashidden="until-found"(content that find-in-page can reveal) and the::details-contentpseudo-element (to style or animate the hidden part) are not in every browser yet; check support before relying on them. - ▸
popoveranddialogcombine with CSS anchor positioning to place menus next to their buttons without JavaScript; anchor positioning is new, so check current support before depending on it. The newer Invoker Commands API (commandforandcommandattributes on buttons) can open dialogs without JavaScript where supported.
Remember this
- 1
**
<details>and<summary>.**detailsis a box that can be open or closed (a disclosure widget). Its first childsummaryis the always-visible label; clicking it, or pressingEnterorSpacewhen it has keyboard focus, toggles the rest. Theopenattribute is present when it's open; write<details open>to start open. The browser fires atoggleevent each time it changes. - 2
Several
detailswith the same **nameattribute form an exclusive accordion**: opening one closes the others, with no JavaScript. Content inside a closeddetailsis still found by the browser's find-in-page (Ctrl+F) in Chromium-based browsers, which opens it automatically. - 3
**
<dialog>** is a popup box. Opened with theopenattribute ordialog.show(), it's non-modal: the rest of the page still works. Opened withdialog.showModal(), it's modal: it appears in the top layer (above everything, whatever the z-index), the page behind becomes inert (can't be clicked or focused), a::backdropcovers the page, keyboard focus moves into the dialog, andEscapecloses it. Close it withdialog.close(value), which setsreturnValueand fires acloseevent. - 4
A
<form method="dialog">inside a dialog closes the dialog when submitted, without sending anything to a server, and setsreturnValueto thevalueof the button that was pressed. That's the simplest way to build "OK / Cancel" confirmations. - 5
**The
popoverattribute** turns any element into a popover: hidden until shown, then displayed in the top layer. A<button popovertarget="id">toggles it with no JavaScript. Withpopover(orpopover="auto") it has light dismiss: clicking outside or pressingEscapecloses it, and opening another auto popover closes the first.popover="manual"stays until you close it. JavaScript can callshowPopover(),hidePopover()andtogglePopover(). - 6
When to use which:
detailsfor show/hide content in the page (FAQs, "more options"). A modaldialogwhen the user must deal with something before continuing (confirm a delete, sign in).popoverfor light, non-blocking layers (menus, tooltips, toasts). Using these instead of hand-madedivpopups gives you correct keyboard handling, focus management and screen-reader roles for free; you'll add behaviour with JavaScript in the JavaScript course (/javascript).
Explain it without notes
What does showModal() give you that show() doesn't?
How does <form method="dialog"> work?
What is light dismiss, and which kind of popover has it?
Why are native details, dialog and popover better than hand-built div widgets?
Practice
Build a two-question FAQ where only one answer can be open at a time and the first is open at the start.
Build a "Subscribe?" modal with Yes/No buttons that logs the choice when it closes. Open it from a button.
Make a button that toggles a small help popover with the text "Passwords need 12 characters".
Trade-offs
- ↔
Native elements bring behaviour you can't fully change (the
detailsmarker, the dialog's focus rules); usually that's a feature, but highly custom designs need more CSS work. - ↔
Modals interrupt the user; use them only when an answer is needed now. A
detailssection or an inline message is often kinder.
Done when you can
I can build a disclosure and an exclusive accordion with
detailsandsummary.I can open a modal with
showModal()and close it withform method="dialog".I can read
returnValuein thecloseevent.I can make a popover with
popoverandpopovertarget, and explain auto vs manual.I can choose between details, dialog and popover for a given need.