πΌοΈ 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.
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.
.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.
/* 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.
.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.
.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; }