This series has been about building fancy image galleries with minimal HTML. The markup for every example is just a wrapper div containing a handful of <img> tags. All the layout heavy lifting comes from CSS Grid's auto-placement and implicit grid features, combined with clipping.

For the die cut gallery, we start with a square grid of three equal columns and let the images fall into place, with the second and third explicitly overlaid:

grid: auto-flow 1fr / repeat(3, 1fr);

That shorthand is equivalent to spelling out every grid property:

grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 1fr;
DevTools style rules for the grid property.
You can also use your favorite DevTools for further proof.

The same shortcut applies to the explicit placement. Opening DevTools on grid-area: 1/2/span 2/span 2; shows what the browser resolves it to:

grid-area: 1 / 2 / span 2 / span 2;

Which is the same as:

grid-row-start: 1; /* 1st row */
grid-column-start: 2; /* 2nd column */
grid-row-end: span 2; /* take 2 rows */
grid-column-end: span 2; /* take 2 columns */

The second and third images are intentionally overlapped in the middle. We then cut a corner out of each one with clip-path, producing the final die cut shape:

Showing the effect with and without clip-path.

The bottom-left corner of the second image gets clipped:

clip-path: polygon(0 0, 100% 0, 100% 100%, calc(50% + var(--g) / 4) 100%, 0 calc(50% - var(--g) / 4))

And the top-right corner of the third image:

clip-path: polygon(0 0, calc(50% - var(--g) / 4) 0, 100% calc(50% + var(--g) / 4), 100% 100%, 0 100%);

That gives us the finished grid, with a grayscale filter added for a hover effect.

The Split Image Reveal

We can combine corner clipping with hover transitions to reveal a full image. The markup uses just two overlapping images of the same size, stacked via grid-area: 1 / 1.

.gallery {
  display: grid;
}
.gallery > img {
  grid-area: 1 / 1;
  width: 350px; /* the size */
  aspect-ratio: 1; /* equal height */
}

The effect has three states:

  1. With no hover, half of each image shows.
  2. Hovering the first image reveals more of it, keeping a small corner cut.
  3. Hovering the second image reduces the first to a slim triangle.

Each of those states is a three-point polygon for clip-path. The clever part is that the "half-revealed" states aren't actually triangles. Adding a box-shadow shows the hidden geometry: the clipping polygon extends past the bounds of the element.

Showing the transition between states with the overflow shape revealed to explain how it works.

clip-path accepts values outside the 0%-100% range. That lets us describe a shape that appears to have a cut corner using only three points instead of the five it would take to trace the visible boundary. The number of points stays constant, so we can animate between states with a single CSS variable:

.gallery {
  --g: 8px; /* the gap */
}
.gallery > img {
  /* etc. */
  --_p: calc(-1 * var(--g));
  transition: .4s .1s;
}
.gallery:hover > img:last-child,
.gallery:hover > img:first-child:hover{
  --_p: calc(50% - var(--g));
}
.gallery:hover > img:first-child,
.gallery:hover > img:first-child:hover + img {
  --_p: calc(-50% - var(--g));
}

Ignoring the gap between images, the values of the --_p variable are 0%, 50%, and -50%, each triggering one of the three states.

The Pie Image Reveal

Extending the same idea to four images produces a pie-chart effect where each image is a quarter circle that morphs into a full circle on hover. The grid setup is unchanged from the split reveal; four equal images sit on top of each other.

The trick is that the points are not rotating. The clip-path is formed of seven points, with three stationary and four moving. At full speed, the slow morph is disguised as a quarter circle swelling into a complete disc. Adding border-radius sells the illusion even further.

The polygon for the first image in the sequence:

.gallery > img:nth-child(1) {
  clip-path: polygon(50% 50%, calc(50% * var(--_i, 0)) calc(120% * var(--_i, 0)), 0 calc(100% * var(--_i, 0)),0 0, 100% 0, 100% calc(100% * var(--_i, 0)), calc(100% - 50% * var(--_i, 0)) calc(120% * var(--_i, 0)));
}
.gallery > img:hover {
 --_i: 1;
}

A variable switches between 0 and 1 to toggle the shape. The other three images follow the same pattern with their own clip-path configurations. The values are hard to read by eye, but tools such as Clippy can visualize them.

The Mosaic of Images

A mosaic layout is an arrangement of irregular pieces that together form a full rectangle. The trick for building these in CSS Grid is to mentally complete each overlapping image into a full rectangle, and then derive the needed grid from those rectangles.

For five overlapping images, start with two large squares, side by side, each spanning the full height. That suggests two columns and one row; the overlapping center image adds two more columns. Finally the last two clips are half-height, adding a second row:

That leaves us with a tidy 4×2 grid.

That yields the grid definition:

.gallery {
  display: grid;
  grid: repeat(2, 1fr) / repeat(4, 1fr); 
  aspect-ratio: 2;
}
.gallery img:nth-child(1) {
  grid-area: 1 / 1 / span 2 / span 2;
}
.gallery img:nth-child(2) {
  grid-area: 1 / 2 / span 2 / span 2;
}
.gallery img:nth-child(3) {
  grid-area: span 2 / span 2 / -1 / -1;
}
.gallery img:nth-child(4) {
  grid-area: 2 / 1 / span 1 / span 2;
}
.gallery img:nth-child(5) {
  grid-area: span 1 / span 2 / -1 / -1;
}

The aspect ratio differs from previous examples. The first two images are squares next to each other, so the grid width is twice its height — aspect-ratio: 2.

The clipping stage produces four triangles and a rhombus:

Showing the three unique shapes and the clip-path values that create them.
We’re only showing the three unique shapes we’re making instead of the five total shapes.

The Complex Mosaic of Images

This example drops symmetry in favor of more intricate shapes, but the method stays the same. Sketch in each image's full rectangle and watch how the grid expands. The first two images are squares at different scales, producing two uneven columns and two rows.

Adding a third image introduces the need for more lines:

That moves us from a 2x2 grid to four columns and three rows. The remaining two images push it to five columns and four rows:

Using one fraction for the smallest column and row unit, the full grid compresses to:

grid: 3fr 1fr 2fr 2fr / 1fr 1fr 2fr 3fr 5fr;

Working through the five columns, define each one by its fractional size; repeat for the four rows. That gives the complete grid template. Then it is just a matter of positioning every image with grid-area and applying the necessary clip-path values.

We can trim the declarations. With no gaps between images, overlaps do some of the work: the center image needs no clip-path at all, since its neighbors overlap it into the correct shape. The overflowing three-point trick also applies to the bottom-left image, keeping everything down to four three-point polygon declarations in total:

.gallery img:nth-child(1) {
  grid-area: 1 / 1 /span 2 / span 3;
  clip-path: polygon(0 0, 100% 0, 0 100%);
}
.gallery img:nth-child(2) {
  grid-area: 1/2/span 3/span 3;
  clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
}
.gallery img:nth-child(3) {
  grid-area: 1 / span 2 / -1 / -1;
  clip-path: polygon(0 0, 100% 0, 100% 100%);
}
.gallery img:nth-child(4) {
  grid-area: span 3 / 1 / -1 / span 3;
  clip-path: polygon(25% 0, 100% 60%, 50% 100%, 0 100%, 0 20%);
}
.gallery img:nth-child(5) {
  grid-area: span 3/span 3/-1/-1;
  clip-path: polygon(50% 0, 100% 100%, 0 100%);
}

Two final layouts are left as practice — one manageable, the other harder. Both are achievable using the same overlapping grid plus clipping strategy shown here.