css:position: fixed一定会按照视口进行定位吗?--包含块

185 阅读2分钟

一、固定定位

假如要想实现一个footer一直定位在页面底部,那么你肯定能想到fixed布局

image.png

实现这样的结构代码也非常简单:

<template>
  <div id="app">
    <div class="wrapper">
      <div v-for="n of 10" :key="n">{{ n }}</div>
      <div class="footer">footer</div>
    </div>
  </div>
</template>
<style lang="less" scoped>
#app {
  width: 100%;
  height: 100vh;
  overflow: auto;
  padding: 20px;
  box-sizing: border-box;
}
.wrapper {
  background-color: aliceblue;
  .footer {
    position: fixed;
    left: 0;
    bottom: 0;
    background-color: aqua;
    width: 100%;
    height: 50px;
    display: flex;
    align-items: center;
    justify-content: center;
  }
}
</style>

二、固定定位一定是你想象中的固定定位吗

有的时候我们会用到transform属性,例如transform: translateZ(0);用来启用GPU进行硬件加速,或者用来进行位移

现在,我们给wrapper元素设置上transform: translateZ(0);

效果就会变成这样:

image.png

这还是你想象中的固定定位吗?为什么footer不在页面最底下,反而跑到上面去了

所以说为什么有的代码当时是好好地,写着写着就会有各种奇怪的问题……

至此,回答下题目提出的问题,fixed不是一定按照视口进行定位的,它只是默认按照视口进行定位,它是可能会发生变化的,至于什么时候会变化,以及哪些属性会引起变化,我们再来探究

三、包含块

什么是包含块:

css中决定一个元素的尺寸和位置的上下文

一般情况下,包含块是最近一个position不为static的父级元素

例如:当给c设置绝对定位时,由于a和b都没有设置position属性,所以c的包含块依然是视口容器

image.png

当给b设置position属性(属性值不为static)时,c的包含块就变成了b,所以c就跑到b里面了

image.png

巧的是,当我们没有给b设置position: relative;而是设置了transform: translateZ(0);一样会使c跑到b里面,此时给c设置的position不是absolute而是fixed呢?结果是一样的

由这个案例可以知道一旦改变了某个属性的包含块,它的子级元素中设置的绝对定位或者固定定位会依赖这个包含块进行定位,哪些属性会生成包含块呢?

  1. transform的值不为none
  2. perspective的值不为none
  3. will-change的值为transform或perspective
  4. filter的值不为none,例如filter: blur(1px);
  5. backdrop-filter的值不为none,例如backdrop-filter: blur(10px);
  6. contain: paint;
  7. clip-path和mask设置也会影响到包含块,例如:mask: url('./1.jpg');

如果你觉得这篇文章对你有用,可以看看作者封装的库xtt-utils,里面封装了非常实用的js方法。如果你也是vue开发者,那更好了,除了常用的api,还有大量的基于element-ui组件库二次封装的使用方法和自定义指令等,帮你提升开发效率。不定期更新,欢迎交流~