This article comes from Slicing SVG 9 Ways. The ideas and methods provided are really good. After learning, the article is not translated word for word. The main idea is to learn the core and method.

I recently encountered a problem in a project, as shown below:

The demo address

Is a card flip effect, carefully observe the card flip at the same time, there is a shadow effect at the bottom of the card, the shadow in the card flip process mainly the following two changes:

  • The shadow will shift as the card size changes during the card flip.
  • The size of the shadow also ADAPTS to the size of the card.

Of course, there are many ways to achieve this effect. But there are not many ways to combine performance and adaptation.

We are looking for a solution that addresses both of the following aspects:

  • Performance friendly. This can be done by using the transform and opacity properties that change shadows, which are rendered directly using the device’s GPU.
  • Good maintenance. Shadows can be easily maintained by code, such as changing the color of the shadow.

Solution 1: Passbox-shadowTo implement the

The first thing that comes to mind is the use of box-shadow. The shadow effect can be achieved with a single line of code.

However, since box-shadow is directly applied to the element itself, this means that if you want to animate the shadow by changing its blur or X and Y values. Will trigger the page redraw, which will affect the performance of the page.

This can also be done by changing opacity of an element such as after or before shadows, but this is not very flexible.

Solution 2: Implement with Blur Filter

Another way to do this is by using CSS filters called Blur filters. Such as filter, blur (12 px).

As shown below:

Normal graph:

After using the filter:

We can control the size of the filter to achieve the animation effect of the shadow, but it has the same problem as box-shadow, that is, changing its related value will trigger the continuous redrawing of the web page, which will affect the performance of the web page, especially on the mobile terminal, pay more attention to the performance problem, if there is nothing left, it will be blocked. It seems that this is not a very good method.

Solution 3:SVG filters

In SVG, it is also very convenient to use filters. The following code is a Gaussian blur filter in SVG to achieve a blur effect:

The < SVG version = "1.1" XMLNS = "http://www.w3.org/2000/svg" width = "112" height = "112" > <! -- Define the blur --> <defs> <filter id="blur-2px"> <feGaussianBlur in="SourceGraphic" stdDeviation="2" /> </filter> </defs> <! -- Make a rect that uses it --> <rect filter="url(#blur-2px)" stroke="none" fill="#000000" x="6" y="6" width="100" height="100"></rect> </svg>Copy the code

In gaussian fuzzy filter, stdDeviation is used to control the parameters of fuzzy degree, the larger the number, the more fuzzy.

The actual situation is as follows:

And it is easy to control the effect of blur, such as the degree of blur, by changing the relevant attributes of filter. If we directly increase the value of stdDeviation to change the degree of blur, we may get the following effect, the filter effect is clipped:

Here’s a description of what happened on the W3C website:

The bounds of this rectangle act as a hard clipping region for each filter primitive included with a given ‘filter’ element; thus, if the effect of a given filter primitive would extend beyond the bounds of the rectangle (this sometimes happens when using a ‘feGaussianBlur’ filter primitive with a very large ‘stdDeviation’), parts of the effect will get clipped. – SVG Filter Effects Spec

The main meaning is: refers to the effect area of the filter. These properties define the rectangular area on which the filter is applied. The filter effect will not apply to points beyond this area.

In the filter, the default values for x and y are -10%, and the default values for width and height are 120%. So if you set the blur level of the filter to more than 120% of the default area where the filter is applied, the effect will be cropped.

To avoid clipping, set x,y, width, and height values accordingly.

Another important parameter to set in the filter is the value of filterUnits of the filter. UserSpaceOnUse represents the user coordinate system that uses the element referencing the filter element. If not set, the default value is objectBoundingBox, indicating a range using the percentage of bounding boxes of elements referencing the filter element.

The clipping effect in the original author’s article is the result of not setting filterUnits to userSpaceOnUse, which will not clipping.

You can go here to see an example in action: Demo.

Here is the highlight of how to use a Gaussian blur filter to animate shadows.

border-image

We will use the border-image attribute to achieve the shadow effect. For details about the border-image, please go to here.

To implement the shadow effect, I will write an element named Shadow in HTML, with CSS as follows:

.shadow {
  position: absolute;
  width: calc(100% + 12px);
  height: calc(100% + 12px);
  left: -6px;
  top: -6px;
  opacity: 0.3;
  box-sizing: border-box;
  border-style: solid;
  border-width: 18px;
  border-image: url(images/shadow-2px.svg) 18 fill stretch;
}
Copy the code

A quick note on the code:

  • The location attribute of the element is set to absolute location, and the width and height of the element relative to the parent element is 100%. Of course, you also need to take into account the fuzzy value of the shadow, which is 12px, so use the calc attribute to calculate the true width and height of the element.
  • Use the border – box. This changes the way the box model is evaluated so that the width of the border is not calculated to the width of the element.
  • Set the border of the element to 18px and use the following border-image.

Here’s how the border-image fills the 18px border:

border-image: url(images/shadow-2px.svg) 18 fill stretch;
Copy the code
  • The first step is to import the url of the already made SVG image (images/shadow-2px.svg)
  • 18: border-width (px); border-width (px); border-width (px);
  • “Stretch” : used to set the layout mode of the border background image, similar to background-position, where “stretch” is stretch, “repeat” is repeat, “round” is tiling, and “stretch” is the default value.
  • Fill: “border-image-slice” specifies the top, right, bottom, and left inner offsets of the border image. There is no specific unit value, just give a simple number, of course, you can also set the value in percentage. The effect is to cut the border image into 9 areas: 4 corners, 4 sides, and a middle area, which is 9 cells. If the optional value of fill is not applied, the middle 9th cell is treated as transparent. So the fill property is used to specify that the middle portion of the image without borders be filled with a blurred image.

Conclusion under

Therefore, SVG and the border-image attribute are used to achieve the shadow effect, and some animation effects can be achieved by changing the relative values of the shadow elements, and the performance is very good. More importantly, the maintainability is not bad. You can easily change the size or color of shadows by editing SVG files.

Finally, let’s take a look at some shadow effects that can be used in this way:

The code can be viewed here.