CSS fixed 定位元素失效的问题

一个示例

考察下面的代码:

  <head>
    <title>css filter issue</title>
    <style>
      body {
        height: 200vh;
        background: #ddd;
      }
      .container {
        background: grey;
        height: 200px;
      }
      .fixed {
        color: red;
        position: fixed;
        top: 0;
        right: 0;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="fixed">fixed item</div>
    </div>
  </body>

页面中有一个位于右上角 position: fixed 定位的元素。按照预期,在页面滚动时它将固定在那个位置。

正常的 fixed 元素其表现

正常的 fixed 元素其表现

现在对容器加应用 CSS filter 样式,

 .container {
+  filter: invert(1);
   background: grey;
   height: 200px;
 }

再观察结果,注意到 fixed 元素不再 fixed 了。

fixed 元素不再生效

fixed 元素不再生效

原因

根据 W3C 对 filter 的描述

A value other than none for the filter property results in the creation of a containing block for absolute and fixed positioned descendants unless the element it applies to is a document root element in the current browsing context. The list of functions are applied in the order provided.

对于指定了 filter 样式且值不为 none 时,被应用该样式的元素其子元素中如果有 positionabsolutefixed 的元素,会为这些元素创建一个新的容器,使得这些绝对或固定定位的元素其定位的基准相对于这个新创建的容器。

相同的情况对 transform 也适用,以下是 W3C 规范的描述

In the HTML namespace, any value other than none for the transform results in the creation of both a stacking context and a containing block. The object acts as a containing block for fixed positioned descendants.

解决

这里只看 filter 的修复。条件允许的情况下,有如下两种方式。

filter 应用到根节点

因为根据规范中对 filter 的描述,如果 filter 应用到根节点,则不会创建新的容器。所以可以将 filter 样式写到 html,如果条件允许的话。

html{
    filter: invert(1);
}

将  应用到根节点后的修复

将 `filter` 应用到根节点后的修复

filter 应用到非正常定位的元素上

对于 filter 样式,还可以将其只应用到出问题的这些非正常定位的元素身上来解决。

 .fixed {
+   filter: invert(1);
   color: red;
   position: fixed;
   top: 0;
   right: 0;
 }

将  应用到固定定位的元素本身身上

将 `filter` 应用到固定定位的元素本身身上

相关资源