Want to Contribute to us or want to have 15k+ Audience read your Article ? Or Just want to make a strong Backlink?

CSS Grid and Custom Shapes, Part 3 | Style-Tricks

After Half 1 and Half 2, I’m again with a 3rd article to discover extra fancy shapes. Just like the earlier articles, we’re going to mix CSS Grid with clipping and masking to create fancy layouts for picture galleries.

CSS Grid and Customized Shapes collection

Ought to I learn the earlier articles earlier than?

It’s not obligatory however extremely advisable to cowl as many tips as attainable. You too can learn them in any order, however following alongside in chronological is a good suggestion to see how we arrived right here.

Sufficient speaking, let’s soar straight to our first instance.

Earlier than digging into the CSS, let’s verify the markup:

<div class="gallery">
  <img src="https://style-tricks.com/css-grid-and-custom-shapes-part-3/..." alt="https://style-tricks.com/css-grid-and-custom-shapes-part-3/...">
  <img src="https://style-tricks.com/css-grid-and-custom-shapes-part-3/..." alt="https://style-tricks.com/css-grid-and-custom-shapes-part-3/...">
  <img src="https://style-tricks.com/css-grid-and-custom-shapes-part-3/..." alt="https://style-tricks.com/css-grid-and-custom-shapes-part-3/...">
  <img src="https://style-tricks.com/css-grid-and-custom-shapes-part-3/..." alt="https://style-tricks.com/css-grid-and-custom-shapes-part-3/...">

Nothing however a couple of <img> tags in a div wrapper, proper? Keep in mind, the principle problem for this collection is to work with the smallest quantity of HTML attainable. All of the examples we’ve seen all through this collection use the very same HTML markup. No additional divs, wrappers, and whatnot. All that we want are photos contained in a wrapper factor.

Let’s verify the CSS now:

.gallery {
  --g: 6px; /* the hole */

  show: grid;
  width: 450px; /* the dimensions */
  aspect-ratio: 1; /* equal top */
  grid: auto-flow 1fr / repeat(3, 1fr);
  hole: var(--g);
.gallery img:nth-child(2) {
  grid-area: 1 / 2 / span 2 / span 2;
.gallery img:nth-child(3) {
  grid-area: 2 / 1 / span 2 / span 2;

Principally, it is a sq. grid with three equal columns. From there, all that’s occurring is the second and third photos are explicitly positioned on the grid, permitting the primary and final photos to put out mechanically round them.

This automated habits is a strong characteristic of CSS Grid known as “auto-placement”. Similar factor with the variety of rows — none of them are explicitly outlined. The browser “implicitly” creates them based mostly on the location of the objects. I’ve a really detailed article that explores each ideas.

You may be questioning what’s happening with these grid and grid-area property values. They appear unusual and are powerful to grok! That’s as a result of I selected the CSS grid shorthand property, which is tremendous helpful however accepts an unseemly variety of values from its constituent properties. You possibly can see all of them within the Almanac.

However what you really want to know is that this:

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

…is equal to this:

grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 1fr;
You too can use your favourite DevTools for additional proof.

Similar for the grid-area property. If we open DevTools and examine our declaration: grid-area: 1/2/span 2/span 2; you’re going to get the next:

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

…that’s the identical as writing all this out:

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 */

Similar deal for the opposite grid-area declaration. Once we put all of it collectively, right here’s what we get:

The different images labeled by number on the grid.

Sure, the second and third photos are overlapped within the center. That’s no mistake! I purposely spanned them on high of each other in order that I can apply a clip-path to chop a portion from every one and get the ultimate outcome:

Showing the effect with and without clip-path.

How will we do this? We are able to reduce the bottom-left nook of the second picture (img:nth-child(2)) with the CSS clip-path property:

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 nook of the third one:

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

I do know, I do know. That’s plenty of numbers and whatnot. I do have an article that particulars the method.

That’s it, we have now our first grid of photos! I added a grayscale filter on the <img> selector to get that neat little hover impact.

The Break up Picture Reveal

Let’s strive one thing totally different. We are able to take what we discovered about clipping the nook of a picture and mix it with a pleasant impact to disclose the total picture on hover.

The grid configuration for this one is much less intense than the final one, as all we want are two overlapping photos:

.gallery {
  show: grid;
.gallery > img {
  grid-area: 1 / 1;
  width: 350px; /* the dimensions */
  aspect-ratio: 1; /* equal top */

Two photos which are the identical dimension are stacked on high of one another (because of grid-area: 1 / 1).

The hover impact depends on animating clip-path. We’ll dissect the code of the primary picture to see the way it works, then plug the identical factor into the second picture with up to date values. Discover, although that we have now three totally different states:

  1. When no photos are hovered, half of every picture is revealed.
  2. Once we hover over the primary picture, it’s extra totally revealed however retains a small nook clip.
  3. Once we hover over the second picture, the primary one has solely a small triangle seen.
Showing the three clipping states of the hover effect.

In every case, we have now a triangular form. Which means we want a three-point polygon for the clip-path worth.

What? The second state isn’t a triangle, however extra of a sq. with a reduce nook.

You’re proper, but when we glance carefully we will see a “hidden” triangle. Let’s add a box-shadow to the pictures.

A ha! Did you discover it?

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

What kind of magic is that this? It’s a bit of identified undeniable fact that clip-path accepts values exterior the 0%-100% vary, which permits us to create “overflowing” shapes. (Sure, I simply coined this. You’re welcome.) This manner, we solely must work with three factors as an alternative of the 5 it will take to make the identical form from the seen components. Optimized CSS for the win!

That is the code after we plug within the polygon values into the clip-path property:

.gallery > img:first-child {
  clip-path: polygon(0 0, calc(100% + var(--_p)) 0 , 0 calc(100% + var(--_p)))
.gallery > img:last-child {
  clip-path: polygon(100% 100%, 100% calc(0% - var(--_p)), calc(0% - var(--_p)) 100%)

Discover the --_p variable. I’m utilizing that to optimize the code a bit as we add the hover transition. As an alternative of updating the entire clip-path we solely replace this variable to get the motion. Here’s a video to see how the factors ought to transfer between every state:

We are able to take slap a transition on the <img> selector, then replace the --_p variable on the states to get the ultimate impact:

.gallery {
  --g: 8px; /* the hole */
.gallery > img {
  /* and so forth. */
  --_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));

If we don’t take into account the hole (outlined as --g within the code) between the pictures, then the three values of --_p are 0%, 50%, and -50%. Each defines one of many states we defined beforehand.

The Pie Picture Reveal

Let’s improve the problem stage from that final one and attempt to do the identical trick however with 4 photos as an alternative of two.

Cool, proper? Every picture is 1 / 4 of a circle and, on hover, we have now an animation that transforms a picture right into a full circle that covers the remaining photos. The impact might look unimaginable as a result of there isn’t a solution to rotate factors and rework them to fill the circle. In actuality, although, we aren’t rotating any factors in any respect. It’s an phantasm!

For this instance, I’ll solely deal with the clip-path animation for the reason that configuration of the grid is similar because the earlier instance: 4 equally-sized photos stacked on high of one another.

And a video value a boring and lengthy clarification:

The clip-path is shaped by seven factors, the place three of them are in a hard and fast place and the others transfer as proven within the video. The impact seems much less cool when it’s working slowly however we will see how the clip-path morphs between shapes.

The impact is a bit of higher if we add border-radius and we make it sooner:

And by making it even sooner like within the unique instance, we get the proper phantasm of 1 quarter of a circle morphing right into a full circle. Right here’s the polygon worth for our clip-path on the primary picture within 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;

As regular, I’m utilizing a variable to optimize the code. The variable will swap between 0 and 1 to replace the polygon.

The identical goes for the others picture however with a distinct clip-path configuration. I do know that the values might look laborious to decipher however you may all the time use on-line instruments like Clippy to visualise the values.

The Mosaic of Photos

You understand mosaics, proper? It’s an artwork type that creates ornamental designs out of smaller particular person items, like coloured stones. But it surely will also be a composite picture made up of different smaller photos.

And, you guessed it: we will completely do this form of factor in CSS!

First, let’s think about what issues are like if clip-path had been taken out of the combo and all we had had been 5 overlapping photos:

I’m dishonest a bit of on this video as a result of I’m inspecting the code to determine the world of every picture, however that is what that you must do in your head. For every picture, attempt to full the lacking half to see the total rectangle and, with this, we will determine the place and dimension of every one.

We have to discover what number of columns and rows we want for the grid:

  1. We have now two massive photos positioned subsequent to one another that every fill half the grid width and the total grid top. Which means will in all probability want two columns (one for each photos) and one row (for the total top of the grid).
  2. We have now the picture within the center that overlaps the 2 different photos. Which means we really want 4 columns as an alternative of two, although we nonetheless solely want the one row.
  3. The final two photos every fill half the grid, identical to the primary two photos. However they’re solely half the peak of the grid. We are able to use the prevailing columns we have already got, however we’re going to wish two rows as an alternative of 1 to account for these photos being half the grid top.
That leaves us with a tidy 4×2 grid.

I don’t need you to suppose that the way in which I sliced this up is the solely solution to do it. That is merely how I’ve made sense of it. I’m positive there are different configurations attainable to get the identical format!

Let’s take that info and outline our grid, then place the pictures on it:

.gallery {
  show: 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;

I believe you get the concept of what’s occurring right here now that we’ve seen a couple of examples utilizing the identical method. We outline a grid and place photos on it explicitly, utilizing grid-area so the pictures overlap.

OK, however the aspect-ratio is totally different this time.

It’s! In case you get again to the reasoning we made, we have now the primary two photos which are sq. subsequent to one another having the identical dimension. Because of this the width of the grid must be equal to twice its top. Therefore, aspect-ratio: 2.

Now it’s time for the clip-path values. We have now 4 triangles and a rhombus.

Showing the three unique shapes and the clip-path values that create them.
We’re solely exhibiting the three distinctive shapes we’re making as an alternative of the 5 complete shapes.

Once more, I’m utilizing Clippy for all this math-y stuff. However, actually, I can write many easy shapes by hand, having spent a number of years working carefully with clip-path, and I do know you may too with follow!

The Complicated Mosaic of Photos

Let’s improve the problem and take a look at one other mosaic, this time with much less symmetry and extra advanced shapes.

Don’t fear, you will notice that it’s the identical idea because the one we simply made! Once more, let’s think about every picture is a rectangle, then go about defining the grid based mostly on what we see.

We’ll begin with two photos:

They’re each squares. The primary picture is the same as half the dimensions of the second picture. The primary picture takes up lower than one half of the grid width, whereas the second picture takes up greater than half giving us a complete of two columns with a distinct dimension (the primary one is the same as half the second). The primary picture is half the peak, so let’s mechanically assume we want two rows as properly.

Let’s add one other picture to the format

This one makes issues a bit extra advanced! We have to draw some traces to determine learn how to replace the grid configuration.

We’ll transfer from a 2×2 grid to 4 columns and three rows. Fairly uneven, proper? Earlier than we strive to determine that full sizing, let’s see if the identical format holds up once we add the opposite photos.

Appears like we nonetheless want extra rows and columns for all the things to fall into place. Primarily based on the traces in that picture, we’re going to have a complete of 5 columns and 4 rows.

The logic is straightforward regardless that the format is advanced, proper? We add the pictures one after the other to search out the precise configuration that matches all the things. Now we have to determine the dimensions of every column and row.

If we are saying the smallest row/column is the same as one fraction of the grid (1fr) we’ll get:

grid-template-columns: 1fr 1fr 2fr 3fr 5fr;

…for the columns, and:

grid-template-rows: 3fr 1fr 2fr 2fr;

…for the rows. We are able to consolidate this utilizing the grid shorthand property once more:

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

You understand the drill! Place the pictures on the grid and apply a clip-path on them:

.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%);

We are able to cease right here and our code is ok, however we’ll perform a little extra to optimize the clip-path values. Since we don’t have any gaps between our photos, we will use the truth that our photos overlap to slim issues down. Here’s a video as an instance the concept:

As you may see, the picture within the center (the one with the digicam) doesn’t want a clip-path. as a result of the opposite photos overlap it, giving us the form with none further work! And spot that we will use the identical overflowing three-point clip-path idea we used earlier on the picture within the bottom-left to maintain the code smaller there as properly.

In the long run, we have now a complex-looking grid of photos with solely 4 clip-path declarations — all of them are three-point polygons!

Wrapping up

Wow, proper? I don’t find out about you, however I by no means become bored with seeing what CSS can do as of late. It wasn’t way back that each one of this may have taken verbose hackery and undoubtedly some JavaScript.

All through this collection, we explored many, many various kinds of picture grids, from the essential stuff to the advanced mosaics we made immediately. And we bought plenty of hands-on expertise working with CSS clipping — one thing that you’ll undoubtedly be capable of use on different initiatives!

However earlier than we finish this, I’ve some homework for you…

Listed here are two mosaics that I would like you to make utilizing what we coated right here. One is on the “simpler” aspect, and the opposite is a bit tough. It could be actually superior to see your work within the feedback, so hyperlink them up! I’m curious to see in case your method is totally different from how I’d go about it!

Add a Comment

Your email address will not be published. Required fields are marked *

Want to Contribute to us or want to have 15k+ Audience read your Article ? Or Just want to make a strong Backlink?