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-filter
need
.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")
}
效果如下
而且由于尺寸是动态的,换个书名也能完美适应
最后再来对比一下,下面哪个一眼看上去效果最好?
完整代码可以查看以下任意链接