COMPONENT
Chrome
An application window around a screenshot. A bare screenshot floating on a page reads as a picture of a page; put a titlebar on it and the same image reads as software running on somebody's machine. That is the whole component, and it costs one wrapper.
A window around anything
The bar and the frame are all this owns. What goes underneath is your slot β an image, a frame, a clip, a live demo. There is deliberately no media box of its own, because that would be a third spelling of one.
<div class="chrome">
<div class="chrome-bar">
<span class="chrome-lights"></span>
<span class="chrome-title">Cloud9 Β· 16x16, 4 layers</span>
</div>
<div class="placeholder" style="--ratio: 16/9">
<span class="placeholder-caption">THE APPLICATION, RUNNING</span>
</div>
</div>Everything it can hold
Two more strips, and both are optional. chrome-meta sits at the far end of the bar and carries figures β a canvas size, a layer count. chrome-foot is a strip of its own under the body and carries a sentence, in the body face, with one live mark in front of it.
Everything open at once: canvas, model, outliner, palette and vector pane.
<div class="chrome">
<div class="chrome-bar">
<span class="chrome-lights"></span>
<span class="chrome-title">Cloud9.flatty</span>
<span class="chrome-meta">16 x 16 Β· 4 LAYERS Β· 892 TRIS</span>
</div>
<div class="placeholder" style="--ratio: 16/9">
<span class="placeholder-caption">THE APPLICATION, RUNNING</span>
</div>
<p class="chrome-foot">Everything open at once: canvas, model, outliner, palette and vector pane.</p>
</div>Running off the foot of the band
chrome-sill drops the bottom edge and squares the bottom two corners, for a window that continues past the end of its section instead of sitting inside it. A border under a screenshot that carries on is a line drawn across nothing.
<div class="chrome chrome-sill">
<div class="chrome-bar">
<span class="chrome-lights"></span>
<span class="chrome-title">Runs off the foot of the band</span>
</div>
<div class="placeholder" style="--ratio: 21/9">
<span class="placeholder-caption">NO BOTTOM EDGE, SQUARE BOTTOM CORNERS</span>
</div>
</div>When the body is also a control
`chrome-open` makes the slot a button, for a window whose screenshot opens at full size. It wraps the picture rather than covering it β a window is three strips and only the middle one is the target, so there is nothing for an overlay to cover. Which also means nothing interactive may go inside it.
Press the picture, or tab to it. Escape closes what opens, and so does the space beside it.
<!-- The body is the control, so the button IS the slot. There is no script in
this: `command` opens the dialog, `method="dialog"` closes it from the
veil, and the platform brings Escape, the focus trap and the focus return. -->
<div class="chrome">
<div class="chrome-bar">
<span class="chrome-lights"></span>
<span class="chrome-title">causeway.tif</span>
<span class="chrome-meta">4096 x 2731 Β· RGB</span>
</div>
<button class="chrome-open" command="show-modal" commandfor="chrome-shot"
aria-label="Open the capture at full size">
<img src="/scenery/causeway.webp" alt="" loading="lazy" decoding="async" />
</button>
<p class="chrome-foot">Press the picture, or tab to it. Escape closes what opens, and so does the space beside it.</p>
</div>
<dialog class="modal modal-bare modal-full" id="chrome-shot">
<div class="modal-box">
<div class="modal-head">
<button class="modal-close" command="close" commandfor="chrome-shot" aria-label="Close"></button>
</div>
<div class="modal-body modal-media">
<img src="/scenery/causeway.webp" alt="A stone causeway running out into flat water" loading="lazy" />
</div>
</div>
<form method="dialog" class="modal-veil"><button aria-label="Close"></button></form>
</dialog>Reference
Read from components/chrome.css when this page was built, so it cannot fall behind the stylesheet.
.chrome.chrome-sill.chrome-bar.chrome-lights.chrome-title.chrome-meta.chrome-open.chrome-foot--ds-accent--ds-chrome-dot--ds-dot--ds-focus-ring-inset--ds-focus-width--ds-font-body--ds-font-display--ds-gap--ds-gap-tight--ds-hairline--ds-ink-faint--ds-ink-soft--ds-motion-fast--ds-pad-chrome--ds-pad-row--ds-radius--ds-radius-round--ds-raised--ds-rule--ds-rule-strong--ds-sunk--ds-text-caption--ds-text-meta--ds-track-noteNotes
Two shapes for one promise, and the situation picks which. frame is one box, so an anchor laid over it covers exactly the right area and the picture underneath is untouched. A window is three β a bar, a body and a foot β and only the middle one is the target. There is no element marking out "the body" for an overlay to cover, so it would have to be inset: 0 and would swallow the titlebar. The body is the slot, so the control is the slot.
Which means nothing interactive may go inside it β a button inside a button is not markup HTML has. That is the exact constraint frame-link was shaped to dodge, and it applies here in full: a window whose body is a clip that needs a pause wants the pause outside the window, or no chrome-open at all.
The hover ring is inset by one hairline, which is the one line here that is not cosmetic. The button's own top and bottom edges land exactly on the bar's bottom rule and the foot's top rule, so a ring at inset: 0 puts an accent hairline against a --ds-rule hairline and hover draws the two-pixel line this design never has. One hairline in lays it over the picture instead, where it has nothing to double up with.
Three empty spans is three pieces of markup that mean nothing, sitting in a bar a screen reader already steps over. One box painted with a repeating gradient draws the same three circles. The tile is one dot plus one gap wide with the circle pinned at its left edge β centre it in the tile instead and the third one sits half outside the box, because three tiles are a whole gap wider than three dots and two gaps.
One role, one colour, and no red-amber-green. A window wearing another platform's close, minimise and zoom is a window whose buttons somebody will try to press, and not one of the three does anything. Keeping them a single grey says "this is a picture of an application" without promising a control that is not there.
--ds-sunk on the bar and on the foot, --ds-raised between them, which is the one place in this library where a strip sits deeper than the thing it is attached to. A titlebar belongs behind its content. Lift it above and the window turns inside out β and the picture stops being a picture held between two rails and becomes three stacked panels.
That is why one is set in the display face and the other is not. A name, a count and a size are things you look for; a sentence about what you are looking at is a thing you read. A caption set in a tracked meta face is a caption pretending to be a label, so the foot takes the body face and a row's padding, where the bar takes a titlebar's.
The lights are one grey on purpose, because nothing up there may look pressable. So nothing in the bar can carry the accent. The foot's mark can, and it is a pseudo-element for the same reason the lights are one box: an empty span before the words is markup that means nothing, sitting in a strip a screen reader is already reading as one sentence.