Yan Wenbin
Original statement: This article is produced by members of Yuewen front-end team YFE, please respect the original, reprint please contact the public number (ID: yuewen_YFE) for authorization, and indicate the author, source and link.
In the real world of Web development, you come across a variety of layouts. A company colleague asked me if there is any good way to achieve such a layout, which is a very common coupon effect in the activity recharge page, as follows
And then there’s this
Considering the various possible scenarios, let’s abstract the following examples and take a look at the implementation
First, the best way to achieve
First, the best implementation to encounter this type of layout is certainly a mask. For masks, see the CSS3 Mask Amway report. Here is a brief introduction
The basic syntax is very simple, and is basically the same as the syntax of background
.content{
-webkit-mask: 'Mask picture' ;
}
/* Complete syntax */
.content{
-webkit-mask: 'Mask picture' [position] / [size] ;
}
Copy the code
The mask image and background are used in the same way. It can be A PNG image, an SVG image, or a gradient image. It also supports multiple image overlay.
The principle of the mask is simple, the final effect will only show the opaque part, the transparent part will not be visible, translucent and so on
In fact, in addition to using Alpha as the mask condition, it can also be determined by luminance, such as white for hiding and black for visibility. It is currently only supported by Firefox
So, as long as you can draw all the above shapes, you can do it.
Two, concave rounded corners
Most coupons have a very obvious feature, is concave rounded corners. When it comes to rounded corners, it’s easy to think of the radial-gradient. CSS3 radial gradient: CSS3 radial gradient: CSS3 Radial gradient
.content{
-webkit-mask: radial-gradient(circle at left center, transparent 20px, red 20px);
}
Copy the code
This creates a transparent circle with a radius of 20px, but there is still a lot of room for optimization at the code level.
- For a well-bounded gradient, the position of the color behind only needs to be less than or equal to the position of the color in front, such as 0
- The transparent color can be replaced by a hexadecimal abbreviation such as **#0000. The opaque part can be used in any color. I prefer red**, mainly because it is a short word
- Also, the gradient position defaults to center, so the second center can be removed and left can be denoted by 0
So if I simplify it a little bit more, I get it
.content{
-webkit-mask: radial-gradient(circle at 0.# 0000 20px, red 0);
}
Copy the code
Good, and a few less B traffic ~ can check out the online instance codepen coupon implementation 1
Three, coupon effect
The above is a basic concave corner effect, now to achieve the following layout, such as two semicircles, according to the above example, and then copy a circle can not be? Change the orientation
.content{
-webkit-mask: radial-gradient(circle at 0.# 0000 20px, red 0), radial-gradient(circle at right, # 0000 20px, red 0);
}
Copy the code
There was no circle left. The reason is actually quite simple. As shown below, two layers of background are superimposed on each other, resulting in the whole background being opaque, so the mask effect is completely visible.
There are two solutions, respectively:
- Stagger the place of the two concave corners, here can be modified by the size and position, but also need to prohibit tiling
.content{
-webkit-mask: radial-gradient(circle at 0.# 0000 20px, red 0), radial-gradient(circle at right, # 0000 20px, red 0);
-webkit-mask-size: 51%; /* Avoid gaps */
-webkit-mask-position: 0.100%; /* One on the left and one on the right */
-webkit-mask-repeat: no-repeat;
}
Copy the code
The dynamic demo is as follows, so you don’t overwrite each other
You can view an online instance of Codepen Coupon Implementation 2
- Use mask compositionmask-compositeThis may not be familiar, but just a quick introduction
Mask-composite has 4 properties under standard properties (Firefox supports)
/* Keyword values */
mask-composite: add; /* Overlay (default) */
mask-composite: subtract; /* minus, you get rid of the upper region */
mask-composite: intersect; /* Intersection, show only overlap */
mask-composite: exclude; /* Exclude, show only the areas that do not overlap */
Copy the code
This may be difficult to understand, in fact, some graphics software can refer to the shape synthesis operation, such as Photoshop
-webkit-mask-composite is different from the standard value, there are a lot of properties, see below
-webkit-mask-composite: clear; /* Clear, do not show any mask */
-webkit-mask-composite: copy; /* Show only the top mask, not the bottom mask */
-webkit-mask-composite: source-over;
-webkit-mask-composite: source-in; /* Show only overlap */
-webkit-mask-composite: source-out; /* Only the top mask is displayed. */ is not displayed where the overlap is
-webkit-mask-composite: source-atop;
-webkit-mask-composite: destination-over;
-webkit-mask-composite: destination-in; /* Show only overlap */
-webkit-mask-composite: destination-out;/* Only the lower mask is displayed. */ is not displayed where the mask overlaps
-webkit-mask-composite: destination-atop;
-webkit-mask-composite: xor; /* Show only the areas that do not overlap */
Copy the code
Is it blindsided? Don’t panic, you can see that some of the values above are source-*, and some start with **destination-**. Source represents new content, which is the layer drawn above, and destination represents meta content, which is the layer drawn below (in CSS, Behind the front layer will cover layer), the attribute value is borrowed from the concepts of the Canvas, specific can view CanvasRenderingContext2D. GlobalComposite
Remember not to matter, the actual development can be tested one by one [\ facepalm]. For details, see the codepen-webkit-mask-composite attribute value
With this property in mind, the superposition problem above is easy, just set it to show only the overlaps
.content{
-webkit-mask: radial-gradient(circle at 0.# 0000 20px, red 0), radial-gradient(circle at right, # 0000 20px, red 0);
-webkit-mask-composite: source-in | destination-in ; /*chrome*/
mask-composite: intersect; /*Firefox*/
}
Copy the code
The dynamic is shown below, so that only overlap is shown
You can view the online instance codepen Coupon Implementation 3
If you have 2 fillets, 4 fillets is easy, just draw 4 circles, and the same can be done easily with mask composition
content{
-webkit-mask: radial-gradient(circle at 0 0.# 0000 20px, red 0), radial-gradient(circle at right 0.# 0000 20px, red 0), radial-gradient(circle at 0 100%.# 0000 20px, red 0), radial-gradient(circle at right 100%.# 0000 20px, red 0); /* Put a circle at each of the four corners
-webkit-mask-composite: source-in | destination-in ; /*chrome*/
mask-composite: intersect; /*Firefox*/
}
Copy the code
You can view the online instance codepen Coupon Implementation 4
Four, coupon tiling effect
The example above shows the effect of 2 and 4 rounded corners, drawing 2 and 4 circles, respectively. This can be achieved by tiling only one circle. The steps are as follows
- Draw a clear circle on the left side
.content{
-webkit-mask: radial-gradient(circle at 20px.# 0000 20px, red 0);
}
Copy the code
- It shifts itself to the left by half
.content{
-webkit-mask: radial-gradient(circle at 20px.# 0000 20px, red 0);
-webkit-mask-position: -20px
}
/* can also be abbreviated to */
.content{
-webkit-mask: radial-gradient(circle at 20px.# 0000 20px, red 0) -20px;
}
Copy the code
It works. Isn’t that amazing? In fact, it uses the default repeat feature, which can be seen here with a GIF
Below, the red border shows the range of viewport, which is the final effect. Here, for the purpose of demonstration, we make the tiling out of sight translucent, and move it to show the process of changing position
You can view an online instance of Codepen coupon implementation 5
The same principle, 4 rounded corners can also be implemented in this way
.content{
-webkit-mask: radial-gradient(circle at 20px 20px.# 0000 20px, red 0);
-webkit-mask-position: -20px -20px;
}
/* can also be abbreviated to */
.content{
-webkit-mask: radial-gradient(circle at 20px 20px.# 0000 20px, red 0) -20px -20px;
}
Copy the code
The implementation principle is shown below
You can view the online instance codepen coupon Implementation 6
Six rounded corners need to be resized.
.content{
-webkit-mask: radial-gradient(circle at 20px 20px.# 0000 20px, red 0);
-webkit-mask-position: -20px -20px;
-webkit-mask-size: 50%;
}
/* can also be abbreviated to */
.content{
-webkit-mask: radial-gradient(circle at 20px 20px.# 0000 20px, red 0) -20px -20px / 50%;
}
Copy the code
The implementation principle is shown below
You can view an online instance of Codepen coupon implementation 7
If you continue to reduce the size of the background image, you can still get the final effect
.content{
-webkit-mask: radial-gradient(circle at 10px.# 0000 10px, red 0);
-webkit-mask-position: -10px;
-webkit-mask-size: 100% 30px;
}
/* can also be abbreviated to */
.content{
-webkit-mask: radial-gradient(circle at 20px 20px.# 0000 20px, red 0) -10px / 100% 30px;
}
Copy the code
The implementation principle is shown below, in fact, tiling
You can view an online instance of Codepen coupon implementation 8
Five, reverse hollowing superposition
In some cases it may not be possible to create complex shapes with a single gradient layer, which requires a reverse hollowing technique, which is the mask composition mentioned above
- So let’s get the implementation up here
.content{
-webkit-mask: radial-gradient(circle at 20px 20px.# 0000 20px, red 0) -20px -20px / 50%;
}
Copy the code
- Make a row of small holes directly in the base
.content{
-webkit-mask: radial-gradient( circle at 50%, red 5px.# 0000 0) 50% 50% / 100% 20px.radial-gradient(circle at 20px 20px.# 0000 20px, red 0) -20px -20px / 50%;
-webkit-mask-composite: destination-out;
mask-composite: subtract; /*Firefox*/
}
Copy the code
**-webkit-mask-composite: destination-out**
You can view the online instance codepen Coupon Implementation 9
You can put it on both sides, just change the position
.content{
-webkit-mask: radial-gradient( circle at 5px, red 5px.# 0000 0) -5px 50% / 100% 20px.radial-gradient(circle at 20px 20px.# 0000 20px, red 0) -20px -20px / 50%;
-webkit-mask-composite: destination-out;
mask-composite: subtract; /*Firefox*/
}
Copy the code
You can view the online instance codepen coupon implementation 10
Six, border mask
Some students think radial gradient is too complicated to write, can use pictures instead? It’s possible. Mask-border is currently in the W3C draft, but there is an alternative attribute -webkit-mask-box-image
The syntax and concept are very similar to that of a border-image. For more information on the correct use of a border-image, see this article
.content{
-webkit-mask-box-image: 'Mask picture' [<top> <right> <bottom> <left> <x-repeat> <y-repeat>]
}
Copy the code
Let’s say there’s a picture like this
SVG code looks like this, many tools can be exported, really can not be directly to design students
<svg xmlns="http://www.w3.org/2000/svg" width="60.031" height="60.031" viewBox="0 0 60.031 60.031"><path d="M40 60.027H20.129a20.065 20.065 0 0 0.06540H0v20.127h.065a20.066 20.066 0 0 20.131.061v-.065H40V.065A20.065 20.065 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 fill-rule="evenodd"/></svg>
Copy the code
Need to escape here, can use Mr. Zhang’s SVG online merge tool
.content{
-webkit-mask-box-image: url("Data: image/SVG + XML, % 3 CSVG XMLNS =" http://www.w3.org/2000/svg "width = '60.031' height = '60.031' viewBox = '0 0, 60.031 60.031'%3E%3Cpath D ='M40 60.027h20.129a20.065 20.065 0 0 065 40h0v20.127h.065a20.066 20.066 0 0 0 20.131.06v -.065h40V.065a20.065 20.065 0 0 0 20.027 20.064 v40a20.063 20.063 0 0 0 40 60.027z' fill-rule='evenodd'/%3E%3C/svg%3E") 20;
/* Here, 20 means to keep a fixed area of 20 pixels around, and tile or stretch the rest */
}
Copy the code
And then you have a shape like this, which is also adaptive
You can view the online instance codepen-webkit-mask-box-iamge implementation 1
Let’s say I have a picture like this
.content{
-webkit-mask-box-image: url("Data: image/SVG + XML, % 3 CSVG XMLNS =" http://www.w3.org/2000/svg "width = '60.031' height = '60.031' viewBox = '0 0, 60.031 60.031'%3E%3Cpath d='M55.186 30.158a4.965 4.965 0 0 0 4.841 4.959 v40a20.063 20.063 0 0 0 40 60.027h20.129 A20.065 20.065 0 0 065 40H0v-4.888c.054 0.1.016.158.016 a4.973 4.973 01 0-9.945c-.054 0-.1.014-.158.015v-5.074h.065a20.066 20.066 0 0 0 20.131.058v-.065h40V.065a20.065 20.065 0 0 0 20.027 20.064v5.07a4.965 4.965 0 0 0-4.841 4.966z' fill-rule='evenodd'/%3E%3C/svg%3E") 20;
}
Copy the code
You get a shape like this, where the semicircle on both sides is stretched
In this case, you only need to set the tiling mode **-webkit-mask-box-image-repeat. ** This is the same concept as border-image-repeat and has the following four values
-webkit-mask-box-image-repeat: stretch; /* Stretch (default), not tile */
-webkit-mask-box-image-repeat: repeat; / * repeat * /
-webkit-mask-box-image-repeat: round; /* Repeat, if you can't tiling an integer number, stretch according to the case. * /
-webkit-mask-box-image-repeat: space; /* repeat, when integer tiling is not possible, the blank space will be filled with */
Copy the code
The differences between several tiling methods are as follows
We can use round or repeat here
.content{
-webkit-mask-box-image: url("...") 20;
-webkit-mask-box-image-repeat: round;
}
Copy the code
You can view the online instance codepen-webkit-mask-box-iamge implementation 2
Vii. Summary and explanation
The above introduces a total of 12 coupon drawing cases, should be able to solve most of this type of layout problems, here to summarize the following points
- CSS masks are definitely the perfect way to implement this type of layout
- CSS radial- Gradient drawing skills are required
- Use repeat whenever possible to repeat the same element
- Mask-composite should be used flexibly when multiple shapes are stacked
- You can also use an image to replace the CSS gradient, using mask-border
In terms of compatibility, there are no major problems regardless of IE. The last mask-border is only compatible with Chrome kernel, so can it be safely used on mobile terminals
Thank you for reading, I hope it will inspire my future work.