A pure CSS photo gallery implementation using images from AWS CloudFront. No JavaScript required!
:target pseudo-classsrcset (browser chooses optimal size):target TrickThe magic is in CSS’s :target pseudo-class:
.modal {
display: none;
}
.modal:target {
display: flex;
}
When you click a photo, the URL gets a hash (#photo-1). The CSS :target selector matches elements with that ID, so the modal appears. Clicking the close button changes the hash to # (empty), which hides the modal.
The gallery uses srcset to provide multiple image sizes:
<img
srcset="small.jpg 600w, large.jpg 3600w"
sizes="(max-width: 768px) 100vw, 33vw"
src="small.jpg">
The browser automatically chooses:
No JavaScript needed - the browser handles it intelligently!
This CSS-only approach has some trade-offs:
See CSS_ONLY_FEASIBILITY.md for a detailed analysis.
To add more photos, follow this pattern:
<a href="#photo-4" class="photo-card">
<img
srcset="small.jpg 600w, large.jpg 3600w"
sizes="(max-width: 768px) 100vw, 33vw"
src="small.jpg"
alt="Description">
<div class="photo-info">
<div class="caption">Your caption here</div>
<div class="date">January 2024</div>
</div>
</a>
<div id="photo-4" class="modal">
<a href="#" class="modal-close">×</a>
<a href="#photo-3" class="modal-nav prev">←</a>
<a href="#photo-5" class="modal-nav next">→</a>
<div class="modal-content">
<img
srcset="small.jpg 600w, large.jpg 3600w"
sizes="(max-width: 768px) 90vw, 800px"
src="large.jpg"
alt="Description"
class="modal-image">
<div class="modal-info">
<div class="modal-caption">Full caption here</div>
<div class="modal-date">January 2024</div>
</div>
</div>
</div>
Currently using test images from AWS CloudFront:
https://photos.alabut.com/shelterisland/tower-vertical-600w.avifhttps://photos.alabut.com/shelterisland/tower-vertical-3600w.avifReplace these with your own image URLs when adding real photos.
:target pseudo-class (widely supported)srcset (widely supported)Note: Keyboard shortcuts (arrow keys, escape) are not available without JavaScript, but standard link navigation works.
If you want to add JavaScript later, you could:
But the CSS-only version works great as-is!