Photo Gallery
A grid photo gallery where images have varying aspect ratios. Dense auto-placement fills gaps automatically, creating a compact mosaic. No JavaScript positioning — pure CSS Grid. sdfsdfs
1. Dense Photo Gallery
Each photo has a type: portrait (tall), landscape (wide), featured (large), or standard. Dense packing fills any gaps left by larger photos by backtracking and finding smaller ones that fit.
CSS
.gallery {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 70px; /* base unit */
grid-auto-flow: dense; /* fill gaps! */
gap: 6px;
}
/* Photo types */
.portrait { grid-row: span 2; } /* tall */
.landscape { grid-column: span 2; } /* wide */
.featured {
grid-column: span 2;
grid-row: span 2;
} /* large: 2×2 */
.standard { /* default: 1×1 */ }2. Without Dense vs With Dense
See exactly what dense packing does. Without it, large items create holes that are never filled. With it, smaller items backfill those gaps — creating a tight, compact layout.
CSS
/* Without dense: holes appear */
.gallery-normal {
grid-auto-flow: row; /* default */
}
/* With dense: holes are filled */
.gallery-dense {
grid-auto-flow: dense; /* or: row dense */
}
/* ⚠️ Dense changes visual order!
Later items may appear before earlier items.
OK for visual galleries, bad for ordered content */3. Responsive Column Count
Combine auto-fill with dense to get a gallery that's both responsive (fills available width) and compact (no gaps). The browser picks the column count automatically.
CSS
.gallery {
display: grid;
/* responsive: fills screen with cols */
grid-template-columns:
repeat(auto-fill, minmax(150px, 1fr));
grid-auto-rows: 150px;
grid-auto-flow: dense;
gap: 8px;
}
/* Works at any screen size! */4. Gallery with Hover Captions
Use CSS Grid's position + overlay technique to add captions on hover. The item itself is a grid container, and the caption is placed in the same cell as the image.
CSS
.gallery-item {
display: grid;
grid-template: 1fr / 1fr; /* 1 cell */
}
/* Both image and caption placed in same cell */
.gallery-item > * {
grid-area: 1 / 1; /* all items overlap */
}
.gallery-caption {
opacity: 0;
transition: opacity 0.2s;
background: rgba(0,0,0,0.5);
}
.gallery-item:hover .gallery-caption {
opacity: 1;
}