fixed失效,css堆叠上下文问题

简介: 我们直接用具体案例来体会css堆叠上下文,因为官方veurpess-reco1.x版本,当你开启右侧子菜单时,右侧的子菜单fixed就失效了。

css堆叠上下文不知道在你的业务中有没有遇到过,前段时间搭建vuepress1.0就遇到这样的一个类似的问题,主要是用了vuepress-reco这个主题,去官方提了一个issue[1],自己提的issue最后自己找到原因了,但是还是有小伙伴遇到同样的类似问题,今天一起探讨一下css堆叠上下文的问题


正文开始...


fixed失效了


我们直接用具体案例来体会css堆叠上下文,因为官方veurpess-reco1.x版本,当你开启右侧子菜单时,右侧的子菜单fixed就失效了。


我们具体写个例子分析下

<div id="app">
    <div class="wrap">
      <div class="subContent">我是fixed在最右侧</div>
      <div class="inner-content"></div>
    </div>
</div>

对应的css如下

* {
  padding: 0;
  margin: 0;
}
.wrap {
  height: 300px;
  border: 1px solid #111;
  margin: 10px;
  overflow-y: auto;
}
.subContent {
  position: fixed;
  right: 10px;
  top: 20px;
  background-color: red;
}

js中我生成了50条数据

function renderHtml() {
  const innerContent = document.getElementsByClassName("inner-content")[0];
  let str = "";
  let max = 50;
  for (let i = 0; i < max; i++) {
    str += `<p>${i}</p>`;
  }
  innerContent.innerHTML = str;
}
renderHtml();

e75f9856c8e154f1c93734584d6a595a.png

我给了.subContent的样式是fixed,fixed是相对整个body的,所以此时当你滚动内容时,会一直固定在最右侧


但是恰巧,此时遇上了一个问题fixed失效了,也正是一行css的原因导致的

.wrap {
    height: 300px;
    border: 1px solid #111;
    margin: 10px;
    overflow-y: auto;
    transform: translateY(0);
}

由于父级.wrap设置了transform导致子级subContentfixed失效了

ec3b26d85a4f5fc66acd31d9c14cda1f.png

fixed失效了,所以就是这个父级元素设置的transform: translateY(0)造成的

为了解决这个问题,我们重置了该样式,将其改成了transform:none,于是fixed就正常了,这也是在解决vuepress-reco1.x主题右侧子菜单fixed失效的原因。


什么样情况会造成fixed失效


除了父级设置transform不为none,还有filter不为none也会造成fixed失效

.wrap {
    height: 300px;
    border: 1px solid #111;
    margin: 10px;
    overflow-y: auto;
    transform: scale(0.5);
    /*filter: blur(1px)*/
  }


堆叠上下文


参考张鑫旭老师的一篇博文深入理解CSS中的层叠上下文和层叠顺序[2],参照张鑫旭老师的一张图,大概就是这样

c98d3f52be7a99a444a12acbf5acce00.png

就是我们看到网页上显示是二维的,实际上还有三维,就是一个类似控制transform:translateZ的一个概念


我们知道在网页中所有可见元素都是由标签组成,所有标签的排列布局其实是由一个经典的概念构成块级格式上下文也俗称BFC,所以整个网页的布局是由BFC这样的特性而构建我们的网页


看一个例子

<div class="wrap2">
    <div class="leavel-1">leavel-1</div>
    <div class="leavel-2">leavel-2</div>
  </div>

.wrap2 {
  margin: 10px;
}
.leavel-2,.leavel-1 {
  width: 100px;
  height: 100px;
}
.leavel-1 {
    background-color: red;
}
.leavel-2 {
    background-color: green;
}

就会下面这样

031e2a1b638127c065a44a730347df46.png

正常情况参照BFC特性,两个块级元素就是这样独占一行的排列了,但是如果我给两个元素设置浮动

.leavel-1, .leavel-2 {
  float: left;
}

此时发现就会像下面这样

ed5457c69a1bf000741870345bd8d3b9.png

然后我再设置.leavel-2margin-left: -100px,你就会发现leavel-1被挡住了

1db6843485ae4cc95a4f579cd489627e.png

初学者可能会好奇,也很容易想到,这leavel-1去哪里了,实际上是在leavel-2的下级,我们把leavel-2的宽度调整一下

e551f17020c730be186126cbd8ad6e5f.png

隐藏出来的.leavel-1就显示出来了


所以你现在明白了层叠上下文了哈,简单的说,网页的所有元素可以像盖棉被一样,一层一层的往上盖,最新的叠在最上面


我们思考下,从浏览器默认的BFC结构到我们想要看到的堆叠上下文的效果,这中间我们主要做了哪些事情


1、设置了浮动【破坏了文档流】

2、设置.leavel-2的外边距margin-left:-100px【改变了元素的默认排列位置】


所以产生堆叠上下文,必须满足两个条件,一个是元素文档流被破坏,二是元素位置发生变化


定位产生堆叠上下文


其实除了这浮动+margin方式,我们还可以用定位去产生堆叠上下文,但实际上也是满足这两个基本的条件


但是如果是用定位,那么有个z-index这个属性是可以影响层叠上下文的顺序的,z-index越小,排得越下面


transform产生堆叠上下文


我们发现浮动+marginposition能产生上下文,除了这两个,新增的css3最新特性中还有transform也可以产生堆叠上下文


因此我们可以这么做

.leavel-2,
.leavel-1 {
  width: 100px;
  height: 100px;
}
.wrap2 {
  margin: 10px;
}
.leavel-1 {
  background: red;
}
.leavel-2 {
  background-color: green;
  transform: translateY(-100px);
}

639baf86eaf07d8d778e316b42d708ac.png

我们会发现此时leavel-2就把leavel-1完全盖住,因此transform也可以产生堆叠上下文,但实际上这个特性并不是像前面两个一样,并不会破坏文档流,所以这是一个例外,他只是改变自身位置,从而形成了堆叠上下文


堆叠优先级问题


我们看到元素,优先级行内元素是不是最高,比如元素的内容文字,永远在最顶层,然后就是背景,然后就是z-index设置的可见元素


当一个元素同时设置定位transform,影响层叠上下文是怎么样

133651ebf01621614b86c79f3e6383ca.png

我们看到fixed会比transform的优先级更高,如果去掉transform,就是贴着body排的

02711330c13563f65fb85f685d3351a7.png


所以这就证明,浏览器在处理层叠上下文优先级时,先执行定位,然后再执行transfrom,这只是作用在同一个元素上


回到我们刚开始的问题上,如果是作用在不同的两个父子级元素上呢

我们文章开头,就是这样的一个例子


父级元素设置了transform: translateY(0)


然后他的子级上设置了一个fixed,于是怪异的问题就发生了,fixed失效了


页面结构大概就是这样

<div class="wrap">
    <div class="subContent">我是fixed在最右侧</div>
    <div class="inner-content"></div>
 </div>

对应的css如下

.wrap {
      height: 300px;
      border: 1px solid #111;
      margin: 10px;
      overflow-y: auto;
      transform: translateY(0);
      /*filter: blur(1px)*/
    }
  .subContent {
    position: fixed;
    right: 10px;
    top: 20px;
    background-color: red;
  }

那为什么会出现这样的情况?我们画个图理解下

8e379e2ea466becfd9485e74058199e2.png

本质上transform:translate(0,0)(10px,-10px)没有差别,图中这么画只是为了更好理解,因此我代码中设置的是translateY(0),所以其实是Y轴方向上往上偏移而已,但是这不影响我们理解这其中的本质。


因为外层父元素设置了transfrom产生了堆叠上下文,而它子元素又想逃脱出去,儿子想造反给自己设置fixed产生一个堆叠上下文,对不起,你必须听老子的,所以子元素设置的fixed就失效了,你还是得跟着老子走


如果你不想因为父级元素transform设置,你想单飞呢,你可以怎么做呢?


唯一的办法,另起炉灶....


因此你可以这么做

<div id="app">
      <div class="subContent">我是fixed在最右侧</div>
      <div class="wrap">
        <div class="inner-content"></div>
      </div>
</div>

028e5af251445cb339b068f4f999309e.png

没错,你看到的就是,子级元素已经挣脱束缚了,所以我不受被包裹元素tranform的影响了。


不知道你注意到没,其实filter也是和transform一样会产生堆叠上下文,如果子元素被包裹,父级元素设置filter,那么子级元素的fixed也会失效

37bdffb997cbdf76e3b18bc897db3ee4.png

是不是很惊讶,总之,一句话,父级如果产生了堆叠上下文,子级想要挣脱,对不起,必须听老子的,除非你另起炉子


好了,终于理清这个堆叠上下文的问题了,所以平时遇到那些奇怪的问题,试来试去,原来是一个css属性设置的原因造成的。


另外思考一个问题,当一个块级子级元素设置width:100%与不设置width,当我们对该元素设置margin时,此时会发生什么?元素本身的宽度是怎么样的,这是一个我们经常遇到的一个问题,想清楚了,貌似你会对margin的作用会有更深的认识。


总结


  • fixed失效的原因,主要是由于产生堆叠上下文造成的
  • 理解堆叠上下文,什么条件会形成堆叠上下文
  • 形成堆叠上下文主要由以下几种
  • 文档流破坏:float+margin,定位postion
  • css新特性:transformfilter会产生堆叠上下文
  • 同一个元素同时使用poistiontransform哪个优先级更高权重更大,首先是会执行定位,然后再执行transform,因此定位的优先级更高,先执行,但是transform权重更大,会作用在定位之上
  • 不同元素产生的堆叠上下文对子级元素造成的影响,如果一个父级产生堆叠上下文,那么它所有的子级元素都不会脱离父级,子元素设置的fixed会失效
  • 最后安利张鑫旭老师的博文,文章很多思考来自深入理解CSS中的层叠上下文和层叠顺序这篇文章
  • 本文示例源码code example[3]
相关文章
|
7月前
|
前端开发 定位技术 开发者
CSS基础-定位:static, relative, absolute, fixed
【6月更文挑战第10天】本文探讨了CSS四种定位方式:static、relative、absolute和fixed,强调理解它们的差异对前端开发者的重要性。static遵循正常文档流,relative通过偏移量调整位置但不脱离文档流,absolute完全脱离文档流并依附于最近的非static祖先元素,fixed则相对于浏览器窗口固定。文章列举了常见问题及避免策略,并提供了实战代码示例以直观展示四种定位的效果。掌握这些定位技术能提升布局效率和页面设计质量。
55 1
|
6月前
|
前端开发 容器
CSS【详解】定位 position (静态定位 static -- 文档流排布 、相对定位 relative、绝对定位 absolute、固定定位 fixed、黏性定位 sticky)
CSS【详解】定位 position (静态定位 static -- 文档流排布 、相对定位 relative、绝对定位 absolute、固定定位 fixed、黏性定位 sticky)
175 0
|
前端开发 容器
CSS:BFC(Block Formatting Context 块级格式化上下文)
CSS:BFC(Block Formatting Context 块级格式化上下文)
89 0
|
前端开发 容器
前端CSS理解 —— BFC(块级格式化上下文)
前端CSS理解 —— BFC(块级格式化上下文)
80 0
|
前端开发 容器
【CSS】定位属性position使用详解(static、relative、fixed、absolute)
css定位属性position:static、relative、fixed、absolute详细介绍及使用样例。
154 0
|
前端开发
【CSS】有意思的BFC:Block Formatting Context(块格式化上下文)!🤡
前言 大家好,我是HoMeTown,今天想聊一聊CSS中的BFC,很多朋友应该都听过这个名词,搞懂BFC可以让我们理解CSS中一些很诡异的地方,话不多说,直奔主题!
62 0
|
前端开发
css calc()的使用,以及失效原因
css calc()的使用,以及失效原因
|
前端开发
|
前端开发
CSS 文档中定位指南:static、relative、absolute、fixed、sticky
CSS 中 position 属性用于指定元素的定位方法的类型(static、relative、absolute、fixed、sticky)。
148 0
CSS 文档中定位指南:static、relative、absolute、fixed、sticky
|
前端开发 JavaScript 算法
使用z-index,必须要知道CSS层叠上下文!
前言 目前前端大环境下,很多人越来越不注重学习 CSS 了,觉得太简单!但是事实并非如此,CSS 的复杂程度其实一点不亚于 JavaScript,只是你没深入了解才会觉得简单。 不知道你有没有遇到过这样的布局问题:我明明设置了 z-index,怎么没起作用?我设置了元素定位,最终效果怎么和我想象得不一样? 如果你遇到了上面得问题,说明你对 CSS 了解得还不够深入。上面问题的出现,都与 CSS 层叠上下文相关,所以今天我们决定彻底将 CSS 层叠上下文搞明白!
456 0
使用z-index,必须要知道CSS层叠上下文!

热门文章

最新文章