如何实现CSS玻璃/模糊效果用于叠加层?

190

我在尝试为一个半透明的覆盖层添加模糊效果时遇到了问题。我想要让该层后面的所有内容都模糊,就像这样:

SFW image

这是一个无法工作的 jsfiddle 示例:http://jsfiddle.net/u2y2091z/

有什么办法可以使此方法可行吗?我希望保持尽可能简单,并且支持跨浏览器。以下是我使用的 CSS:

#overlay {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;

    background:black;
    background:rgba(0,0,0,0.8);

    filter:blur(4px);
    -o-filter:blur(4px);
    -ms-filter:blur(4px);
    -moz-filter:blur(4px);
    -webkit-filter:blur(4px);
}

2
也许可以将该div设置为不透明,但使用伪元素作为其背景并独立进行模糊处理,以显示图像。 - bjb568
1
@chipChocolate.py CSS过滤器在默认情况下已经被FF35+支持。但是我同意你的观点,作为开发人员,我们不应该依赖它,因为它不是跨浏览器功能。 - Hashem Qolami
4
CSS滤镜现在已被大多数主流浏览器支持。 - Eric Reed
13个回答

239

更简单且更实时的答案:

backdrop-filter: blur(6px);

请注意,浏览器支持并不完美,但在大多数情况下,模糊效果并非必要。


26
注意,截至2021年2月1日,当前没有任何版本的Firefox支持此功能。 - KyleFarris
2
Firefox在技术上支持它,但它是一个禁用的标志,您可以在about:config中启用它。 - Maxim
使用 position:fixed 的 div 叠加的示例:https://jsfiddle.net/hfjqa6ns/ - freedomn-m
7
注意,截至2022年9月8日,FireFox自7月份起已经支持了这个属性:D,全球接受率达到了94% https://caniuse.com/css-backdrop-filter - Djave

76
这是一个使用svg过滤器的示例。使用svg元素,高度与#overlay相同,并在其上应用feGaussianblur过滤器。该过滤器应用于svgimage元素上。要使其具有凸起效果,可以在叠加层底部使用box-shadow。了解svg过滤器的浏览器支持情况,请参见此处。查看代码演示请点击这里

body {
  background: #222222;
}
#container {
  position: relative;
  width: 450px;
  margin: 0 auto;
}
img {
  height: 300px;
}
#overlay {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  z-index: 1;
  color: rgba(130, 130, 130, 0.5);
  font-size: 50px;
  text-align: center;
  line-height: 100px;
  box-shadow: 0 3px 5px rgba(0, 0, 0, 0.3);
}
<div id="container">
  <img src="http://lorempixel.com/450/300/sports" />
  <div id="overlay">WET</div>
  <svg width="450" height="100" viewBox="0 0 450 100" style="position: absolute; top: 0;">
    <defs>
      <filter id="blur">
        <feGaussianBlur in="SourceGraphic" stdDeviation="3" />
      </filter>
    </defs>
    <image filter="url(#blur)" xlink:href="http://lorempixel.com/450/300/sports" x="0" y="0" height="300px" width="450px" />
  </svg>
</div>


65
我能够从这里每个人和进一步的谷歌搜索中整合信息,并得出以下在Chrome和Firefox中有效的解决方案:http://jsfiddle.net/xtbmpcsu/。我仍在努力使其在IE和Opera中工作。
关键是将内容放置在应用筛选器的div内部:

body {
    background: #300000;
    background: linear-gradient(45deg, #300000, #000000, #300000, #000000);
    color: white;
}
#mask {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    background-color: black;
    opacity: 0.5;
}
img {
    filter: blur(10px);
    -webkit-filter: blur(10px);
    -moz-filter: blur(10px);
  -o-filter: blur(10px);
  -ms-filter: blur(10px);
    position: absolute;
    left: 100px;
    top: 100px;
    height: 300px;
    width: auto;
}
<div id="mask">
    <p>Lorem ipsum ...</p>
    <img src="http://www.byui.edu/images/agriculture-life-sciences/flower.jpg" />
</div>

因此,蒙版已应用滤镜。同时,注意在值中使用 <svg> 标签的筛选器时,使用了 url() -- 这个想法来自于 http://codepen.io/AmeliaBR/pen/xGuBr。如果您压缩 CSS,则可能需要将 SVG 筛选标记中的任何空格替换为 "%20"。

现在,蒙版 div 中的所有内容都被模糊处理。


它非常聪明。 - Jamaluddin Rumi
3
Chrome不支持最终的 filter: url(...,移除该部分后,Chrome将能够成功使用 filter: blur(10px); - Doug S
2
我是否误解了?这不是OP想要的。文本不应该模糊。 - Eric
4
@Eric,你显然误解了,因为回答者就是 OP(原帖作者)。 - tao

26
background: rgba(255,255,255,0.5);
backdrop-filter: blur(5px);

不要再给你的内容添加另一个模糊背景,可以使用backdrop-filter。请注意IE 11和Firefox可能不支持它。查看caniuse

演示:

header {
  position: fixed;
  width: 100%;
  padding: 10px;
  background: rgba(255,255,255,0.5);
  backdrop-filter: blur(5px);
}
body {
  margin: 0;
}
<header>
  Header
</header>
<div>
  <img src="https://dummyimage.com/600x400/000/fff" />
  <img src="https://dummyimage.com/600x400/000/fff" />
  <img src="https://dummyimage.com/600x400/000/fff" />
</div>


相同的解决方案已经被提出: https://dev59.com/7V4c5IYBdhLWcg3wvsbB#58083568 - Kaiido
有没有一种类似的方法可以用于内联SVG呢? - 71GA
1
@71GA 请查看此链接 https://www.sitepoint.com/design-tricks-with-svg-filters-a-masked-blur-effect/ - Allen Wong

15

如果你今天正在寻找一个可靠的跨浏览器方法,你不会找到一个很好的选择。你最好的选择是创建两个图像(在一些环境中可以自动化),并安排它们以便其中一个覆盖另一个。我在下面创建了一个简单的示例:

<figure class="js">
    <img src="http://i.imgur.com/3oenmve.png" />
    <img src="http://i.imgur.com/3oenmve.png?1" class="blur" />
</figure>
figure.js {
    position: relative;
    width: 250px; height: 250px;
}

figure.js .blur {
    top: 0; left: 0;
    position: absolute;
    clip: rect( 0, 250px, 125px, 0 );
}

虽然这种方法是有效的,但并不一定是理想的。话虽如此,它确实产生了期望的结果

输入图像描述


10

这里提供一种可能的解决方案。

HTML

<img id="source" src="http://www.byui.edu/images/agriculture-life-sciences/flower.jpg" />

<div id="crop">
    <img id="overlay" src="http://www.byui.edu/images/agriculture-life-sciences/flower.jpg" />
</div>

CSS

#crop {
    overflow: hidden;

    position: absolute;
    left: 100px;
    top: 100px;

    width: 450px;
    height: 150px;
}

#overlay {
    -webkit-filter:blur(4px);
    filter:blur(4px);

    width: 450px;
}

#source {
    height: 300px;
    width: auto;
    position: absolute;
    left: 100px;
    top: 100px;
}

我知道CSS可以简化,而且你可能应该摆脱id。这里的想法是使用一个div作为裁剪容器,然后在图像的副本上应用模糊效果。 Fiddle

如果想要在Firefox中实现这个效果,你需要使用SVG hack


@chipChocolate.py 我猜你需要在这种情况下使用SVG hack,http://demosthenes.info/blog/534/Crossbrowser-Image-Blur。 - Juho Vepsäläinen
请注意,对于CSS过滤器,您可以忽略除“-webkit-”以外的供应商前缀,因为它在这些浏览器中未实现。最好将标准声明放在末尾-在所有前缀版本之后。 - Hashem Qolami
@HashemQolami完成了。谢谢。 - Juho Vepsäläinen
FF没问题,现在是(54.0.1 (32位))。非常完美!谢谢! - Pedro Ferreira

9

来源自 backdrop-filter

...可以将图形效果(如模糊或变色)应用于元素后面的区域。因为它应用于元素后面的所有内容,所以要看到效果,必须使元素或其背景至少部分透明。


请考虑过滤器的兼容性,因为它目前无法与Firefox桌面版和Android版本一起使用。 - askepott

5
这将在内容上添加模糊叠加效果:
.blur {
  display: block;
  bottom: 0;
  left: 0;
  position: fixed;
  right: 0;
  top: 0;
  -webkit-backdrop-filter: blur(15px);
  backdrop-filter: blur(15px);
  background-color: rgba(0, 0, 0, 0.5);
}

4

#bg, #search-bg {
  background-image: url('https://images.pexels.com/photos/719609/pexels-photo-719609.jpeg?w=940&h=650&auto=compress&cs=tinysrgb');
  background-repeat: no-repeat;
  background-size: 1080px auto;
}

#bg {
  background-position: center top;
  padding: 70px 90px 120px 90px;
}

#search-container {
  position: relative;
}

#search-bg {
  /* Absolutely position it, but stretch it to all four corners, then put it just behind #search's z-index */
  position: absolute;
  top: 0px;
  right: 0px;
  bottom: 0px;
  left: 0px;
  z-index: 99;

  /* Pull the background 70px higher to the same place as #bg's */
  background-position: center -70px;

  -webkit-filter: blur(10px);
  filter: url('/media/blur.svg#blur');
  filter: blur(10px);
}

#search {
  /* Put this on top of the blurred layer */
  position: relative;
  z-index: 100;
  padding: 20px;
  background: rgb(34,34,34); /* for IE */
  background: rgba(34,34,34,0.75);
}

@media (max-width: 600px ) {
  #bg { padding: 10px; }
  #search-bg { background-position: center -10px; }
}

#search h2, #search h5, #search h5 a { text-align: center; color: #fefefe; font-weight: normal; }
#search h2 { margin-bottom: 50px }
#search h5 { margin-top: 70px }
<div id="bg">
  <div id="search-container">
    <div id="search-bg"></div>
    <div id="search">
      <h2>Awesome</h2>
      <h5><a href="#">How it works »</a></h5>
    </div>
  </div>
</div>


2
我想出了这个解决方案。

点击查看模糊效果的图片

这是一种技巧,使用绝对定位的子div,将其背景图像设置为与父div相同,并结合在父元素上设置的相同background属性和background-attachment:fixed CSS属性。
然后,在子
上应用filter:blur(10px)(或任何值)。

*{
    margin:0;
    padding:0;
    box-sizing: border-box;
}
.background{
    position: relative;
    width:100%;
    height:100vh;
    background-image:url('https://images.unsplash.com/photo-1547937414-009abc449011?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80');
    background-size:cover;
    background-position: center;
    background-repeat:no-repeat;
}

.blur{
    position: absolute;
    top:0;
    left:0;
    width:50%;
    height:100%;
    background-image:url('https://images.unsplash.com/photo-1547937414-009abc449011?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80');
    background-position: center;
    background-repeat: no-repeat;
    background-attachment: fixed;
    background-size:cover;
    filter:blur(10px);
    transition:filter .5s ease;
    backface-visibility: hidden;
}

.background:hover .blur{
    filter:blur(0);
}
.text{
    display: inline-block;
    font-family: sans-serif;
    color:white;
    font-weight: 600;
    text-align: center;
    position: relative;
    left:25%;
    top:50%;
    transform:translate(-50%,-50%);
}
<head>
    <title>Blurry Effect</title>
</head>
<body>
    <div class="background">
        <div class="blur"></div>
        <h1 class="text">This is the <br>blurry side</h1>
    </div>
</body>

在CodePen上查看


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接