Click anywhere in this card and start typing
This is a real editing surface. Select text. Hit Cmd/Ctrl+Z. Misspell somethng and watch the squiggle appear. Paste rich text from another app.
Everything on this page — the modal dialogs, the popover menus, the accordion, the pickers, the editor, the drag — is plain HTML doing its job. Open view-source and count the script tags.
0 lines of JavaScript on this entire page
For twenty years "open a modal" meant a library. Today a button can
command a <dialog> to open — focus is trapped, the page behind is inert,
Esc closes it, and the backdrop is a styleable pseudo-element. The browser does all of it.
<button commandfor="greeting" command="show-modal">Open a real modal</button> <dialog id="greeting"> ... <button commandfor="greeting" command="close">Close</button> </dialog>
Invoker commands (command/commandfor) are the newest thing
on this page — shipping in current Chrome, Edge, and Firefox. In older browsers this exact pattern is
a three-line script; the <dialog> element itself has been everywhere since 2022.
The popover attribute promotes any element to the top layer:
light-dismiss (click outside or press Esc), one-at-a-time management, no z-index wars.
popovertarget wires the button declaratively.
<button popovertarget="tip">What's a popover?</button> <div id="tip" popover>Light-dismiss, top layer, Esc — all free.</div>
<details name>Give several <details> elements the same name and the browser
enforces "only one open at a time" — the classic accordion widget, as one attribute. Searchable,
keyboard-accessible, and it even auto-opens when find-in-page matches hidden text.
name attribute makes the group exclusive. Opening one closes the others.::marker, ::details-content, and CSS transitions.
That's the CSS wing's department.<details name="faq" open> <summary>...</summary> ... </details> <details name="faq"> <summary>...</summary> ... </details> <details name="faq"> <summary>...</summary> ... </details>
Every control below is one element. Each ships with a mobile-optimized UI, keyboard support, and assistive-technology wiring that a div-based rebuild has to earn back line by line.
Try submitting empty, then fix the fields and watch the borders change.
required, type="email", minlength, and pattern
block the submission and explain why in the user's own language. The green/red styling is the CSS
:user-valid / :user-invalid pseudo-classes — which only kick in after you interact,
so the form doesn't scold you on arrival.
Remember Module 06: this is UX, not security — the server still re-checks everything.
contenteditable turns any element into an editor — caret, selection,
undo history, spellcheck, IME support, the lot. Every "rich text editor" you've used sits on top of this.
This is a real editing surface. Select text. Hit Cmd/Ctrl+Z. Misspell somethng and watch the squiggle appear. Paste rich text from another app.
Add draggable="true" and the browser gives you the pickup: the drag ghost,
the cursor, the OS-level drag session. Try dragging these cards around — even into another app's window.
Honesty box: making something catch the drop is JavaScript's half of the deal.
HTML serves; JS returns.
Play/pause, scrubbing, volume, fullscreen, AirPlay/cast buttons, keyboard control,
picture-in-picture — controls brings the whole player. The audio below isn't even a file
on disk: it's a WAV baked into the page as a data: URI (Module 05 says hello).
Audio — a chime embedded directly in this HTML file:
Video — with a poster frame and captions, streamed from MDN's CC0 samples (needs the network):
<audio controls src="data:audio/wav;base64,UklGRu…"></audio> <video controls src="flower.mp4"></video>
One-liners that surprise people, live in the second column:
| Markup | Live |
|---|---|
<a href="…" download> |
Download a file (generated from a data: URI) |
<a href="mailto:…?subject=…"> |
Email with a pre-filled subject |
<ruby> |
漢字 — pronunciation guides, natively typeset |
dir="auto" |
مرحبا — this span detected its own text direction |
<input type="search"> |
|
<img loading="lazy"> |
Below-the-fold images that don't download until needed — an attribute, not an intersection-observer library |
<abbr title> / <kbd> |
Hover WYSIWYG, press Ctrl+K |