From d02d8edfe9384b3fe1f08a9fc3c024e8a29dec92 Mon Sep 17 00:00:00 2001 From: Kristian Wind Date: Wed, 19 Aug 2026 11:14:13 +0200 Subject: [PATCH] =?UTF-8?q?feat(site):=20klik=20et=20sk=C3=A6rmbillede=20o?= =?UTF-8?q?g=20se=20det=20i=20l=C3=A6sbar=20st=C3=B8rrelse?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Et skærmbillede af en brugerflade siger ingenting ved 281 pixels, og det er der, de fleste af dem sidder i gitteret. Et klik åbner nu det samme billede omkring tre en halv gang større. frem for et selvbygget lag: Escape lukker, fokus bliver inde i den, resten af siden bliver inert — tre ting browseren gør gratis og som et selvbygget overlay skal have kode for hver af. Billedet får rolle og tabindex, så det også kan åbnes fra tastaturet; en kontrol, kun en mus kan nå, er ikke en kontrol alle har. To ting rettet undervejs, som først kunne ses ved at kigge: billedet fik lov at blive højere end skærmen, så billedtekst og lukkeknap røg op over kanten — og lukkeknappen er den synlige vej ud. Og dialogen fyldte hele bredden i stedet for at slutte om billedet, så skærmbilledet stod op ad venstre kant med knappen ude i det modsatte hjørne. Nu er den fit-content og centreret, og alt er inden for vinduet ned til en telefonbredde. Co-Authored-By: Claude Opus 5 --- site/index.html | 136 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) diff --git a/site/index.html b/site/index.html index 74ee4c0..f8abe34 100644 --- a/site/index.html +++ b/site/index.html @@ -344,6 +344,89 @@ text-align: center; } + /* --- zoom ------------------------------------------------------------- + + A screenshot of an interface is unreadable at 280px in a three-column + grid, which is where most of them sit. Clicking one opens it at the + size it was taken. + + rather than a hand-built overlay: Escape closes it, focus is + trapped, the rest of the page is inert, and the browser does all three + without a line of script. */ + .shot img { + cursor: zoom-in; + } + + /* Sized so the whole thing fits: a screenshot is 1.55 times wider than it + is tall, so on a laptop the height is what runs out first. Left to grow, + it pushed the caption and the close button off the top of the screen — + and the button is the visible way out. */ + dialog.zoom { + max-width: 96vw; + max-height: 100vh; + /* Wraps the image rather than the viewport. With a plain `auto` the box + stayed full width, so the screenshot sat against the left edge and + the close button ended up in the far corner, nowhere near it. */ + width: fit-content; + margin: auto; + padding: 2.5rem 0 0; + border: 0; + background: transparent; + overflow: visible; + } + + dialog.zoom::backdrop { + background: rgb(0 0 0 / 0.82); + } + + dialog.zoom img { + max-width: 96vw; + max-height: 78vh; + width: auto; + height: auto; + display: block; + border-radius: var(--radius-lg); + cursor: zoom-out; + } + + dialog.zoom figcaption { + margin-top: 0.75rem; + font-size: 0.8125rem; + color: #a8b0ac; + text-align: center; + } + + /* The whole backdrop closes, so the button is a visible affordance rather + than the only way out. */ + dialog.zoom .close { + position: absolute; + top: 0; + right: 0; + background: none; + border: 0; + color: #a8b0ac; + font-size: 1.5rem; + line-height: 1; + cursor: pointer; + padding: 0.25rem 0.5rem; + } + + dialog.zoom .close:hover { + color: #fff; + } + + @media (prefers-reduced-motion: no-preference) { + dialog.zoom[open] { + animation: zoom-in 0.15s ease-out; + } + @keyframes zoom-in { + from { + opacity: 0; + transform: scale(0.98); + } + } + } + .shots { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); @@ -636,5 +719,58 @@

+ + + + + +
+
+ +