This article is translated from CSS Grid and Custom Shapes, Part 1 , slightly edited
In normal development, we will encounter many requirements for the alignment of element blocks, such as the nine-square grid lottery, the preview of the layout in equal parts after uploading multiple pictures, and the display of multiple pictures in the WeChat Moments. This is a normal square very neat layout.
As shown below, what if the image is not exactly square, but shaped like a hexagon or a rhombus? How do we do it. In fact, we're going to combine the CSS grid techniques we've already looked at and throw in some CSS clip-path
and mask
magic to create beautiful image grids for any shape you can imagine!
the same HTML
Most of the layouts we'll be looking at seem easy to implement at first glance, but the challenging part is implementing them using the same HTML markup. We could use a lot of wrappers, divs, etc., but the goal of this article is to use the same and minimal HTML code and still achieve all the different styles of grids we want.
That said, let's start with the following HTML:
<div class="gallery">
<img src="..." alt="...">
<img src="..." alt="...">
<img src="..." alt="...">
<img src="..." alt="...">
<!-- as many times as we want -->
</div>
A container with an image is all we need here. Enough!
Hexagon CSS Grid
This shape is also sometimes called a honeycomb grid.
First, we use clip-path
on the image to create hexagon shapes and place them all in the same grid area so that they overlap.
.gallery {
--s: 150px; /* controls the size */
display: grid;
}
.gallery > img {
grid-area: 1/1;
width: var(--s);
aspect-ratio: 1.15;
object-fit: cover;
clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0 50%);
}
![clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0 50%)
]( https://files.mdnice.com/user/29888/049f77e7-f848-47eb-95a8-cf8f810bcb8f.png )
At this point all the images are hexagonal and overlapped. So it looks like we only have one hexagonal image element, but there are actually seven. The next step is to translate the images to the grid where they are correctly placed.
Keep one of the images in the center. The rest of the image is panned around it using CSS translate
. Here is the simulation formula I came up with for each image in the grid:
translate((height + gap)*sin(0deg), (height + gap)*cos(0))
translate((height + gap)*sin(60deg), (height + gap)*cos(60deg))
translate((height + gap)*sin(120deg), (height + gap)*cos(120deg))
translate((height + gap)*sin(180deg), (height + gap)*cos(180deg))
translate((height + gap)*sin(240deg), (height + gap)*cos(240deg))
translate((height + gap)*sin(300deg), (height + gap)*cos(300deg))
After some calculations and optimizations, we get the following final CSS
.gallery {
--s: 150px; /* control the size */
--g: 10px; /* control the gap */
display: grid;
}
.gallery > img {
grid-area: 1/1;
width: var(--s);
aspect-ratio: 1.15;
object-fit: cover;
clip-path: polygon(25% 0%, 75% 0%, 100% 50% ,75% 100%, 25% 100%, 0 50%);
transform: translate(var(--_x,0), var(--_y,0));
}
.gallery > img:nth-child(1) { --_y: calc(-100% - var(--g)); }
.gallery > img:nth-child(7) { --_y: calc( 100% + var(--g)); }
.gallery > img:nth-child(3),
.gallery > img:nth-child(5) { --_x: calc(-75% - .87*var(--g)); }
.gallery > img:nth-child(4),
.gallery > img:nth-child(6) { --_x: calc( 75% + .87*var(--g)); }
.gallery > img:nth-child(3),
.gallery > img:nth-child(4) { --_y: calc(-50% - .5*var(--g)); }
.gallery > img:nth-child(5),
.gallery > img:nth-child(6) { --_y: calc( 50% + .5*var(--g)); }
Each image is transformed by --_x
and variables based on these formulas. --_y
Only the second image ( nth-child(2) ) is undefined in any selector because it is in the center. It can be any image if you decide to use a different order. Here is the order I use:
With just a few lines of code, we have a cool grid of images. To this end, I added a hover effect to the image to take the interaction to a higher level. The online preview of the code is as follows:
https://code.juejin.cn/pen/7132450107156332552
CSS diamond grid
A rhombus is a square that is rotated 45 degrees.
Still the same HTML, we first define a 2x2 grid of images in CSS:
.gallery {
--s: 150px; /* controls the size */
display: grid;
gap: 10px;
grid: auto-flow var(--s) / repeat(2, var(--s));
place-items: center;
}
.gallery > img {
width: 100%;
aspect-ratio: 1;
object-fit: cover;
}
Then set the rotation, notice how I rotate them both by 45deg, but in the opposite direction.
.gallery {
transform: rotate(45deg);
}
.gallery > img {
transform: rotate(-45deg);
}
Rotating the images in the negative direction prevents them from rotating with the grid, so they stay straight. Now, we apply clip-path
to cut diamonds out of them.
![clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%)
]( https://files.mdnice.com/user/29888/795a309b-c674-4d26-bbe9-89e932b09c80.png )
The images at this point are not spaced as we expected, and we need to correct the size of the images to make them fit together. Otherwise, they'll be so far apart that they don't look like an image grid.
The image is within the bounds of the green circle, the circle inscribed in the grid area where the image is placed. What we want is to enlarge the image to fit the red circle, the circumcircle of the grid area.
.gallery > img {
width: 141%; /* 100%*sqrt(2) = 141% */
aspect-ratio: 1;
object-fit: cover;
transform: rotate(-45deg);
clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
}
Finally, add a hover effect to the image. The online code is as follows:
https://code.juejin.cn/pen/7132464081167974434
CSS grid of triangles
As you probably know by now, the biggest trick is figuring out clip-path
the shape we want. For this grid, each element has its own clip-path
value, and the last two grids use a consistent shape. So, this time, it's like we're dealing with a few different triangle shapes that combine to form a rectangular image grid.
We place them in a 3×2 grid using the following CSS:
.gallery {
display: grid;
gap: 10px;
grid-template-columns: auto auto auto; /* 3 columns */
place-items: center;
}
.gallery > img {
width: 200px; /* controls the size */
aspect-ratio: 1;
object-fit: cover;
}
/* the clip-path values */
.gallery > img:nth-child(1) { clip-path: polygon(0 0, 50% 0, 100% 100% ,0 100%); }
.gallery > img:nth-child(2) { clip-path: polygon(0 0, 100% 0, 50% 100%); }
.gallery > img:nth-child(3) { clip-path: polygon(50% 0, 100% 0, 100% 100%, 0 100%); }
.gallery > img:nth-child(4) { clip-path: polygon(0 0, 100% 0, 50% 100%, 0 100%); }
.gallery > img:nth-child(5) { clip-path: polygon(50% 0, 100% 100%, 0% 100%); }
.gallery > img:nth-child(6) { clip-path: polygon(0 0, 100% 0 ,100% 100%, 50% 100%); } }
The final result is shown in the figure below:
The last point is to make the width of the middle column equal to 0 to eliminate the space between the images. We had the same spacing issue with the diamond grid, but took a different approach to the shapes we used:
grid-template-columns: auto 0 auto;
The final online code is as follows:
https://code.juejin.cn/pen/7132468930584510502
Pizza Shaped CSS Grid
Another cool grid can be achieved by adding simple border-radius and overflow based on the triangle grid above, a pizza shaped CSS grid.
Puzzle style CSS grid
This time we will use the CSS mask
property to make the image look like a puzzle.
Setting up the grid should be a piece of cake now, so let's focus on mask
. We need two gradients to create the final puzzle shape. One gradient creates a circle (the green part), and the other gradient creates the red area and fills the semicircle with the white area.
--g: 6px; /* controls the gap */
--r: 42px; /* control the circular shapes */
background:
radial-gradient(var(--r) at left 50% bottom var(--r), green 95%, #0000),
radial-gradient(calc(var(--r) + var(--g)) at calc(100% + var(--g)) 50%, #0000 95%, red)
top/100% calc(100% - var(--r)) no-repeat;
Two variables control the shape. --g
Variable controls grid gap, relatively not the most important. It is important to consider how to properly place our circles between the gaps so that they overlap perfectly when the entire puzzle is assembled. The --r
variable controls the size of the circular portion of the puzzle shape.
Then we create the other three shapes using the same CSS values with slight adjustments for different positions:
At this point the overall puzzle is in shape, but it doesn't overlap as we expected. Because each image is constrained to the grid cell it's in, it's right that the shape is a bit messy now:
We need to create overflow by increasing the height/width of the image. From the image above, we have to increase the height of the first and fourth images, while increasing the width of the second and third images. As you might have guessed we need to use the --r variable to increment them.
.gallery > img:is(:nth-child(1),:nth-child(4)) {
width: 100%;
height: calc(100% + var(--r));
}
.gallery > img:is(:nth-child(2),:nth-child(3)) {
height: 100%;
width: calc(100% + var(--r));
}
At this point the two images on the left are displayed as expected, but by default our images either overlap on the right (if we increase the width) or on the bottom (if we increase the height). But this is not the second and fourth image we want. The workaround is to use place-self: end
on both images, and finally our full code is as follows:
https://code.juejin.cn/pen/7132472038211452942
Finally, a different one, in order to ensure the loading speed of the gif image, I replaced the image with a solid color image, this time we use clip-path
, because it is an attribute that we can animate, we only need to update the control shape Custom properties to get cool hover effects. We set a custom variable to control the angle of the default triangle. When the mouse is hovered, set the variable to 0 to return to the normal square. The effect is as follows:
The online code is as follows:
https://code.juejin.cn/pen/7133195476844675103
at last
This article by combining what we already know about CSS Grid
with some additional magic of clip-path
of mask
, we are able to make grid layouts of different shapes. And we use the same HTML code every time! The code itself is nothing more than a container with a small number of image elements! After reading it, do you think it is very simple and amazing? Interested students can try it for themselves, maybe you can create more interesting grid graphics.
If you find it useful at the end, remember to like it and save it, maybe you will use it someday.
Focus on front-end development, share dry goods related to front-end technology, public account: Nancheng Front-end (ID: nanchengfe)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。