Image Gallery

Collection of images presented for browsing.

html

<ul class="img-gallery" style="grid-template-columns:repeat(3, 1fr);gap:8px;">
  <li class="img-gallery__item" style="border-radius:8px;">
    <img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Crect width='300' height='300' fill='%23A8E6C1'/%3E%3Ccircle cx='150' cy='150' r='60' fill='%23FAF7F2'/%3E%3C/svg%3E" alt="Gallery photo 1: pale circle on mint" loading="lazy" width="300" height="300" />
    
  </li>
  <li class="img-gallery__item" style="border-radius:8px;">
    <img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Crect width='300' height='300' fill='%23BFD9F2'/%3E%3Ccircle cx='150' cy='150' r='60' fill='%23FAF7F2'/%3E%3C/svg%3E" alt="Gallery photo 2: pale circle on sky blue" loading="lazy" width="300" height="300" />
    
  </li>
  <li class="img-gallery__item" style="border-radius:8px;">
    <img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Crect width='300' height='300' fill='%23F5C2E0'/%3E%3Ccircle cx='150' cy='150' r='60' fill='%23FAF7F2'/%3E%3C/svg%3E" alt="Gallery photo 3: pale circle on blush pink" loading="lazy" width="300" height="300" />
    
  </li>
  <li class="img-gallery__item" style="border-radius:8px;">
    <img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Crect width='300' height='300' fill='%23D9C8F0'/%3E%3Ccircle cx='150' cy='150' r='60' fill='%23FAF7F2'/%3E%3C/svg%3E" alt="Gallery photo 4: pale circle on lavender" loading="lazy" width="300" height="300" />
    
  </li>
  <li class="img-gallery__item" style="border-radius:8px;">
    <img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Crect width='300' height='300' fill='%23E8A020'/%3E%3Ccircle cx='150' cy='150' r='60' fill='%23FAF7F2'/%3E%3C/svg%3E" alt="Gallery photo 5: pale circle on gold" loading="lazy" width="300" height="300" />
    
  </li>
  <li class="img-gallery__item" style="border-radius:8px;">
    <img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Crect width='300' height='300' fill='%23241430'/%3E%3Ccircle cx='150' cy='150' r='60' fill='%23D9C8F0'/%3E%3C/svg%3E" alt="Gallery photo 6: lavender circle on ink" loading="lazy" width="300" height="300" />
    
  </li>
</ul>
<style>
.img-gallery { display: grid; list-style: none; margin: 0; padding: 0; max-width: 400px; }
.img-gallery__item { position: relative; overflow: hidden; background: #FAF7F2; }
.img-gallery__item img { display: block; width: 100%; height: 100%; object-fit: cover; aspect-ratio: 1 / 1; }
.img-gallery__cap { position: absolute; left: 0; right: 0; bottom: 0; padding: 4px 6px; background: #241430cc; color: #FAF7F2; font: 500 10px/1.3 system-ui, sans-serif; }
</style>

tailwind

<ul class="img-gallery-tw grid list-none m-0 p-0 max-w-[400px]" style="grid-template-columns:repeat(3, 1fr);gap:8px;">
  <li class="relative overflow-hidden bg-[#FAF7F2]" style="border-radius:8px;">
    <img class="block w-full h-full object-cover" style="aspect-ratio:1/1;" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Crect width='300' height='300' fill='%23A8E6C1'/%3E%3Ccircle cx='150' cy='150' r='60' fill='%23FAF7F2'/%3E%3C/svg%3E" alt="Gallery photo 1: pale circle on mint" loading="lazy" width="300" height="300" />
    
  </li>
  <li class="relative overflow-hidden bg-[#FAF7F2]" style="border-radius:8px;">
    <img class="block w-full h-full object-cover" style="aspect-ratio:1/1;" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Crect width='300' height='300' fill='%23BFD9F2'/%3E%3Ccircle cx='150' cy='150' r='60' fill='%23FAF7F2'/%3E%3C/svg%3E" alt="Gallery photo 2: pale circle on sky blue" loading="lazy" width="300" height="300" />
    
  </li>
  <li class="relative overflow-hidden bg-[#FAF7F2]" style="border-radius:8px;">
    <img class="block w-full h-full object-cover" style="aspect-ratio:1/1;" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Crect width='300' height='300' fill='%23F5C2E0'/%3E%3Ccircle cx='150' cy='150' r='60' fill='%23FAF7F2'/%3E%3C/svg%3E" alt="Gallery photo 3: pale circle on blush pink" loading="lazy" width="300" height="300" />
    
  </li>
  <li class="relative overflow-hidden bg-[#FAF7F2]" style="border-radius:8px;">
    <img class="block w-full h-full object-cover" style="aspect-ratio:1/1;" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Crect width='300' height='300' fill='%23D9C8F0'/%3E%3Ccircle cx='150' cy='150' r='60' fill='%23FAF7F2'/%3E%3C/svg%3E" alt="Gallery photo 4: pale circle on lavender" loading="lazy" width="300" height="300" />
    
  </li>
  <li class="relative overflow-hidden bg-[#FAF7F2]" style="border-radius:8px;">
    <img class="block w-full h-full object-cover" style="aspect-ratio:1/1;" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Crect width='300' height='300' fill='%23E8A020'/%3E%3Ccircle cx='150' cy='150' r='60' fill='%23FAF7F2'/%3E%3C/svg%3E" alt="Gallery photo 5: pale circle on gold" loading="lazy" width="300" height="300" />
    
  </li>
  <li class="relative overflow-hidden bg-[#FAF7F2]" style="border-radius:8px;">
    <img class="block w-full h-full object-cover" style="aspect-ratio:1/1;" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Crect width='300' height='300' fill='%23241430'/%3E%3Ccircle cx='150' cy='150' r='60' fill='%23D9C8F0'/%3E%3C/svg%3E" alt="Gallery photo 6: lavender circle on ink" loading="lazy" width="300" height="300" />
    
  </li>
</ul>

react

export function ImageGallery({
  columns = 3,
  gap = 8,
  radius = 8,
  captions = false,
}) {
  const photos = [
    { fill: "#A8E6C1", alt: "Gallery photo 1: pale circle on mint", cap: "Meadow, no. 1" },
    { fill: "#BFD9F2", alt: "Gallery photo 2: pale circle on sky blue", cap: "Harbour, no. 2" },
    { fill: "#F5C2E0", alt: "Gallery photo 3: pale circle on blush pink", cap: "Orchard, no. 3" },
    { fill: "#D9C8F0", alt: "Gallery photo 4: pale circle on lavender", cap: "Studio, no. 4" },
    { fill: "#E8A020", alt: "Gallery photo 5: pale circle on gold", cap: "Kiln, no. 5" },
    { fill: "#241430", dot: "#D9C8F0", alt: "Gallery photo 6: lavender circle on ink", cap: "Nightfall, no. 6" },
  ];
  return (
    <ul style={{ display: "grid", listStyle: "none", margin: 0, padding: 0, maxWidth: 400,
      gridTemplateColumns: `repeat(${columns}, 1fr)`, gap }}>
      {photos.map((p) => (
        <li key={p.cap} style={{ position: "relative", overflow: "hidden", background: "#FAF7F2", borderRadius: radius }}>
          <svg viewBox="0 0 300 300" width="100%" height="100%" style={{ display: "block", aspectRatio: "1 / 1" }} role="img" aria-label={p.alt}>
            <rect width="300" height="300" fill={p.fill} />
            <circle cx="150" cy="150" r="60" fill={p.dot ?? "#FAF7F2"} />
          </svg>
          {captions && (
            <span style={{ position: "absolute", left: 0, right: 0, bottom: 0, padding: "4px 6px",
              background: "#241430cc", color: "#FAF7F2", font: "500 10px/1.3 system-ui, sans-serif" }}>
              {p.cap}
            </span>
          )}
        </li>
      ))}
    </ul>
  );
}