21 / 22
All 22 in 22 CSS Image Galleries
- 01CSS Hexagon Honeycomb Gallery
- 02CSS Aspect-Ratio Justified Gallery
- 03CSS Flexbox Expanding Panel Gallery
- 04CSS :has() Hover Spotlight Gallery
- 05CSS Radial Orbit Image Gallery
- 06CSS Interactive Pointer Trail Gallery
- 07CSS Masonry Image Gallery
- 08CSS Metro Tile Grid Gallery
- 09CSS Magazine Layout Gallery
- 10CSS Lightbox Gallery Overlay
- 11CSS Filmstrip Carousel Gallery
- 12CSS Accordion Image Gallery
- 13CSS Mosaic Zoom Gallery
- 14CSS Glassmorphism Hover Cards
- 15CSS Diagonal Slice Reveal Gallery
- 16CSS Tilt Parallax Image Cards
- 17CSS 3D Cube Image Viewer
- 18CSS Perspective Depth Stack Gallery
- 19CSS Infinite Scroll Image Strip
- 20CSS Ken Burns Slideshow Gallery
- 21CSS Polaroid Stack Gallery
- 22CSS Scattered Photos Gallery
CSS Polaroid Stack Gallery
Photos styled as vintage Polaroid snapshots — thick white frame, deep bottom border, handwritten caption — scattered at playful angles and straightening with a lift on hover. The nostalgic photo-stack look boutique and wedding sites search for.
Build interactive UI like this from scratch: 20 HTML, CSS & JavaScript projects
ZTM · JavaScript Web Projects · 30‑day money-back guarantee · Affiliate link
The code
<section class="gl-21" aria-label="Polaroid stack gallery">
<div class="gl-21__pile">
<figure class="gl-21__pola" tabindex="0"><img src="https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?q=80&w=400&h=400&auto=format&fit=crop" alt="Friends on a summer trip" loading="lazy" decoding="async"><figcaption>Summer '24</figcaption></figure>
<figure class="gl-21__pola" tabindex="0"><img src="https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?q=80&w=400&h=400&auto=format&fit=crop" alt="Sunset on the beach" loading="lazy" decoding="async"><figcaption>Last light</figcaption></figure>
<figure class="gl-21__pola" tabindex="0"><img src="https://images.unsplash.com/photo-1499346030926-9a72daac6c63?q=80&w=400&h=400&auto=format&fit=crop" alt="Road trip stop" loading="lazy" decoding="async"><figcaption>Route 1</figcaption></figure>
<figure class="gl-21__pola" tabindex="0"><img src="https://images.unsplash.com/photo-1620121692029-d088224ddc74?q=80&w=400&h=400&auto=format&fit=crop" alt="Picnic in the park" loading="lazy" decoding="async"><figcaption>Sunday</figcaption></figure>
<figure class="gl-21__pola" tabindex="0"><img src="https://images.unsplash.com/photo-1568901346375-23c9450c58cd?q=80&w=400&h=400&auto=format&fit=crop" alt="Mountain hike" loading="lazy" decoding="async"><figcaption>The climb</figcaption></figure>
</div>
</section><section class="gl-21" aria-label="Polaroid stack gallery">
<div class="gl-21__pile">
<figure class="gl-21__pola" tabindex="0"><img src="https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?q=80&w=400&h=400&auto=format&fit=crop" alt="Friends on a summer trip" loading="lazy" decoding="async"><figcaption>Summer '24</figcaption></figure>
<figure class="gl-21__pola" tabindex="0"><img src="https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?q=80&w=400&h=400&auto=format&fit=crop" alt="Sunset on the beach" loading="lazy" decoding="async"><figcaption>Last light</figcaption></figure>
<figure class="gl-21__pola" tabindex="0"><img src="https://images.unsplash.com/photo-1499346030926-9a72daac6c63?q=80&w=400&h=400&auto=format&fit=crop" alt="Road trip stop" loading="lazy" decoding="async"><figcaption>Route 1</figcaption></figure>
<figure class="gl-21__pola" tabindex="0"><img src="https://images.unsplash.com/photo-1620121692029-d088224ddc74?q=80&w=400&h=400&auto=format&fit=crop" alt="Picnic in the park" loading="lazy" decoding="async"><figcaption>Sunday</figcaption></figure>
<figure class="gl-21__pola" tabindex="0"><img src="https://images.unsplash.com/photo-1568901346375-23c9450c58cd?q=80&w=400&h=400&auto=format&fit=crop" alt="Mountain hike" loading="lazy" decoding="async"><figcaption>The climb</figcaption></figure>
</div>
</section>.gl-21,
.gl-21 *,
.gl-21 *::before,
.gl-21 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.gl-21 ::selection {
background: oklch(0.6 0.12 40);
color: #fff;
}
.gl-21 {
--accent: oklch(0.55 0.13 40);
font-family: 'Segoe UI',system-ui,sans-serif;
width: 100%;
min-height: 100vh;
padding: 40px 20px;
background: #d9cfc0;
background-image: radial-gradient(rgba(120,100,80,.12) 1px,transparent 1px);
background-size: 6px 6px;
display: flex;
align-items: center;
justify-content: center;
}
.gl-21__pile {
display: flex;
flex-wrap: wrap;
gap: 6px;
justify-content: center;
align-items: center;
width: min(820px,100%);
}
.gl-21__pola {
background: #fffdf8;
padding: 12px 12px 44px;
border-radius: 2px;
width: 190px;
box-shadow: 0 10px 24px -10px rgba(60,40,20,.5);
transition: transform .35s cubic-bezier(.2,.7,.2,1),box-shadow .35s;
outline: none;
}
.gl-21__pola img {
display: block;
width: 100%;
aspect-ratio: 1/1;
object-fit: cover;
background: #e7e0d4;
filter: sepia(.18) contrast(1.02);
}
.gl-21__pola figcaption {
margin-top: 12px;
text-align: center;
font-family: 'Segoe Script','Bradley Hand',cursive;
font-size: 17px;
color: #5a4a38;
}
.gl-21__pola:nth-child(1) {
transform: rotate(-6deg);
}
.gl-21__pola:nth-child(2) {
transform: rotate(4deg);
}
.gl-21__pola:nth-child(3) {
transform: rotate(-3deg);
}
.gl-21__pola:nth-child(4) {
transform: rotate(5deg);
}
.gl-21__pola:nth-child(5) {
transform: rotate(-5deg);
}
.gl-21__pola:hover,
.gl-21__pola:focus-visible {
transform: rotate(0) scale(1.06);
z-index: 5;
box-shadow: 0 24px 44px -16px rgba(60,40,20,.6);
}
.gl-21__pola:focus-visible {
outline: 3px solid var(--accent);
outline-offset: 4px;
}
@media (prefers-reduced-motion: reduce) {
.gl-21__pola {
transition: none;
}
}.gl-21,
.gl-21 *,
.gl-21 *::before,
.gl-21 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.gl-21 ::selection {
background: oklch(0.6 0.12 40);
color: #fff;
}
.gl-21 {
--accent: oklch(0.55 0.13 40);
font-family: 'Segoe UI',system-ui,sans-serif;
width: 100%;
min-height: 100vh;
padding: 40px 20px;
background: #d9cfc0;
background-image: radial-gradient(rgba(120,100,80,.12) 1px,transparent 1px);
background-size: 6px 6px;
display: flex;
align-items: center;
justify-content: center;
}
.gl-21__pile {
display: flex;
flex-wrap: wrap;
gap: 6px;
justify-content: center;
align-items: center;
width: min(820px,100%);
}
.gl-21__pola {
background: #fffdf8;
padding: 12px 12px 44px;
border-radius: 2px;
width: 190px;
box-shadow: 0 10px 24px -10px rgba(60,40,20,.5);
transition: transform .35s cubic-bezier(.2,.7,.2,1),box-shadow .35s;
outline: none;
}
.gl-21__pola img {
display: block;
width: 100%;
aspect-ratio: 1/1;
object-fit: cover;
background: #e7e0d4;
filter: sepia(.18) contrast(1.02);
}
.gl-21__pola figcaption {
margin-top: 12px;
text-align: center;
font-family: 'Segoe Script','Bradley Hand',cursive;
font-size: 17px;
color: #5a4a38;
}
.gl-21__pola:nth-child(1) {
transform: rotate(-6deg);
}
.gl-21__pola:nth-child(2) {
transform: rotate(4deg);
}
.gl-21__pola:nth-child(3) {
transform: rotate(-3deg);
}
.gl-21__pola:nth-child(4) {
transform: rotate(5deg);
}
.gl-21__pola:nth-child(5) {
transform: rotate(-5deg);
}
.gl-21__pola:hover,
.gl-21__pola:focus-visible {
transform: rotate(0) scale(1.06);
z-index: 5;
box-shadow: 0 24px 44px -16px rgba(60,40,20,.6);
}
.gl-21__pola:focus-visible {
outline: 3px solid var(--accent);
outline-offset: 4px;
}
@media (prefers-reduced-motion: reduce) {
.gl-21__pola {
transition: none;
}
}/* No JavaScript — nth-child rotations scatter the pile; hover straightens and lifts each print. */
/* No JavaScript — nth-child rotations scatter the pile; hover straightens and lifts each print. */Here's a working CSS Image Gallerie from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: CSS Polaroid Stack Gallery
Source: https://codefronts.com/snippets/css-image-gallery/css-polaroid-stack-gallery/
Photos styled as vintage Polaroid snapshots — thick white frame, deep bottom border, handwritten caption — scattered at playful angles and straightening with a lift on hover. The nostalgic photo-stack look boutique and wedding sites search for.
## HTML
```html
<section class="gl-21" aria-label="Polaroid stack gallery">
<div class="gl-21__pile">
<figure class="gl-21__pola" tabindex="0"><img src="https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?q=80&w=400&h=400&auto=format&fit=crop" alt="Friends on a summer trip" loading="lazy" decoding="async"><figcaption>Summer '24</figcaption></figure>
<figure class="gl-21__pola" tabindex="0"><img src="https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?q=80&w=400&h=400&auto=format&fit=crop" alt="Sunset on the beach" loading="lazy" decoding="async"><figcaption>Last light</figcaption></figure>
<figure class="gl-21__pola" tabindex="0"><img src="https://images.unsplash.com/photo-1499346030926-9a72daac6c63?q=80&w=400&h=400&auto=format&fit=crop" alt="Road trip stop" loading="lazy" decoding="async"><figcaption>Route 1</figcaption></figure>
<figure class="gl-21__pola" tabindex="0"><img src="https://images.unsplash.com/photo-1620121692029-d088224ddc74?q=80&w=400&h=400&auto=format&fit=crop" alt="Picnic in the park" loading="lazy" decoding="async"><figcaption>Sunday</figcaption></figure>
<figure class="gl-21__pola" tabindex="0"><img src="https://images.unsplash.com/photo-1568901346375-23c9450c58cd?q=80&w=400&h=400&auto=format&fit=crop" alt="Mountain hike" loading="lazy" decoding="async"><figcaption>The climb</figcaption></figure>
</div>
</section>
```
## CSS
```css
.gl-21,
.gl-21 *,
.gl-21 *::before,
.gl-21 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.gl-21 ::selection {
background: oklch(0.6 0.12 40);
color: #fff;
}
.gl-21 {
--accent: oklch(0.55 0.13 40);
font-family: 'Segoe UI',system-ui,sans-serif;
width: 100%;
min-height: 100vh;
padding: 40px 20px;
background: #d9cfc0;
background-image: radial-gradient(rgba(120,100,80,.12) 1px,transparent 1px);
background-size: 6px 6px;
display: flex;
align-items: center;
justify-content: center;
}
.gl-21__pile {
display: flex;
flex-wrap: wrap;
gap: 6px;
justify-content: center;
align-items: center;
width: min(820px,100%);
}
.gl-21__pola {
background: #fffdf8;
padding: 12px 12px 44px;
border-radius: 2px;
width: 190px;
box-shadow: 0 10px 24px -10px rgba(60,40,20,.5);
transition: transform .35s cubic-bezier(.2,.7,.2,1),box-shadow .35s;
outline: none;
}
.gl-21__pola img {
display: block;
width: 100%;
aspect-ratio: 1/1;
object-fit: cover;
background: #e7e0d4;
filter: sepia(.18) contrast(1.02);
}
.gl-21__pola figcaption {
margin-top: 12px;
text-align: center;
font-family: 'Segoe Script','Bradley Hand',cursive;
font-size: 17px;
color: #5a4a38;
}
.gl-21__pola:nth-child(1) {
transform: rotate(-6deg);
}
.gl-21__pola:nth-child(2) {
transform: rotate(4deg);
}
.gl-21__pola:nth-child(3) {
transform: rotate(-3deg);
}
.gl-21__pola:nth-child(4) {
transform: rotate(5deg);
}
.gl-21__pola:nth-child(5) {
transform: rotate(-5deg);
}
.gl-21__pola:hover,
.gl-21__pola:focus-visible {
transform: rotate(0) scale(1.06);
z-index: 5;
box-shadow: 0 24px 44px -16px rgba(60,40,20,.6);
}
.gl-21__pola:focus-visible {
outline: 3px solid var(--accent);
outline-offset: 4px;
}
@media (prefers-reduced-motion: reduce) {
.gl-21__pola {
transition: none;
}
}
```
## JavaScript
```js
/* No JavaScript — nth-child rotations scatter the pile; hover straightens and lifts each print. */
```Here's a working CSS Image Gallerie from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: CSS Polaroid Stack Gallery
Source: https://codefronts.com/snippets/css-image-gallery/css-polaroid-stack-gallery/
Photos styled as vintage Polaroid snapshots — thick white frame, deep bottom border, handwritten caption — scattered at playful angles and straightening with a lift on hover. The nostalgic photo-stack look boutique and wedding sites search for.
## HTML
```html
<section class="gl-21" aria-label="Polaroid stack gallery">
<div class="gl-21__pile">
<figure class="gl-21__pola" tabindex="0"><img src="https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?q=80&w=400&h=400&auto=format&fit=crop" alt="Friends on a summer trip" loading="lazy" decoding="async"><figcaption>Summer '24</figcaption></figure>
<figure class="gl-21__pola" tabindex="0"><img src="https://images.unsplash.com/photo-1595950653106-6c9ebd614d3a?q=80&w=400&h=400&auto=format&fit=crop" alt="Sunset on the beach" loading="lazy" decoding="async"><figcaption>Last light</figcaption></figure>
<figure class="gl-21__pola" tabindex="0"><img src="https://images.unsplash.com/photo-1499346030926-9a72daac6c63?q=80&w=400&h=400&auto=format&fit=crop" alt="Road trip stop" loading="lazy" decoding="async"><figcaption>Route 1</figcaption></figure>
<figure class="gl-21__pola" tabindex="0"><img src="https://images.unsplash.com/photo-1620121692029-d088224ddc74?q=80&w=400&h=400&auto=format&fit=crop" alt="Picnic in the park" loading="lazy" decoding="async"><figcaption>Sunday</figcaption></figure>
<figure class="gl-21__pola" tabindex="0"><img src="https://images.unsplash.com/photo-1568901346375-23c9450c58cd?q=80&w=400&h=400&auto=format&fit=crop" alt="Mountain hike" loading="lazy" decoding="async"><figcaption>The climb</figcaption></figure>
</div>
</section>
```
## CSS
```css
.gl-21,
.gl-21 *,
.gl-21 *::before,
.gl-21 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.gl-21 ::selection {
background: oklch(0.6 0.12 40);
color: #fff;
}
.gl-21 {
--accent: oklch(0.55 0.13 40);
font-family: 'Segoe UI',system-ui,sans-serif;
width: 100%;
min-height: 100vh;
padding: 40px 20px;
background: #d9cfc0;
background-image: radial-gradient(rgba(120,100,80,.12) 1px,transparent 1px);
background-size: 6px 6px;
display: flex;
align-items: center;
justify-content: center;
}
.gl-21__pile {
display: flex;
flex-wrap: wrap;
gap: 6px;
justify-content: center;
align-items: center;
width: min(820px,100%);
}
.gl-21__pola {
background: #fffdf8;
padding: 12px 12px 44px;
border-radius: 2px;
width: 190px;
box-shadow: 0 10px 24px -10px rgba(60,40,20,.5);
transition: transform .35s cubic-bezier(.2,.7,.2,1),box-shadow .35s;
outline: none;
}
.gl-21__pola img {
display: block;
width: 100%;
aspect-ratio: 1/1;
object-fit: cover;
background: #e7e0d4;
filter: sepia(.18) contrast(1.02);
}
.gl-21__pola figcaption {
margin-top: 12px;
text-align: center;
font-family: 'Segoe Script','Bradley Hand',cursive;
font-size: 17px;
color: #5a4a38;
}
.gl-21__pola:nth-child(1) {
transform: rotate(-6deg);
}
.gl-21__pola:nth-child(2) {
transform: rotate(4deg);
}
.gl-21__pola:nth-child(3) {
transform: rotate(-3deg);
}
.gl-21__pola:nth-child(4) {
transform: rotate(5deg);
}
.gl-21__pola:nth-child(5) {
transform: rotate(-5deg);
}
.gl-21__pola:hover,
.gl-21__pola:focus-visible {
transform: rotate(0) scale(1.06);
z-index: 5;
box-shadow: 0 24px 44px -16px rgba(60,40,20,.6);
}
.gl-21__pola:focus-visible {
outline: 3px solid var(--accent);
outline-offset: 4px;
}
@media (prefers-reduced-motion: reduce) {
.gl-21__pola {
transition: none;
}
}
```
## JavaScript
```js
/* No JavaScript — nth-child rotations scatter the pile; hover straightens and lifts each print. */
```How this works
Each photo is a <figure> with generous padding and an extra-deep bottom padding to mimic the Polaroid's white frame, a soft drop box-shadow for the physical-print feel, and a handwritten-style caption in the bottom band. A per-card transform: rotate() (varied by nth-child) tosses them at casual angles.
On :hover/:focus-within the card rotates back to straight, scales up slightly and rises on z-index, as if picked up off the pile — all via transform, so it's smooth and reversible.
Make it yours
- Change the resting angles in the
nth-childrotations for more or less scatter. - Swap the caption font for a real handwriting webfont.
- Deepen the frame by increasing the figure's bottom padding.
- Overlap the cards with negative margins for a tighter physical stack.
Gotchas — read before shipping
- Lift the hovered card's
z-indexso it rises above its neighbours instead of being clipped by them. - Keep captions real text (not baked into the image) for SEO and screen readers.
- Straighten on
:focus-withintoo so keyboard users get the same pick-up affordance.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 15.4+ | 113+ | 111+ |
Floor set by oklch() as this demo is written. The core technique itself goes back further — Chrome 36+.
transform rotate + box-shadow — universally supported; no modern features required.