深入理解css 笔记(7)
前面讲了几种控制网页布局的方式,flex,gird 和 float。这下我们初略讲下 position.这个我日常中用到的已经挺多了。定位和其他控制文档流的行为不同。它将元素彻底从文档流中移走,它允许你将元素放在屏幕的任意位置。还可以将一个元素放在另一个元素的前面或后面,彼此重叠。
浏览器将 html 解析为 dom 的同时还创建了另一个树形结构,叫做渲染树。它代表了每个元素的视觉样式和位置。同时还决定浏览器绘制元素的顺序。顺序很重要,因为如果元素刚好重叠,后绘制的元素就会出现在先绘制的元素前面。通常情况下。元素在 html 里出现的顺序决定了绘制的顺序。定位元素时,这种行为会改变。浏览器会先绘制所有非定位的元素,然后绘制定位元素。
默认情况下,所有的定位元素会出现在非定位元素前面。z-index 属性的值可以是任意整数正负都行。拥有较高 z-index 的元素出现在拥有较低 z-index 的元素前面。拥有负数 z-index 的元素会出现在静态元素后面。使用 z-index 是解决网页叠层问题的第二个方法。z-index 的行为很好理解,但是使用它时要注意两个小陷阱。第一,z-index 只在定位元素上生效,不能用它控制静态元素。第二,给一个定位元素加上 z-index 可以创建层叠上下文。
一个层叠上下文包含一个元素或者由浏览器一起绘制的一组元素。其中一个元素会作为层叠上下文的根,比如给一个定位元素加上 z-index 的时候,它就变成了一个新的层叠上下文的根。所有后代元素就是这个层叠上下文的一部分。将层叠上下文里所有元素一起绘制会造成严重的后果:层叠上下文之外的元素无法放在层叠上下文内的两个元素之间。举个例子:
<!DOCTYPE html>
<html lang="cn" class="has-bottombar">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
name="viewport"
/>
<style>
body {
margin: 40px;
}
.box {
display: inline-block;
width: 200px;
line-height: 200px;
text-align: 200px;
border: 2px solid black;
background-color: #ea5;
margin-left: -60px;
vertical-align: top;
}
.one {
margin-left: 0;
}
.two {
margin-top: 30px;
}
.three {
margin-top: 60px;
}
.positioned {
position: relative;
background-color: #5ae;
z-index: 1;
}
.absolute {
position: absolute;
top: 1em;
right: 1em;
height: 2em;
background-color: #fff;
border: 2px dashed #888;
z-index: 100;
line-height: initial;
padding: 1em;
}
</style>
</head>
<body>
<div class="box one positioned">
one
<div class="absolute">nested</div>
</div>
<div class="box two positioned">tow</div>
<div class="box three">three</div>
<script></script>
</body>
</html>
这个代码包含了三个盒子,其中两个被定位,并且z-index为1,第一个盒子里有一个绝对定位的元素,它的z-index为100,虽然第一个盒子的z-index很高,但还是出现在第二个盒子后面,因为它的父元素,即第一个盒子形成的层叠上下文在第二个盒子后面。叠放在第二个盒子后面的第一个盒子是一个层叠上下文的根。因此,虽然它的z-index值很高,但它内部的绝对定位元素不会跑到第二个盒子前面。
给一个定位元素加上z-index是创建层叠上下文最主要的方式,但有些属性也会创建,比如小于1的opacity属性,还有transform,filter属性。由于这些属性主要会影响元素及其子元素渲染的方式,因此一起绘制父子元素。
如果不根据组件的优先级定义清晰的层叠顺序,那么一个样式表很容易演变成一场z-index大战。如果没有清晰的说明,开发人员在一个模态框之类的元素添加样式时,为了不被其他元素遮挡,就会设置一个高的离谱的z-index.这种事情重复几次后,大家就只能凭感觉给一个新的组件设置z-index.所以我们最好建立一个自定义属性文件,就能很方便的处理这个问题。将增量设为100,10,这样就可以在需要的时候往中间插入新值。
如果发现z-index没有按照预期表现,就在dom树里往上找到元素的祖先节点,直到发现层叠上下文的根,然后给它设置z-index.