Monday, November 28, 2022
HomeProgrammingCSS Grid and Customized Shapes, Half 3 | CSS-Methods

CSS Grid and Customized Shapes, Half 3 | CSS-Methods


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 potential. You can even 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 leap straight to our first instance.

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

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

Nothing however a couple of <img> tags in a div wrapper, proper? Bear in mind, the principle problem for this collection is to work with the smallest quantity of HTML potential. All of the examples we’ve seen all through this collection use the very same HTML markup. No further divs, wrappers, and whatnot. All that we’d like are pictures contained in a wrapper ingredient.

Let’s test the CSS now:

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

  show: grid;
  width: 450px; /* the scale */
  aspect-ratio: 1; /* equal peak */
  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;
}

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

This computerized conduct is a strong function of CSS Grid referred to as “auto-placement”. Identical factor with the variety of rows — none of them are explicitly outlined. The browser “implicitly” creates them based mostly on the position of the objects. I’ve a very detailed article that explores each ideas.

You is perhaps 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’ll be able to 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;
DevTools style rules for the grid property.
You can even use your favourite DevTools for additional proof.

Identical for the grid-area property. If we open DevTools and examine our declaration: grid-area: 1/2/span 2/span 2; you’ll 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 */

Identical 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 pictures are overlapped within the center. That’s no mistake! I purposely spanned them on prime of each other in order that I can apply a clip-path to chop a portion from each and get the ultimate consequence:

Showing the effect with and without clip-path.

How can we do this? We are able to minimize 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 loads of numbers and whatnot. I do have an article that particulars the method.

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

The Break up Picture Reveal

Let’s attempt 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 complete picture on hover.

The grid configuration for this one is much less intense than the final one, as all we’d like are two overlapping pictures:

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

Two pictures which can be the identical dimension are stacked on prime of one another (due to grid-area: 1 / 1).

The hover impact depends on animating clip-path. We are going to 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’ve three totally different states:

  1. When no pictures are hovered, half of every picture is revealed.
  2. Once we hover over the primary picture, it’s extra absolutely 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’ve a triangular form. Meaning we’d like a three-point polygon for the clip-path worth.

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

You’re proper, but when we glance intently we are able to 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 little bit recognized 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 should 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 a substitute 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 many others. */
  --_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 think about 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 pictures as an alternative of two.

Cool, proper? Every picture is 1 / 4 of a circle and, on hover, we’ve an animation that transforms a picture right into a full circle that covers the remaining pictures. The impact might look unattainable as a result of there is no such thing as a method 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 give attention to the clip-path animation for the reason that configuration of the grid is similar because the earlier instance: 4 equally-sized pictures stacked on prime of one another.

And a video value a boring and lengthy rationalization:

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 operating slowly however we are able to see how the clip-path morphs between shapes.

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

And by making it even sooner like within the authentic instance, we get the right 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 standard, 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 special clip-path configuration. I do know that the values might look onerous to decipher however you possibly can at all times use on-line instruments like Clippy to visualise the values.

The Mosaic of Photographs

You recognize mosaics, proper? It’s an artwork fashion that creates ornamental designs out of smaller particular person items, like coloured stones. Nevertheless it can be a composite picture made up of different smaller pictures.

And, you guessed it: we are able to completely do this kind 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 pictures:

I’m dishonest a little bit on this video as a result of I’m inspecting the code to establish the realm of every picture, however that is what you’ll want to do in your head. For every picture, attempt to full the lacking half to see the complete rectangle and, with this, we are able to establish the place and dimension of every one.

We have to discover what number of columns and rows we’d like for the grid:

  1. We’ve got two massive pictures positioned subsequent to one another that every fill half the grid width and the complete grid peak. Meaning will most likely want two columns (one for each pictures) and one row (for the complete peak of the grid).
  2. We’ve got the picture within the center that overlaps the 2 different pictures. Meaning we really need 4 columns as an alternative of two, although we nonetheless solely want the one row.
  3. The final two pictures every fill half the grid, identical to the primary two pictures. 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 want two rows as an alternative of 1 to account for these pictures being half the grid peak.
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 method to do it. That is merely how I’ve made sense of it. I’m certain there are different configurations potential to get the identical format!

Let’s take that data 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 thought of what’s occurring right here now that we’ve seen a couple of examples utilizing the identical strategy. We outline a grid and place pictures on it explicitly, utilizing grid-area so the pictures overlap.

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

It’s! In the event you get again to the reasoning we made, we’ve the primary two pictures which can be sq. subsequent to one another having the identical dimension. Which means that the width of the grid must be equal to twice its peak. Therefore, aspect-ratio: 2.

Now it’s time for the clip-path values. We’ve got 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 whole shapes.

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

The Advanced Mosaic of Photographs

Let’s improve the problem and check out one other mosaic, this time with much less symmetry and extra complicated 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 pictures:

They’re each squares. The primary picture is the same as half the scale 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 special dimension (the primary one is the same as half the second). The primary picture is half the peak, so let’s robotically assume we’d like two rows as nicely.

Let’s add one other picture to the format

This one makes issues a bit extra complicated! We have to draw some strains to establish the way to replace the grid configuration.

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

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

The logic is easy though the format is complicated, proper? We add the pictures one after the other to seek out the best configuration that matches all the things. Now we have to establish the scale 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 recognize 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 pictures, we are able to use the truth that our pictures overlap to slim issues down. Here’s a video for example the thought:

As you possibly can see, the picture within the center (the one with the digicam) doesn’t want a clip-path. as a result of the opposite pictures overlap it, giving us the form with none extra work! And see that we are able to 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 nicely.

Ultimately, we’ve a complex-looking grid of pictures 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 lately. It wasn’t way back that every one of this is able to 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 complicated mosaics we made at present. And we bought loads of hands-on expertise working with CSS clipping — one thing that you’ll undoubtedly be capable to use on different tasks!

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

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

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments