# CSS绝对定位absolute详解
返回:一般常见样式处理及开发技巧 | 返回:css属性position处
TIP
包裹性 和 高度欺骗
一旦给元素加上absolute或float就相当于给元素加上了display:block;
什么意思呢?
比如内联元素span默认宽度是自适应的,你给其加上width是不起作用的。要想width定宽,你需要将span设成display:block。
但如果你给span加上absolute或float,那span的display属性自动就变成block,就可以指定width了。
因此如果看到CSS里absolute/float和display:block同时出现,那display:block就是多余的CSS代码。
# 如何确定定位点
一旦absolute分层后,第一个出现的问题就是让浏览器在何处显示该元素。普通文档流里的元素,浏览器可以根据其父子兄弟元素的大小和位置,计算出该元素的位置。但分层后怎么办?
- 第一种情况:用户
只给元素指定了absolute,未指定left/top/right/bottom。此时absolute元素的左上角定位点位置就是该元素正常文档流里的位置。如上面图例中,图片熊猫是父元素的第一个孩子,因此左上角定位点就是父元素的content的左上角。

- 第二种情况:用户给absolute元素指定了left/right,top/bottom
- 只指定left时,元素的左上角定位点的left值会变成用户指定值。但top值仍旧是该元素在正常文档流中的top值
- 只指定right时,元素的右上角定位点的right值会变成用户指定值。但top值仍旧是该元素在正常文档流中的top值
TIP
通过对left/top/right/bottom的组合设置,由于没有position:static以外的父元素,此时absolute元素可以去任意它想去的地方,天空才是它的极限。
# 和relative相爱相杀
TIP
如果absolute元素没有position:static以外的父元素,那将相对body定位,天空才是它的极限。而一旦父元素被设为relative,那absolute子元素将相对于其父元素定位,就好像一只脚上被绑了绳子的鸟。
.withAbsoluteDiv {
border: 3px dashed #e1622f;
//position: absolute;
position: relative;
display: inline-block; // 这个很重要,否则将很难调整徽标的位置
}
.badgeDigit {
border: 1px solid #b7d28d;
background-color: #f00;
color: #fff;
border-radius: 50%;
text-align: center;
position: absolute;
width: 30px;
height: 30px;
right: -15px;
top: -15px;
font-size: 18px;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<div className={ styles.withAbsoluteDiv }>
<img alt="rmb11" src={ rmb12 } height={63}/>
<span className={styles.badgeDigit}>首</span>
</div>
2
3
4

如果没有display: inline-block;,则效果图如下:

这样做效果是OK的,兼容性也OK。但CSS的世界里要实现一个效果可以有很多种方式,具体选用哪个方案是见仁见智的。我比较看重的标准:一个是简洁,另一个是尽量让每个属性干其本职工作。
用这两个标准看待上述实现方法,应该是有改进的空间的。首先外层div多了relative未能简洁到极致。其次relative的本职工作是让元素在相对其正常文档流位置进行偏移,但父层div并不需要任何位置偏移,之所以设成relative唯一的目的是限制absolute子元素的定位点。
用父relative + 子absolute来实现定位,万一将来页面布局要调整,父元素的尺寸需要变换呢?则会出现错位现象
TIP
未指定left/top/right/bottom的absolute元素,其在所处层级中的定位点就是正常文档流中该元素的定位点。
.withAbsoluteDiv {
border: 3px dashed #e1622f;
display: inline-block;
}
.badgeDigit2 {
border: 1px solid #b7d28d;
background-color: #f00;
color: #fff;
border-radius: 50%;
text-align: center;
position: absolute;
width: 30px;
height: 30px;
font-size: 18px;
margin: -15px -15px 0 0;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
这么说来relative和absolute是否应该彻底断绝关系呢?不是这样的,这段的标题是“和relative相爱相杀”,刚才说的想杀部分,现在说下什么相爱部分。
# 全屏覆盖、遮罩层
absolute常见的一个案例是透明层覆盖元素。
TIP
用absolute的left: 0;right: 0;top: 0;bottom: 0;来实现全屏拉伸,对于absolute元素来说,如果同时设置left和right会水平拉伸,同时设置top和bottom会垂直拉伸。
.withAbsoluteDiv {
border: 3px dashed #e1622f;
display: inline-block;
}
2
3
4
<div className={ styles.withAbsoluteDiv }>
<img alt="rmb11" src={ rmb12 } height={63}/>
{/* <span className={styles.badgeDigit}>首</span> */}
<span className={styles.badgeDigit2}>二</span>
</div>
<span className={styles.cover} />
2
3
4
5
6

WARNING
那为何不设width/height为100%呢?
前面说了,不设top/right/top/bottom的话absolute会从正常文档流应处的位置开始定位,因此做不到全屏。
除非你设置width/height为100%后,同时再设left: 0; top: 0;。这样就显得很啰嗦。
# 部分遮罩
只希望给图片部分设置滤镜呢?用js计算图片的大小尺寸和定位点后,设置absolute滤镜的尺寸和定位点?太麻烦了。用relative吧
.withAbsoluteDiv {
border: 3px dashed #e1622f;
position: relative;
display: inline-block;
}
2
3
4
5
<div className={ styles.withAbsoluteDiv }>
<span className={styles.cover} />
<img alt="rmb11" src={ rmb12 } height={63}/>
{/* <span className={styles.badgeDigit}>首</span> */}
<span className={styles.badgeDigit2}>二</span>
</div>
2
3
4
5
6

# 和relative相爱相杀-结论
- 1.相对定位时,不必拘泥于relative+absolute,试试去掉relative,充分利用absolute自身定位的特性,将relative和absolute解耦。耦合度越低维护起来越容易,前端仔腾出时间陪女朋友吃饭才是正道。
- 2.拉伸平铺时,用relative可以有效限制子absolute元素的拉伸平铺范围(注意是拉伸,不是缩小。要缩小请再加上width/height:100%;)
# 和z-index的关系
TIP
z-index被太多的滥用了。几乎成了个定势思维:只要设了absolute就需要同步设置z-index。其实不是这样的。
- 以下情况根本不需要设z-index:
- 让absolute元素覆盖正常文档流内元素(不用设z-index,自然覆盖)
- 让后一个absolute元素覆盖前一个absolute元素(不用设z-index,只要在HTML端正确设置元素顺序即可)
# 什么时候需要设置z-index
- 当absolute元素覆盖另一个absolute元素,且HTML端不方便调整DOM的先后顺序时,需要设置z-index: 1。非常少见的情况下多个absolute交错覆盖
- 或者需要显示最高层次的模态对话框时,可以设置z-index > 1。
TIP
如果你的页面不比京东更复杂,那z-index通常设成1,2,3足够了
# 减少重绘和回流的开销
TIP
例如将元素隐藏,你或许会用display:none。
其实我更推荐的是absolute控制隐藏和显示。
方法当然相当简单,
如absolute+ top:-9999em,或absolute + visibility:hidden。
TIP
考虑到重绘和回流的开销,可以将动画效果放到absolute元素中,避免浏览器将render tree回流。