此文绝对定位部分优有点复杂,学习此文之前可以先看看这篇文章:
https://blog.youkuaiyun.com/androidioskl/article/details/123292769
此文参考于: w3c文档:
https://www.w3.org/TR/CSS2/visudet.html#abs-non-replaced-width
定位的简介
通过定位可以将元素摆放到页面的任意位置,手动控制元素在包含块中的精准位置,通过position属性可设置定位类型。
position属性
表示定位的方式。
值:
- 默认值:static,元素是静止的(不定位,该浮动的浮动该是常规流的是常规流)
- relative:相对定位
- absolute:绝对定位
- fixed:固定定位
- sticky:粘滞定位
一个元素,只要position的取值不是static,认为该元素是一个定位元素.
偏移属性
此属性配合position使用,用来设置偏移量
定位位置: 表示参考元素,可能是自身的边,可能是带有定位元素的元素的边。
left:定位元素左外边距边界相对于参考元素左边缘的进行偏移。
right:定位元素边距边界相相对于参考元素右边缘进行偏移。
top:定位元素上外边距边界相对于参考元素顶端进行偏移。
bottom:定位元素下外边距边界相对于参考元素底端进行偏移。
ps: 负值相反。
相对定位:
特点:
- 参考物是自身位置,相对于自身的位置进行偏移。
.a{
width:100px;
height:100px;
background:red;
position:relative;
left:100px;
}
<div class="a"></div>
注:这里设置的是红色div元素相当于原来文档流位置的左边缘偏移100px
-
不会改变元素的性质(该元素原来是浮动元素它还是浮动元素),
-
不会导致元素脱离文档流,盒子偏移不会对其它盒子造成影响(只是视觉效果上产生偏差,实际上这个盒子以前在还在哪,元素自身仍然占据原来的位置(灵魂脱壳)。
<div style="background: red;
position: relative;
left: 100px;
width: 100px;
height: 100px;"></div>
<div style="background: yellow; width: 100px; height: 100px;"></div>
红色元素相对定位,黄色元素并没有向上移动,是因为红色元素并没有脱离文档流,还占据着原来的位置,可以想象成红色元素只是灵魂脱壳了,身体还在原来的位置上。
过渡受限:
当设置同时设置left和right值产生冲突(也叫过渡受限)时,浏览器会自动调整这两个值。
调整情况:
left 和 right 的特性值(受限情况)
1). 如果left和right的值都是 auto
则left和right计算后的值都为0。
2). 如果left或right其一的值为auto
如果left为auto,则计算后的值为-right。
如果right为auto,则计算后的值-left。
示例代码:
<div style="width:100px; height:100px; background-color:red; position:relative; left:100px;"></div>
上述代码中,div是相对定位,它的left值是100px,right没有设置,所以默认为auto,那么,right计算后的值应该是-left,即right:-100px。
为什么这么做?:
只有left为100px和right为-100px才可以同时设置,因为left为100px其实就等于right为-100px,向自身位置的左边偏移100px和向自身位置的右边偏移负100px表示的都是同一个位置。
3). left和right的值都不是auto
那么定位就显得很牵强,其中一个会被调整。如果包含块的direction属性是 ltr, 那么right调整为-left。如果包含块的direction属性是rtl,left值调整为-right。
示例代码:
<div style="width:100px; height:100px; overflow:auto; border:1px solid blue;">
<div style="width:20px; height:20px; background-color:red; position:relative; left:60px; right:60px;"></div>
</div>
最后,right计算为-left,right调整为-60px。
静态位置(static):
计算元素原来在文档流位置的意思,也就是所谓的静态位置。
案例:
.right{
/* position: absolute; */
height: 300px;
background: lightblue;
margin: 0px auto;
width: 300px;
margin-left: 40px;
}
.ne{
position: absolute;
left: auto;
width:100px;
height: 100px;
background: red;
}
<div class="right">
<span>asdasd</span>
<span class="ne"></span>
</div>
这里的 left: auto;表示的就是静态位置,可以看到红色方块,我们知道当祖先元素没有定位的情况下,定位元素是相对于文档定位的,left值为auto,那么left的值就是元素相对于原来文档流位置到文档的左边缘的距离。
绝对定位
- 宽高为auto时,适应内容
- 相对于最近的定位祖先元素的位置边框盒(padding+content的区域)左上角为原点进行定位偏移,如果没有则相对于初始包含块(整个文档)进行偏移摆放元素。
注释:根据用户代理的不同,最初的包含块可能是画布或 HTML 元素。
- 开启绝对定位如果不设置偏移元素的位置不会发生改变。
- 完全脱离文档流,不占据文档流的位置,后面的任何元素被忽视,包括行内元素。
- 元素会强制display为block,哪怕你设置diplay:inline也改不过来。
- 绝对定位使用浮动无效。
可以设置auto值的属性
width、height、margin、top、bottom、left、right.
绝对定位布局计算等式:
left + margin-left + border-left + padding-left + width + padding-right + border-right + margin-right + right = 包含块内容区的宽度。
为了解决left、top、bottom、top同时设置而产生的冲突,w3c制定了这个规则,比方说同时设置left:20px; right:30px,元素相对于包含块偏移20px同时相对于包含块右边偏移30px,这个是互相矛盾。
当等式不成立时,由浏览器去调整这个等式的某个值以使等式满足(也叫使用值过渡约束)。
浏览器的调整情况:
规则一: 如果left、width和right这三个都是auto:
如果margin-left和margin-right为auto值时调整为0,width为自适应内容,当包含块的direction属性是ltr,将left调整为静态位置,right计算包含块可用空间,否则相反right调整为静态位置。
规则二: 如果left、width 和 right都不是auto:
当margin-left和margin-right为auto时,则margin平分包含块可用空间。
当margin-left或margin-right之一是auto时,则为auto值的margin计算可用空间。
当margin也都不是auto,则如果包含块的direction属性是rtl,则right计算包含块可用空间,left设置为动态位置,否则就由left计算。
以上1)、2)点情况都不是,则将 margin-left 和 margin-right 的 auto 值设置为 0,并选择以下六个适用的规则之一。
规则:
- ‘left’ 和 ‘width’ 是 ‘auto’ 而 ‘right’ 不是 ‘auto’,那么宽度自适应内容,left设置为静态位置,right计算包含块可用空间。
- ‘left’ 和 ‘right’ 是 ‘auto’ 并且 ‘width’ 不是 ‘auto’,那么如果包含块的 ‘direction’ 属性是 ‘ltr’,则将 ‘left’ 设置为静态位置,否则将’right’设置为静态位置。然后’left’(如果’direction’是’rtl’)或’right’(如果’direction’是’ltr’)计算包含块可用空间。
- ‘width’ 和 ‘right’ 是 ‘auto’ 并且 ‘left’ 不是 ‘auto’,那么宽度自适应内容 ,然后right计算包含块可用空间。
- ‘left’ 是 ‘auto’,‘width’ 和 ‘right’ 不是 ‘auto’,则 'left ’ 计算包含块可用空间。
- ‘width’ 是 ‘auto’,‘left’ 和 ‘right’ 不是 ‘auto’ 则 ‘width’ 计算包含块可用空间。
- ‘right’ 是 ‘auto’,‘left’ 和 ‘width’ 不是 ‘auto’ 则 ‘right’ 计算包含块可用空间。
替换元素的情况:width、height不参与以上调整,width和height为固有宽度。
垂直方向的布局和水平方向的布局一样:
top + margin-top + border-top + padding-top + height + padding-bottom + border-bottom + margin-bottom + bottom = 包含块内容区的宽度。
案例
.parent{
position: relative;
width: 400px;
height: 400px;
background: lightblue;
}
.child{
position: absolute;
left: 10px;
right: 10px;
width: 100px;
height: 100px;
margin: 0 auto;
background: red;
}
<div class="parent">
<div class="child">我是绝对定位</div>
</div>
我们已知包含块元素的width为400px,left和right为10px。
根据绝对定位的布局计算等式:
left + margin-left + border-left + padding-left + width + padding-right + border-right + margin-right + right = 包含块内容区的宽度。
10px + auto + 0 + 0 + 100px + 0 + 0 + auto + 10px = 400px;
也就是120px + auto * 2 = 400px; (求解方程)
根据上面的规则二 left、right、width都不为auto,但是margin为auto时,会平方包含块的可用空间,因此就居中了。
10px + 140px + 0 + 0 + 100px + 0 + 0 + 140px + 10px = 400px;
因此该元素的auto值被计算为(400px - 120px) / 2 = 140px(margin-left或margin-right值),以满足以上等式。
只有当条件为margin左右为140px,width为100px时,才可以同时设置left:10px和right:10px,才能成立元素相对于包含块的左边为10px,同时又相对于包含块的右边为10px,此时left:10px和right:10px表示的都是同一个位置。
这也就是我上面所诉的设置这个等式是为了解决同时设置对立值而产生的冲突。
固定定位
其它情况和绝对定位一样。
包含块不同:固定为视口(浏览器的可以看见的窗口,就可以看见的区域)
定位下的居中
第一种
1.定宽(高)
2.将左右(上下)距离设置为0
3.将左右(上下)margin:设置为auto
原理见绝对定位的水平计算等式的规则二
.center{
width:100px;
height:100px;
background:red;
position:absolute;
left:0;
right:0;
top:0;
bottom:0;
margin:auto;
}
第二种
.center{
width:100px;
height:100px;
background:red;
position:absolute;
left:50%;
top:50%;
margin-left:-50px;
margin-top:-50px;
}