summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-11-12 10:31:07 +0100
committerDanilo M. <danix@danix.xyz>2026-11-12 10:31:07 +0100
commit73478fbb995181c0fc15090d9abeabf7d4373f1c (patch)
tree92241fe02eeeb1b7abc20aac347b73e4e96a22f6
parent2066c9933766f5176a79ecf4ce5acc3a5fd339f1 (diff)
downloaddanixxyz-theme-73478fbb995181c0fc15090d9abeabf7d4373f1c.tar.gz
danixxyz-theme-73478fbb995181c0fc15090d9abeabf7d4373f1c.zip
feat: enlarge article images on clickHEADmaster
A shared native <dialog> shows the clicked image at up to 95% of the viewport. Esc or a click closes it and focus returns to the image. Images are keyboard-reachable (Enter/Space). Linked images are skipped. Loaded on single pages only, styled inline so no CSS rebuild is needed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
-rw-r--r--assets/js/image-zoom.js43
-rw-r--r--layouts/_default/baseof.html2
2 files changed, 45 insertions, 0 deletions
diff --git a/assets/js/image-zoom.js b/assets/js/image-zoom.js
new file mode 100644
index 0000000..307c858
--- /dev/null
+++ b/assets/js/image-zoom.js
@@ -0,0 +1,43 @@
+// Click (or Enter/Space) on an article image to see it full screen.
+// One native <dialog> is shared by all images: Esc closes it natively,
+// a click anywhere closes it too, and focus returns to the image.
+(function () {
+ var imgs = Array.prototype.filter.call(
+ document.querySelectorAll('.prose img'),
+ function (img) { return !img.closest('a'); }
+ );
+ if (!imgs.length) return;
+
+ var dlg = document.createElement('dialog');
+ dlg.setAttribute('aria-label', 'Enlarged image');
+ dlg.style.cssText = 'padding:0;border:0;background:transparent;max-width:95vw;max-height:95vh;overflow:visible;cursor:zoom-out';
+ var big = document.createElement('img');
+ big.style.cssText = 'display:block;max-width:95vw;max-height:95vh;width:auto;height:auto;object-fit:contain;border-radius:0.5rem';
+ dlg.appendChild(big);
+ document.body.appendChild(dlg);
+
+ var style = document.createElement('style');
+ style.textContent = 'dialog[aria-label="Enlarged image"]::backdrop{background:rgba(0,0,0,0.85)}';
+ document.head.appendChild(style);
+
+ var opener = null;
+ dlg.addEventListener('click', function () { dlg.close(); });
+ dlg.addEventListener('close', function () { if (opener) opener.focus(); });
+
+ function open(img) {
+ opener = img;
+ big.src = img.currentSrc || img.src;
+ big.alt = img.alt;
+ dlg.showModal();
+ }
+
+ imgs.forEach(function (img) {
+ img.style.cursor = 'zoom-in';
+ img.tabIndex = 0;
+ img.setAttribute('role', 'button');
+ img.addEventListener('click', function () { open(img); });
+ img.addEventListener('keydown', function (e) {
+ if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); open(img); }
+ });
+ });
+})();
diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html
index 50bdf39..7aa13cc 100644
--- a/layouts/_default/baseof.html
+++ b/layouts/_default/baseof.html
@@ -111,6 +111,8 @@
{{ if eq .Kind "page" }}
{{ $codeScript := resources.Get "js/code-copy.js" | minify }}
<script src="{{ $codeScript.RelPermalink }}"></script>
+ {{ $zoomScript := resources.Get "js/image-zoom.js" | minify }}
+ <script src="{{ $zoomScript.RelPermalink }}"></script>
{{ end }}
<!-- Twemoji: consistent cross-platform emoji rendering on article pages -->