Skip to content

Commit 1cb23fd

Browse files
feat: Add click-to-zoom lightbox for blog post images (#6575)
Clicking any image in a blog post now opens a fullscreen overlay with the image centered on a dark backdrop. Close with click or Escape. Signed-off-by: Francisco Javier Arceo <[email protected]> Co-authored-by: Claude Opus 4.6 <[email protected]>
1 parent 506d919 commit 1cb23fd

1 file changed

Lines changed: 65 additions & 1 deletion

File tree

‎infra/website/src/pages/blog/[slug].astro‎

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ const socialImage = heroImage ? toAbsoluteUrl(heroImage) : undefined;
223223
height: auto;
224224
border-radius: 4px;
225225
margin: 32px 0;
226+
cursor: zoom-in;
226227
}
227228

228229
/* Hero Image */
@@ -339,4 +340,67 @@ const socialImage = heroImage ? toAbsoluteUrl(heroImage) : undefined;
339340
font-size: 18px;
340341
}
341342
}
342-
</style>
343+
</style>
344+
345+
<script>
346+
const overlay = document.createElement('div');
347+
overlay.className = 'lightbox-overlay';
348+
const img = document.createElement('img');
349+
overlay.appendChild(img);
350+
document.body.appendChild(overlay);
351+
352+
function open(src: string, alt: string) {
353+
img.src = src;
354+
img.alt = alt;
355+
overlay.classList.add('active');
356+
document.body.style.overflow = 'hidden';
357+
}
358+
359+
function close() {
360+
overlay.classList.remove('active');
361+
document.body.style.overflow = '';
362+
}
363+
364+
overlay.addEventListener('click', close);
365+
366+
document.addEventListener('keydown', (e) => {
367+
if (e.key === 'Escape') close();
368+
});
369+
370+
document.querySelectorAll('.blog-content img').forEach((el) => {
371+
el.addEventListener('click', () => {
372+
const image = el as HTMLImageElement;
373+
open(image.src, image.alt);
374+
});
375+
});
376+
</script>
377+
378+
<style is:global>
379+
.lightbox-overlay {
380+
position: fixed;
381+
inset: 0;
382+
z-index: 9999;
383+
background: rgba(0, 0, 0, 0.85);
384+
display: flex;
385+
align-items: center;
386+
justify-content: center;
387+
cursor: zoom-out;
388+
opacity: 0;
389+
visibility: hidden;
390+
transition: opacity 0.2s ease, visibility 0.2s ease;
391+
}
392+
393+
.lightbox-overlay.active {
394+
opacity: 1;
395+
visibility: visible;
396+
}
397+
398+
.lightbox-overlay img {
399+
max-width: 90vw;
400+
max-height: 90vh;
401+
object-fit: contain;
402+
border-radius: 4px;
403+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
404+
}
405+
</style>
406+

0 commit comments

Comments
 (0)