Image Gallery
An image gallery is an important component for displaying a collection of photos or images. CSS offers several approaches: CSS Grid for precise layouts, Flexbox for more flexible layouts, and a combination of both for responsive galleries.
Hover effects such as zoom, info overlays, or a lightbox concept increase interactivity. A responsive gallery must adapt to the screen size, showing fewer columns on mobile and more on desktop.
A gallery can also function as a portfolio grid with a consistent aspect ratio, or as a thumbnail strip for image navigation.
Code Example
<!DOCTYPE html>
<html lang="en">
<head>
<style>
body {
font-family: 'Segoe UI', Arial, sans-serif;
padding: 30px 20px;
background: #f0f2f5;
color: #333;
}
.demo-section {
max-width: 900px;
margin: 0 auto 40px;
background: white;
padding: 30px;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
}
.demo-section h3 {
margin-top: 0;
color: #333;
}
/* Grid Gallery */
.grid-gallery {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 15px;
}
.grid-gallery .gallery-item {
position: relative;
border-radius: 10px;
overflow: hidden;
aspect-ratio: 1;
cursor: pointer;
}
.grid-gallery .gallery-item img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s;
}
.grid-gallery .gallery-item:hover img {
transform: scale(1.1);
}
.grid-gallery .gallery-item .overlay {
position: absolute;
inset: 0;
background: rgba(0, 0, 0, 0.6);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s;
}
.grid-gallery .gallery-item:hover .overlay {
opacity: 1;
}
.overlay .overlay-text {
color: white;
font-weight: 600;
font-size: 1.1em;
}
/* Flexbox Gallery */
.flex-gallery {
display: flex;
flex-wrap: wrap;
gap: 15px;
justify-content: center;
}
.flex-gallery .gallery-item {
flex: 0 0 calc(25% - 12px);
aspect-ratio: 1;
border-radius: 10px;
overflow: hidden;
position: relative;
}
.flex-gallery .gallery-item img {
width: 100%;
height: 100%;
object-fit: cover;
transition: filter 0.3s;
}
.flex-gallery .gallery-item:hover img {
filter: brightness(0.7);
}
.flex-gallery .gallery-item .caption {
position: absolute;
bottom: 0;
left: 0;
right: 0;
padding: 12px;
background: linear-gradient(transparent, rgba(0,0,0,0.8));
color: white;
font-size: 0.85em;
transform: translateY(100%);
transition: transform 0.3s;
}
.flex-gallery .gallery-item:hover .caption {
transform: translateY(0);
}
/* Masonry-like Gallery */
.masonry-gallery {
columns: 3;
column-gap: 15px;
}
.masonry-gallery .gallery-item {
break-inside: avoid;
margin-bottom: 15px;
border-radius: 10px;
overflow: hidden;
position: relative;
}
.masonry-gallery .gallery-item img {
width: 100%;
display: block;
transition: transform 0.3s;
}
.masonry-gallery .gallery-item:hover img {
transform: scale(1.05);
}
/* Lightbox Concept */
.lightbox-gallery {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 10px;
}
.lightbox-gallery .gallery-item {
aspect-ratio: 1;
border-radius: 8px;
overflow: hidden;
cursor: pointer;
position: relative;
}
.lightbox-gallery .gallery-item img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s;
}
.lightbox-gallery .gallery-item:hover img {
transform: scale(1.08);
}
.lightbox-gallery .gallery-item .zoom-icon {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0);
width: 50px;
height: 50px;
background: rgba(255,255,255,0.9);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5em;
transition: transform 0.3s;
}
.lightbox-gallery .gallery-item:hover .zoom-icon {
transform: translate(-50%, -50%) scale(1);
}
/* Thumbnail Strip */
.thumbnail-strip {
display: flex;
gap: 10px;
overflow-x: auto;
padding: 10px 0;
scroll-snap-type: x mandatory;
}
.thumbnail-strip::-webkit-scrollbar {
height: 4px;
}
.thumbnail-strip::-webkit-scrollbar-thumb {
background: #ccc;
border-radius: 2px;
}
.thumbnail-strip .thumb {
flex: 0 0 80px;
height: 80px;
border-radius: 8px;
overflow: hidden;
cursor: pointer;
scroll-snap-align: start;
border: 3px solid transparent;
transition: border-color 0.2s;
}
.thumbnail-strip .thumb.active,
.thumbnail-strip .thumb:hover {
border-color: #667eea;
}
.thumbnail-strip .thumb img {
width: 100%;
height: 100%;
object-fit: cover;
}
.main-image {
width: 100%;
height: 350px;
border-radius: 10px;
overflow: hidden;
margin-bottom: 15px;
}
.main-image img {
width: 100%;
height: 100%;
object-fit: cover;
}
</style>
</head>
<body>
<div class="demo-section">
<h3>CSS Grid Gallery</h3>
<div class="grid-gallery">
<div class="gallery-item">
<img src="https://picsum.photos/400/400?random=20" alt="Image 1">
<div class="overlay">
<span class="overlay-text">View</span>
</div>
</div>
<div class="gallery-item">
<img src="https://picsum.photos/400/400?random=21" alt="Image 2">
<div class="overlay">
<span class="overlay-text">View</span>
</div>
</div>
<div class="gallery-item">
<img src="https://picsum.photos/400/400?random=22" alt="Image 3">
<div class="overlay">
<span class="overlay-text">View</span>
</div>
</div>
<div class="gallery-item">
<img src="https://picsum.photos/400/400?random=23" alt="Image 4">
<div class="overlay">
<span class="overlay-text">View</span>
</div>
</div>
<div class="gallery-item">
<img src="https://picsum.photos/400/400?random=24" alt="Image 5">
<div class="overlay">
<span class="overlay-text">View</span>
</div>
</div>
<div class="gallery-item">
<img src="https://picsum.photos/400/400?random=25" alt="Image 6">
<div class="overlay">
<span class="overlay-text">View</span>
</div>
</div>
</div>
</div>
<div class="demo-section">
<h3>Lightbox Concept</h3>
<div class="lightbox-gallery">
<div class="gallery-item">
<img src="https://picsum.photos/300/300?random=30" alt="Image 1">
<div class="zoom-icon">🔍</div>
</div>
<div class="gallery-item">
<img src="https://picsum.photos/300/300?random=31" alt="Image 2">
<div class="zoom-icon">🔍</div>
</div>
<div class="gallery-item">
<img src="https://picsum.photos/300/300?random=32" alt="Image 3">
<div class="zoom-icon">🔍</div>
</div>
<div class="gallery-item">
<img src="https://picsum.photos/300/300?random=33" alt="Image 4">
<div class="zoom-icon">🔍</div>
</div>
<div class="gallery-item">
<img src="https://picsum.photos/300/300?random=34" alt="Image 5">
<div class="zoom-icon">🔍</div>
</div>
<div class="gallery-item">
<img src="https://picsum.photos/300/300?random=35" alt="Image 6">
<div class="zoom-icon">🔍</div>
</div>
<div class="gallery-item">
<img src="https://picsum.photos/300/300?random=36" alt="Image 7">
<div class="zoom-icon">🔍</div>
</div>
<div class="gallery-item">
<img src="https://picsum.photos/300/300?random=37" alt="Image 8">
<div class="zoom-icon">🔍</div>
</div>
</div>
</div>
<div class="demo-section">
<h3>Thumbnail Strip</h3>
<div class="main-image">
<img src="https://picsum.photos/900/400?random=40" alt="Main image">
</div>
<div class="thumbnail-strip">
<div class="thumb active"><img src="https://picsum.photos/160/160?random=41" alt="Thumb 1"></div>
<div class="thumb"><img src="https://picsum.photos/160/160?random=42" alt="Thumb 2"></div>
<div class="thumb"><img src="https://picsum.photos/160/160?random=43" alt="Thumb 3"></div>
<div class="thumb"><img src="https://picsum.photos/160/160?random=44" alt="Thumb 4"></div>
<div class="thumb"><img src="https://picsum.photos/160/160?random=45" alt="Thumb 5"></div>
<div class="thumb"><img src="https://picsum.photos/160/160?random=46" alt="Thumb 6"></div>
<div class="thumb"><img src="https://picsum.photos/160/160?random=47" alt="Thumb 7"></div>
<div class="thumb"><img src="https://picsum.photos/160/160?random=48" alt="Thumb 8"></div>
</div>
</div>
</body>
</html>
Code Explanation
Grid gallery: Uses grid-template-columns: repeat(3, 1fr) for 3 equal-width columns. aspect-ratio: 1 ensures every item is square. The hover effect reveals an overlay with text.
Flexbox gallery: Flex items with flex: 0 0 calc(25% - 12px) for 4 columns. flex-wrap: wrap allows items to wrap to the next row. The caption slides up on hover.
Masonry-like: Uses columns: 3 with break-inside: avoid to prevent items from being cut. Images with different heights create a masonry layout.
Lightbox concept: A grid with a zoom icon that appears on hover. The icon scales from the center (scale 0 to scale 1), providing interactive feedback.
Thumbnail strip: Horizontal scrolling with scroll-snap-type: x mandatory for snapping behavior. The border changes color when active/hover.
object-fit: cover: Ensures the image fills the area without distortion, cropping the excess.
Everyday Use Cases
Portfolio website: A grid gallery with an info overlay to display design or photography work.
E-commerce: A thumbnail strip for a product gallery where the main image changes when a thumbnail is clicked.
Blog post: A gallery of images inside an article with a lightbox to view the full-size version.
Social media: A masonry gallery for a photo feed with varying image heights.
Conclusion
An image gallery can be built with CSS Grid (precise), Flexbox (flexible), or Columns (masonry). Hover effects increase interactivity. Responsive design ensures the gallery displays optimally on all screen sizes. For lightbox functionality, you need JavaScript or a library, but CSS handles the grid and hover effects well.