使用 filter 置灰网站需要注意!

f7184fa3951c926e6e0644626ebe0bc9.png

最近在做一个置灰网站的需求,我跟大部分网站一样使用了 CSS 的 filter 滤镜功能,但是事情并没有原本的那么简单,如果使用不当,还会引发线上事故。

位置问题

代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <style>
    .container {
      /* filter: grayscale(1); */
      padding-top: 50px;
    }
    .box {
      position: fixed;
      left: 0;
      bottom: 0;
      width: 100%;
      height: 300px;
      background: pink;
    }
</style>
</head>
<body>
  <div class="container">
    <h1>hello</h1>
    <div class="box"></div>
  </div>
</body>
</html>

页面效果:红元素是相对于页面底部定位,设置了置灰样式,元素相对于父级定位了。

fb318fb99b75631934d12a0775b6ecfe.png

左边是正常网站,右边是置灰的网站,就因为加了一行CSS代码,导致我的样式错乱,严重影响页面的正常使用。

原因是:配置了 css filter 属性的元素,其子元素的 fixed 定位会失效。

为什么会这样?最后我在 MDN 上找到这样一段话:

fixed•元素会被移出正常文档流,并不为元素预留空间,而是通过指定元素相对于屏幕视口(viewport)的位置来指定元素位置。元素的位置在屏幕滚动时不会改变。打印时,元素会出现在的每页的固定位置。fixed 属性会创建新的层叠上下文。当元素祖先的 transformperspective 或 filter 属性非 none 时,容器由视口改为该祖先。

由于我上面的代码中,给类名为 container 元素加了 filter 属性,所以 box 元素的定位从视口改为了 container 元素。

【解决方案】

web 端:将 filter 设置在 html 上即可。小程序:需逐个元素排查,确保设置了 filter 的元素,不包含存在 fixed 定位的子元素。

层叠问题

代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <style>
    .box {
      position: fixed;
      left: 0;
      top: 0;
      width: 100%;
      height: 300px;
      background: pink;
    }
    .hello {
      filter: grayscale(1);
    }
</style>
</head>
<body>
  <div class="container">
    <div class="box"></div>
    <h1 class="hello">hello</h1>
  </div>
</body>
</html>

页面效果:红元素相对于页面顶部定位,设置了置灰样式,定位元素无法覆盖没定位的元素。

5094b5a39d3aacfae2e7118e4cebd040.png

预计的效果是定位的元素会覆盖下面类名为的 hello 的元素,但是由于我的 hello 元素使用了 CSS 的 filter 属性导致无法被定位的元素覆盖了。

原因是:配置了 css filter 属性的元素,z-index 会被提升,可能会覆盖掉其他有定位元素

所以上面代码中类名为 box 和 hello 的元素处于同一个层级中,所以后面的元素覆盖了前面的,要想不被覆盖,可以给定位的元素加上 z-index 值来解决。或者修改一下元素的先后顺序,把 box 放在 hello 的后面。

【解决方案】

注意调整 z-index 层级。