CSS定位(层叠上下文)

400 阅读3分钟

前面花大力气介绍了布局,现在讲一讲CSS的定位。

定位是什么?

定位跟布局有啥关系?答案是没有关系,定位是指CSS在立体的角度的堆叠的情况,是垂直于屏幕的。
常常会有一个疑惑,CSS中,我给其中的一个div设置了它的background,给它的子元素设置了的background,请问这个时候两个元素的颜色谁为主? 于是,让我们来做实验推理到底哪个在前哪个在后面。

  • 首先我们分析出可能堆叠在一起的所有元素:
    • backgroud
    • border
    • block(块级元素)
    • float
    • inlink
    • inline-block
    • position

实验来证明

首先来看backgroundborder这两个的关系:

 html:
 	<div class="father">
       <div class="son"></div>
   </div>
css:
	.father{
           margin: 300px auto;
           background-color: red;
           height: 100px;
           width: 100px;
           border: 20px solid rgba(100%,100%,0%,1);
       }


证明border是在background上方的,为了加深印象,将boder改成border:20px solid rgba(100%,100%,0%,0.5)
明显的看到黄色被红色渲染的有了颜色。于是得到结论border的层级高于background 接着加上子元素,给子元素的加上样式如

.son{
            background-color: blue;
            height: 50px;
            width: 50px;
        }


看到子元素的背景色完全遮住了父元素的背景色,得到结论div的层级高于background 接着比较border和div的层级,给子元素加上如下css

.son{
            background-color: blue;
            height: 50px;
            width: 50px;
            margin-top: -10px;
        }

得到结论,块级的层级高于border
总结上述结论:background层级 < border层级 < 块级层级

加入float

设计再加一个float,让两个子元素比较

html:
<div class="father clearfix">
        <div class="sonFloat"></div>
        <div class="son"></div>
    </div>
 css:
.sonFloat{
            background-color: rgba(250, 190, 88, 0.8);
            height: 30px;
            width: 30px;
            float: left;
        } 	


此时float的元素设置了透明度为0.8的背景色,结果显示,float能盖住原先div的背景色,证明了块级的层级小于float

inline和inline-block

<div class="son"></div>中写几个字——我要上天,查看效果

证明内联的层级大于块级 对代码做如下改动

html:
+ <div class="father clearfix">
        <div class="sonInline"></div>
    </div>
css:
+ .sonInline{
            background-color: green;
            height: 40px;
            width: 40px;
            display: inline-block;
            margin-bottom: -30px;
        }


所以得出结论inline的层级大于inline-block的层级大于block的层级

position

代码再次做改动

.sonInline{
            background-color: orange;
            width: 100px;
            height: 100px;
            position: relative;
            top: 54px;
        }


看到连文字都被覆盖了,证明有position的元素的层级是最高的,无可争议!对同一层级的,元素的表现如何呢?各自做相应的实验,结果表明,遵循谁在下面谁就覆盖上面的原则

最后得出结论:background < border < div < float < inline-block < line < position

但是,但是,但是!这是正常情况,如果我给position的元素加一个z-index,情况就都变化了!重新写一个例子

html:
<div class="test">
        <div class="demo01">我是小毛</div>
        <div class="demo02">我是大毛</div>
    </div>
css:
.test{
            border: 1px solid red;
            height: 200px;
            width: 200px;
            margin: 300px auto;
            position: relative;
        }
        .demo01{
            background-color: yellow;
            height: 100px;
            width: 100px;
            position: absolute;
        }
        .demo02{
            width: 50px;
            height: 50px;
            background-color: blue;
            position: absolute;
        }


这一切看起来很正常,因为demo01和demo02都加了absoulte,那么此时后出现的排在前面,于是demo02放前面,因为内联仅仅小于position,于是html中内容我是大毛显示了出来。此时给demo01和demo02加一个z-index

.demo01{
+ z-index=1;
}
.demo01{
+ z-index=0;
}

此时,demo01的我是小毛出来了,而我是大毛却消失了,给一个透明度,发现就在demo01的下面,但是此时,css的排序方式并不符定位的规则!

所以这边还要加一个特殊的规则:层叠上下文

文档中的层叠上下文由满足以下任意一个条件的元素形成:

  • 文档根元素()
  • position的值为absolute(绝对定位)或relative(相对定位)且z-index的值不为auto(即z-index不为默认值)
  • position的值为fixed或sticky的元素
  • flex的子元素,且z-index不为auto
  • gird的子元素,且z-index不为auto
  • opacity的值不为1
  • 以下任意值不为none的元素:
    • transform
    • filter
    • perspective
    • clip-path 如果形成了层叠上下文,那么久去比较双方的z-index或者其他属性谁高,但是它的内部还是按照定位的规则排列。