【踩坑】子元素position:fixed失效问题

714 阅读1分钟

以下代码,父元素未设置transform,定位一切正常

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
        .outer {
            width: 100%;
            height: 50vh;
            background-color: #ccc;
        }
        .btn {
            width: 100px;
            height: 50px;
            position: fixed;
            bottom: 10px;
            left: 50%;
        }
    </style>
  </head>
  <body>
    <div class="outer">
      <button class="btn">fixed</button>
    </div>
  </body>
</html>

image.png

但当父元素设置了transform,定位就相对于父元素定位

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
        .outer {
            width: 100%;
            height: 50vh;
            background-color: #ccc;
            transform: scale(1);
        }
        .btn {
            width: 100px;
            height: 50px;
            position: fixed;
            bottom: 10px;
            left: 50%;
        }
    </style>
  </head>
  <body>
    <div class="outer">
      <button class="btn">fixed</button>
    </div>
  </body>
</html>

image.png

position:fixed具体解释

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

为什么设置了这些属性为非none后,定位会失效呢?

原来是当父元素设置了transformperspectivefilter 或 backdrop-filter 属性非 none 时,会创建一个新的坐标系,子元素会相对于该坐标系进行定位,而 position:fixed 是相对于浏览器窗口进行定位的,因此在该坐标系中子元素的位置无法固定在窗口中。因此,当元素祖先的 transformperspectivefilterbackdrop-filter 属性非 none 时,子元素的 position:fixed 会失效。