css技巧收集-毛玻璃效果

其实毛玻璃的模糊效果技术上比较简单,只是用到了 css 滤镜(filter)中的 blur 属性。但是要做一个好的毛玻璃效果,需要注意很多细节。

比如我们需要将上图中页面中间的文字区域变成毛玻璃效果,首先想到的是给其设置一个透明度,并添加模糊滤镜:

article {
      background-color: rgba(0,0,0,0.3);
      -webkit-filter: blur(2px);
      -moz-filter: blur(2px);
      -ms-filter: blur(2px);
      -o-filter: blur(2px);
      filter: blur(2px);    
  }

可是生成的效果却是下面这样

从这个失败的例子我们得到两个结论:

  1. 对元素直接使用模糊会将其内容全部模糊掉,为了保证文字不会模糊掉需要多一个层单独应用模糊效果。

  2. 模糊效果并不会应用到其背后的元素上,所以需要使用 content 区域有和背景相同的背景图并进行模糊。

先解决第一个问题:

多一个层级的方法不通过添加元素,而通过伪元素。

article {
    z-index: 1;
}


article :after {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background-color: rgba(255,255,255,0.8);
        z-index: -1;
    }

这里有两点需要注意,由于伪元素不能通过 width:100% 和 height:100% 来继承宿主元素的尺寸,所以通过上述方式来继承 article 的尺寸;为了使伪元素位于 article 的下面这里给其设置 z-index:-1,为不使其隐藏到背景图的后面,这里给 article 设置 z-index:1;注意必须给article设置position:relative。
效果:

接下来给 article::after 设置相同的背景图。

如上图,即使我们设置了相同的 background-postion 与 background-size,中间部分的图和大背景还是没有拼接成功。

解决这个问题的方法很简单,只需要添加 background-attachment: fixed 属性,之后为其进行模糊处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
article{
background-position: center top;
background-size: cover;
}
article::after {
background-image: url(xxx.jpg);
background-position: center top;
background-size: cover;
background-attachment: fixed;
-webkit-filter: blur(20px);
-moz-filter: blur(20px);
-ms-filter: blur(20px);
-o-filter: blur(20px);
filter: blur(20px);
}

可以看到基本得到了我们想要的效果,美中不足的是在元素的边缘模糊的效果减弱了。为了解决这个问题,我们将伪元素的范围扩大一些,同时为了效果不超出 content 的范围,给其设置 overflow:hidden 属性。

article {
  overflow: hidden;
}
article::after {
  margin: -30px;
}

这样一个比较完美的毛玻璃效果就完成了,无论你如何改变浏览器窗口的尺寸,article 部分的背景图都能很好的与背景拼接,这都归功于 background-attachment 属性。
附上源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>css3毛玻璃效果</title>
<style>
body,html{
margin: 0;
padding: 0;
height: 100vh;
width: 100vw;
}
.content{
background: url(./img/timg1.jpg) no-repeat;
background-size: cover;
width: 100%;
height: 100%;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
}
article{
width: 60%;
background: rgba(255,255,255,.8);
border-radius: 10px;
box-shadow: 1px 4px 8px rgba(0,0,0,.4);
padding: 15px 25px;
box-sizing: border-box;
position: relative; /*宿主元素必须加relative ,否则伪元素会继承body的宽高*/
z-index: 1;
background-size: cover;
background-position: center top;
overflow: hidden;
}
article :after{
content: '';
position: absolute;
top:0;
left:0;
bottom:0;
right: 0; /*!* 定位这些是为了让伪类元素继承宿主元素的宽高 *!*/
z-index: -1;
background-color: rgba(255,255,255,.8);
border-radius: 10px;
background-image: url(./img/timg1.jpg);
background-size: cover;
background-position: center top;/* !*设置和宿主元素相同的背景位置,为了和背景进行拼接*!*/
background-attachment: fixed; /*!*背景图片相对于视口固定,就算元素有了滚动条,背景图也不随内容移动。伪元素的背景就和背景图片拼合了*!*/
margin-left: -30px; /*!*进行稍微的偏移*!*/
-webkit-filter: blur(12px); /*!*背景进行模糊处理效果*!*/
-moz-filter: blur(12px);
-ms-filter: blur(12px);
-o-filter: blur(12px);
filter: blur(12px);
}
article p{
width: 100%;
word-break: normal;
word-wrap: break-word;
line-height: 30px;
color: #000;
}
article h3{
text-align: center;
color: #000;
}
</style>
</head>
<body>
<div class="content">
<article>
<h3>Aestheticism</h3>
<p>To the world you may be one person, but to one person you may be the world.No man or woman is worth your tears, and the one who is, won't make you cry. Never frown, even when you are sad, because you never know who is falling in love with your smile. We met at the wrong time, but separated at the right time. The most urgent is to take the most beautiful scenery; the deepest wound was the most real emotions.Time would heal almost all wounds. If your wounds have not been healed up, please wait for a short while. </p>
</article>
</div>
</body>
</html>