Record--How does CSS achieve feathering effect?

Here I will share with you some of the knowledge I have summarized on the Internet, I hope it will be helpful to everyone

Recently, I encountered such a problem. If the title of a book is displayed directly on a cover, there may be a situation where the title of the book is not clear (easy to be disturbed by the background), as follows

In order to solve this problem, the designer proposed an "extreme" solution, which is to blur the picture behind the title of the book. This is very easy to achieve in CSS, just backdrop-filterneed

.name{
  backdrop-filter: blur(10px);
}

Of course, the blur is now blurred, but the edges are too "faulted", causing the title and cover of the book to be "out of place". The effect is as follows

If you can feather the edge and blur the edge effect, you can blend the title of the book into the background well.

Feathering is a photoshop term. The principle of feathering is to blur the connection between the inside and outside of the selected area, and play the role of gradient to achieve the effect of natural connection. It is an important tool for processing pictures in PS and other versions

This is the effect after the final feathering of the design, which can not only ensure that the text is clearly visible, but also avoid being too abrupt, as follows

It is very simple for designers to achieve this, just wipe it with an eraser, so what about CSS? Let's explore how CSS achieves the feathering effect.

1. The principle of feathering

Feathering is actually blurring the edges. In CSS, it is actually creating a mask with blurred edges , which requires a semi-transparent gradient.

Regarding the mask, here is a brief introduction. The basic syntax is very simple, which is basically the same as the background syntax.

.content{
  -webkit-mask: '遮罩图片' ;
}
/*完整语法*/
.content{
  -webkit-mask: '遮罩图片' [position] / [size] ;
}

The mask image here is basically used in the same way as the background. It can be a PNG image, an SVG image, or a gradient-drawn image. It also supports multi-image overlay.

The principle of masking is very simple, the final effect only shows the opaque part, the transparent part will be invisible, translucent and so on

Let’s take an example of a circle first, which is relatively simple because it can be created directly through radial gradients

For example, there is an avatar below, and it is very abrupt to place it directly on the background

We can draw this avatar a mask from opaque to transparent through a radial gradient to achieve the effect of blending with the background

.head{
  -webkit-mask: radial-gradient(closest-side circle,#000 60%, transparent 100%);
}

The principle is this

The final effect is as follows

Of course this is circular, what if it is rectangular?

2. The feathering principle of the rectangle

根据上面的分析,如果希望羽化矩形边缘,需要创建这一个遮罩

那么问题来了,如何创建这一个边缘模糊的矩形呢?貌似没办法直接通过渐变来实现,而且还需要是尺寸自适应的(自动跟随容器尺寸)

如果单纯看这样一个矩形,还是很容易实现的,通过box-shadow即可实现

.shadow{
  width: 200px;
  height: 200px;
 	background:black;
  border-radius:10px;
  box-shadow:0 0 5px black, 0 0 10px black, 0 0 15px black
}

根据需求,可以多叠加几层box-shadow,这里叠加了3层,效果如下

但是问题又来了,这样一个 dom 无法直接用作mask-image,那如何处理呢?

三、通过 SVG foreignObject 转换成图片

上面提到,通过 CSS 阴影可以很轻松的实现我们说需要的效果,但可惜现在还是 dom 阶段,所以需要将这个 dom 转换成图像。

在这里,需要借助 SVG 中的foreignObject元素,通过这个元素,可以将 HTML嵌入到SVG中,轻松实现 dom 转图片的效果

有兴趣的可以参考之前这几篇文章

  • CSS、SVG、Canvas对特殊字体的绘制与导出
  • CSS & SVG foreignObject 实现文字镂空波浪动画

原理如下

回到这里,我们仅需要将上面的结果放到foreignObject元素中,由于需要自适应尺寸,这里的body宽高都是100%,如下

<svg xmlns="http://www.w3.org/2000/svg">
  <foreignObject width="100%" height="100%">
    <body class="wrap" xmlns="http://www.w3.org/1999/xhtml">
      <style>
        .wrap{
          box-sizing: border-box;
          margin: 0;
          height: 100%;
          padding: 10px;
        }
        .shadow{
          height: 100%;
          background:black;
          border-radius:10px;
          box-shadow:0 0 5px black, 0 0 10px black, 0 0 15px black
        }
      </style>
      <div class="shadow"></div>
    </body>
  </foreignObject>
</svg>

这样就得到了一个宽高自适应的SVG图像,无论宽高怎么变化,都是撑满的

别看这么多标签,这其实已经是一张图片,可以直接使用,接下来看看如何运用

四、矩形的羽化

其实上面得到的 SVG可以直接当成一个图片资源,正常使用了,就像这样

.name{
  -webkit-mask: url('./fearher.svg')
}

不过,也可以将这个SVG图片转换成内联形式,减少资源依赖,转换后仍然保持自适应特性

这里推荐张鑫旭老师的SVG在线压缩合并工具

转换后就是这个样子

.name{
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3CforeignObject width='100%25' height='100%25'%3E%3Cbody class='wrap' xmlns='http://www.w3.org/1999/xhtml'%3E%3Cstyle%3E.wrap%7Bbox-sizing:border-box;margin:0;height:100%25;padding:10px%7D.shadow%7Bheight:100%25;background:%23000;border-radius:10px;box-shadow:0 0 5px %23000,0 0 10px %23000,0 0 15px %23000%7D%3C/style%3E%3Cdiv class='shadow'/%3E%3C/body%3E%3C/foreignObject%3E%3C/svg%3E")
}

效果如下

Kapture 2022-12-10 at 18.23.20

而且由于尺寸是动态的,换个书名也能完美适应

image-20221210221842455

最后再来对比一下,下面哪个一眼看上去效果最好

image-20221210183113086

完整代码可以查看以下任意链接

本文转载于:

https://juejin.cn/post/7176094306124431421

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 

Guess you like

Origin blog.csdn.net/qq_40716795/article/details/129906291