主题
相对定位与绝对定位(Day9 1/3)
本页对应 Day09_页面布局,共 7 段视频,约 1 小时 27 分。
学习目标
- 能使用
position属性及relative、absolute、fixed值设置相对定位、绝对定位和固定定位,并说明三者是否脱离文档流。 - 能使用
left、right、top、bottom调整定位元素位置,并准确说明相对定位、绝对定位、固定定位各自的参照点或包含块规则。 - 能判断绝对定位元素的包含块:从父元素向上查找第一个已定位祖先元素,若无则参照整个页面或根元素。
- 能使用
z-index调整定位元素的显示层级,并检验“仅定位元素有效、数值越大层级越高、后写元素覆盖先写元素、父元素层级可能拖后腿”等规则。 - 能说明定位相关 CSS 属性的作用、默认值和取值要求,包括
position、left/right/top/bottom、z-index。 - 能根据是否设置固定宽高,判断绝对定位或固定定位元素的默认宽高计算方式,并检验同时设置
left/right或top/bottom对宽高的拉伸效果。
知识点
从浮动与行内块回顾布局基础
为什么需要:页面布局不能只靠默认文档流,需要理解浮动、行内块元素在排列、撑高父元素、居中和对齐上的差异。怎么想:先判断元素是否脱离文档流,再看它是否还被父元素当作文本处理。怎么做:浮动元素会脱离文档流,多个浮动可水平排列并自动换行;不论原显示模式如何,设置浮动后按浮动元素处理。行内块元素会被父元素当作文本,因此可用父元素的 text-align 做水平居中,但纵向对齐受基线影响。易错点:兄弟元素要浮动就全浮动,避免“浮动与不浮动做兄弟”;父元素高度塌陷可用固定高度、父元素浮动、overflow 非 visible,最推荐伪元素清除浮动:
css
.clearfix::after {
content: "";
display: block;
clear: both;
}行内块底部空白来自基线与底线之间的距离,可给行内块设置 vertical-align 为非 baseline,或给父元素 font-size: 0 后重置字体大小。左右空白通常由换行产生,也可用父元素 font-size: 0 解决。
相对定位
为什么需要:有时只想微调元素位置,又不想影响其他元素。怎么想:相对定位不脱离文档流,参照“自己原来的位置”定位。怎么做:
css
.box2 {
position: relative;
left: 100px;
top: 100px;
}设置后元素原本占位不变,只发生视觉位移;left: 100px 是相对原位置向右,top: 100px 是向下。right: 30px 与 left: -30px 效果相近,bottom 与 top 也类似。易错点:left 与 right 同时设置时通常听 left,top 与 bottom 同时设置时通常听 top;相对定位不改变显示模式,也可与浮动共存。它常用来做鼠标悬停微动,更重要的是给绝对定位子元素提供包含块。
绝对定位
为什么需要:需要把元素放到指定位置,或覆盖到其他不相关元素上层时使用。怎么想:绝对定位脱离文档流,后边兄弟会占它的位置,它自身显示在上层;定位参考点是“包含块”。怎么做:
css
.box2 {
position: absolute;
left: 0;
top: 0;
}包含块规则:从父元素向上找第一个“已定位”的祖先元素;若没有,则包含块是整个页面/根元素。定位从包含块的内边距区域开始,不是边框。易错点:不要把所有元素都绝对定位来排版,元素不会像浮动那样自动排列,容易重叠;绝对定位比浮动优先级更强,同时设置浮动和绝对定位时按绝对定位处理;它也不被父元素当作文本,text-align 不能让它整体居中。
固定定位
为什么需要:广告、固定导航等滚动页面时仍固定在视口某一位置。怎么想:固定定位也脱离文档流,显示特点与绝对定位基本相同,唯一关键区别是包含块固定为视口。怎么做:
css
.box2 {
position: fixed;
right: 10px;
top: 100px;
}易错点:固定定位与祖先元素是否定位无关;不设置 left/right/top/bottom 时,它默认还在原位置附近,不是自动跑到视口某处;left 与 right、top 与 bottom 不宜同时设置。
显示层级与 z-index
为什么需要:定位元素重叠时,需要控制谁在上谁在下。怎么想:所有定位元素默认显示层级相同,后写的显示在上层;定位元素整体高于不定位元素。怎么做:
css
.box1 {
position: fixed;
z-index: 1;
}z-index 只对定位元素有效,值为纯数字,越大层级越高,也可为负值。易错点:不定位元素设置 z-index 无效;若父元素设置了较小的 z-index,子元素层级再大也可能被父元素“拖后腿”。
定位属性与默认宽高
定位统一用 position:relative 相对、absolute 绝对、fixed 固定;配合 left/right/top/bottom 调整位置,值可为长度或百分比。绝对/固定定位元素未设置固定宽度时,同时设置 left 和 right 会生效并拉伸默认宽度;未设置固定高度时,同时设置 top 和 bottom 会拉伸默认高度。若已有固定宽高,则通常只按一个方向生效。易错点:不要死记硬背,要理解“有固定宽高时不能再被两边拉开”的逻辑;相对定位不改变显示模式,默认宽高仍按原显示模式判断。
回顾清单(保留原代码)
text
1 回顾
1. 浮动
1.1 文字环绕
1.2 浮动元素的特点
① 脱离文档流
② 水平排列,自动换行
③ 不论原来的显示模式如何,设置为浮动就是浮动
1.3 浮动元素的影响
① 对后面兄弟元素
② 对父元素的影响
2. 行内块元素布局 会被父元素当成文本
2.1 居中
2.2 布局中的问题
① 左右空白
② 底部空白
③ 对不齐 没有文字、一行文字、多行文字浮动:从文字环绕到布局工具
为什么需要:浮动最初用于文字环绕,后来常用来做水平排列。怎么想:元素一旦浮动就脱离文档流,多个浮动元素水平排列、自动换行;不论原来是块级、行内还是行内块,设置为浮动就按浮动处理。怎么做:用float;兄弟元素要浮动就全浮动;父元素高度塌陷时,可用固定高度、父元素也浮动、overflow非visible,最推荐伪元素清除浮动:content、display:block、clear:both。易错点:浮动和不浮动元素做兄弟容易出问题;浮动元素不能像块级那样靠margin:auto居中;它不会被父元素当成文本。
行内块布局:父元素把它当文本
为什么需要:行内块做居中较方便。怎么想:行内块会被父元素当成文本,所以父元素设text-align可横向居中;但行内块有宽高,纵向受基线影响。怎么做:左右空白来自代码换行,可给父元素font-size:0,再给子元素重设字号;底部空白和对不齐用vertical-align,值只要不是baseline即可,常用bottom;图片也可display:block。易错点:无文字、一行文字、多行文字参与对齐的基线不同;vertical-align是关键。
相对定位:参照自己原来的位置
为什么需要:只微调位置,又尽量不影响布局。怎么想:position:relative不脱离文档流,参照自己原来的位置,用left/right/top/bottom调整;left与right冲突时听left,top与bottom冲突时听top。怎么做:position:relative; left:100px; top:100px;,可用负值;可与浮动共存,显示模式不变。易错点:不是相对父元素;不要同时设置冲突方向;它不影响相邻元素,和margin挤动兄弟不同。应用如鼠标悬停上移,也常给绝对定位子元素做包含块。
绝对定位:脱离文档流,找包含块
为什么需要:让元素盖到不相关元素上层,如下拉菜单、图片上的按钮。怎么想:position:absolute脱离文档流,后兄弟会占位,定位元素显示在上层;参考点是包含块——从父元素向上找第一个定位的祖先元素,没有就是整个页面/根元素。怎么做:position:absolute; left/right/top/bottom调整;祖先常设relative。调试时把B设绝对定位,C消失,检查发现C跑到B下面;设left:0;top:0跑到body外边距外,说明包含块不是body而是页面;给html、body、weper加定位后位置会变。易错点:全设绝对定位会重叠、父高度塌陷;包含块不一定是父元素;同时设浮动和绝对定位,绝对定位生效;默认宽高被内容撑开,不被父当文本,margin:auto一般不能居中。
固定定位:包含块是视口
为什么需要:滚动时固定广告、固定导航。怎么想:position:fixed的包含块固定为视口,与祖先是否定位无关;显示特点同绝对定位,也脱离文档流。怎么做:position:fixed; right:10px; top:100px;。调试时span设固定定位后宽高生效,但仍在原位置,加right/top才移动;拖滚动条它不动。易错点:没调位置就以为没生效;不是相对父元素;left/right、top/bottom不要一起设,除非无固定宽高想拉伸。
显示层级与z-index
为什么需要:重叠时决定谁上谁下。怎么想:所有定位元素默认层级相同,后写的在上;定位元素比不定位高;z-index只对定位元素有效,数字越大越高,可负。调试时三兄弟重叠,后写的相对定位C在上;给A设z-index:1后A在上;item与book01比较时,weper设z-index:20会拖后腿,book01设100也不如item的80。易错点:不定位元素设z-index无效;不必盲目写大数;注意父元素层级影响。
定位相关CSS属性与默认宽高
为什么需要:统一理解定位属性和默认宽高。怎么想:position默认static,值有relative/absolute/fixed;left/right/top/bottom是参照点距离;z-index是纯数字。绝对/固定定位默认宽高被内容撑开,但未设固定宽度时同时设left/right会拉伸宽度,未设固定高度时同时设top/bottom会拉伸高度;有固定宽高时只按一个方向生效。怎么做:如position:absolute; left:0; right:0;可拉满包含块;固定定位可拉满视口。易错点:相对定位不改变显示模式;这些默认宽高规则主要看绝对和固定;不要死记,理解“有固定宽高就不能再拉伸”。
课堂画面






代码示例
示例一:相对定位 + 绝对定位(子绝父相)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>相对定位与绝对定位</title>
<style>
* { margin: 0; padding: 0; }
.wrapper {
width: 800px;
padding: 20px;
margin: 60px auto;
background: #f0f0f0;
position: relative; /* 相对定位:成为子元素绝对定位的包含块 */
}
.box {
width: 200px;
height: 100px;
margin-bottom: 10px;
color: #fff;
}
.box-a { background: #f00; }
.box-b { background: #0f0; }
.box-c { background: #00f; }
/* 元素B:相对定位,参照自己原来的位置 */
.box-b {
position: relative;
left: 100px;
top: 100px;
}
/* 元素C:绝对定位,参照包含块 .wrapper */
.box-c {
position: absolute;
right: 0;
bottom: 0;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="box box-a">元素A</div>
<div class="box box-b">元素B</div>
<div class="box box-c">元素C</div>
</div>
</body>
</html>关键行与易错点
position: relative不脱离文档流,left/top参照的是自己原来的位置,前后兄弟元素仍按原位置排列,影响比外边距还小。left与right同时写只有left生效;top与bottom同时写只有top生效(有固定宽高时)。- 绝对定位的包含块 = 第一个定位的祖先元素;若没有任何定位祖先,就是整个页面(根元素)。
- 定位是从包含块的内边距开始算,不是从边框开始。
- 易错点:忘给父元素加
position: relative,绝对定位的子元素会跑到页面左上角(脱离文档流后认的是页面);相对定位元素依旧占原来的坑,不能拿它做水平排列。
示例二:固定定位与 z-index 显示层级
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>固定定位与显示层级</title>
<style>
* { margin: 0; padding: 0; }
body { height: 2000px; } /* 撑出滚动条,验证 fixed 不动 */
.wrapper {
width: 800px;
padding: 20px;
margin: 60px auto;
background: #eee;
position: relative;
z-index: 20; /* 父元素设置 z-index 会影响子元素比较 */
}
.box { width: 200px; height: 100px; color: #fff; }
.box-a { background: #f00; }
.box-b { background: #0f0; }
.box-c { background: #00f; }
/* A:固定定位,包含块永远是视口 */
.box-a {
position: fixed;
left: 100px;
top: 150px;
z-index: 100;
}
/* B:绝对定位 */
.box-b {
position: absolute;
left: 50px;
top: 50px;
}
/* C:相对定位,参照自己原来的位置 */
.box-c {
position: relative;
left: 10px;
top: 10px;
}
/* 不相关的兄弟元素 */
.item {
width: 400px;
background: #909;
color: #fff;
position: absolute;
left: 200px;
top: 150px;
z-index: 80;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="box box-a">元素A</div>
<div class="box box-b">元素B</div>
<div class="box box-c">元素C</div>
</div>
<div class="item">item 元素</div>
</body>
</html>关键行与易错点
position: fixed的包含块永远固定是视口,与祖先元素定不定位无关;页面滚动它不动(广告、固定导航就是这么做的)。- 三种定位(relative / absolute / fixed)的默认显示层级完全相同,位置重叠时后写的元素在上面,别以为 fixed 最“猛”。
z-index只能给定位元素设置,不定位的元素写了无效;值为纯数字,越大越靠上,可为负值(负值会沉到父元素背景之下)。- 父元素设了
z-index会“拖后腿”:box-a的z-index:100大于item的80,但因父元素.wrapper只有20,整体仍被item压住。排查“层级明明更高却被盖住”时先看父元素。 - 易错点:
fixed不写left/top时会停在原来位置,看起来“没生效”;fixed也脱离文档流,父元素高度同样会塌陷。
示例三:定位元素默认宽高的计算规则
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>定位元素默认宽高计算规则</title>
<style>
* { margin: 0; padding: 0; }
.wrapper {
width: 800px;
height: 400px;
padding: 20px;
margin: 60px auto;
background: #eee;
position: relative; /* 作为 A 的包含块 */
}
/* A:绝对定位,不设宽高 */
.box-a {
background: #f00;
color: #fff;
position: absolute;
left: 0;
right: 0; /* 左右同时生效 → 宽度被拉开 */
top: 0;
bottom: 0; /* 上下同时生效 → 高度被拉开 */
}
/* B:固定定位,不设宽高 */
.box-b {
background: #0f0;
color: #fff;
position: fixed;
left: 0;
right: 0; /* 参照视口 → 与视口一样宽 */
top: 200px;
bottom: 200px; /* 上下各 200,高度被拉开 */
}
</style>
</head>
<body>
<div class="wrapper">
<div class="box-a">元素A:绝对定位,未设宽高,left/right/top/bottom 全 0</div>
</div>
<div class="box-b">元素B:固定定位,left/right 为 0,top/bottom 为 200px</div>
</body>
</html>关键行与易错点
- 绝对/固定定位元素默认宽高被内容撑开(只有块级元素的默认宽度才是铺满父元素);无内容就无宽高。
- 没有固定宽高时,
left和right可以同时生效,把宽度拉开;top和bottom同时生效,把高度拉开——宽高是“平等”的,打破了块级margin: auto只能左右居中的限制。 - 一旦设置了固定宽/高,
left与right只left生效,top与bottom只top生效。 - 相对定位不属于此列:它不改变显示模式,宽高仍按原来的块级/行内/行内块规则计算。
- 易错点:死记“left 和 right 不能同时写”——只在有固定宽度时才失效;另外定位元素不会发生外边距塌陷与合并,
margin: auto一般也不能让它水平居中。
常见错误
设了
left:0; right:0,宽度却没被拉伸 现象:明明两个方向都写了 0,元素还是原来的宽度,right像没写一样。 原因:元素自身写了固定width,此时left/right只能生效一个(优先left),right白写。 修法:想用left/right拉开宽度就不要给width;已有固定宽度又想居中,就别指望这对属性。子元素绝对定位后“跑”到页面别处,不认父元素 现象:给子元素
position:absolute后,它跑到了页面左上角或页面右下角,完全脱离父盒子。 原因:绝对定位的参照是“包含块”——从父元素向上找第一个已定位的祖先;一个都没找到就退到初始包含块(整个页面)。父元素没定位,自然不认它。 修法:给父元素加position:relative(影响最小),形成“子绝父相”;父元素若已定位则不用再加。固定定位元素位置不对,或滚动时跟着跑 现象:设置
position:fixed后元素位置很怪;或者滚动页面时它并没有“钉住”。 原因:① 只写了fixed却没写left/top/right/bottom,元素仍停在原来的文档流位置上(fixed只是让它不再随流,不等于自动挪位);② 误以为祖先定位会影响它,其实固定定位的包含块永远是视口,与祖先定不定位无关。 修法:设置偏移属性调整位置;确认没有被父级transform之类属性改变其参照。z-index写得很大,却依然压不住别人 现象:明明写了z-index: 9999,还是被下面某个元素盖住。 原因:① 元素没定位,z-index对该元素完全无效;② 元素所在祖先设置了更小的z-index,整个后代被“拖后腿”,子元素再大也出不了祖先这一层。 修法:先给元素加定位;再沿祖先链检查有没有多余的z-index,能删就删,删不掉就调整祖先的值。绝对定位元素后面的兄弟“消失”了,父元素高度也没了 现象:给中间元素加绝对定位后,后面的兄弟跑到了它下面被盖住,父元素高度塌陷。 原因:绝对/固定定位脱离文档流,后续元素按它“不存在”来排列,同时它又显示在上层。 修法:这是正常机制而非 bug。父元素给固定高度或
overflow(非 visible)撑住;更根本的是——不要用绝对定位做常规排版。用绝对定位给所有元素逐个算
left/top排页面 现象:一开始排得挺整齐,内容一多就完全乱套,改一处崩一片。 原因:定位元素之间不会自动排列换行(不像浮动),只能靠手算坐标硬拼。 修法:定位只作布局补充。常规排列仍用浮动等方案;绝对定位留给“需要盖在不相关元素上层”的场景(下拉菜单、图片上的小按钮等)。
练习
做一个“子绝父相”的最小验证:父盒子 400×300 带内边距和边框,子盒子 100×100。分别测试父元素不定位、
relative、absolute、fixed四种情况下,子元素left:0;top:0的落点,用文字标注每次的参照物是什么。用
left/right拉伸宽度:在同一个定位父盒子里放两个绝对定位元素,A 设width:200px; left:0; right:0,B 不设宽度只设left:20px; right:20px。观察两者宽度差异,并用一句话解释原因。再把 B 的top/bottom也设成 0,观察高度变化。商品列表悬停上浮:三个 250×300 的卡片横向排列(
margin-right20px),鼠标移入时卡片向上移动几像素并加阴影。要求:移动过程中其他卡片位置完全不动,并说明为什么这里选相对定位而不是margin-top。下拉菜单:做一个顶部导航,其中一项鼠标移入时向下弹出一个菜单面板,要求面板浮在下方内容之上、不影响导航条高度。完成后回答:菜单面板和它的父项分别用什么定位?为什么不能两个都用绝对定位?
层级排查实验:三个重叠的定位盒子 + 一个外部定位元素,先只调各自
z-index观察结果;再给最外层容器加一个较小的z-index,重新观察并记录“谁压谁”的变化,写出你的排查结论。
原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | 回顾 | 09:48 |
| 2 | 相对定位 | 15:55 |
| 3 | 绝对定位 | 27:15 |
| 4 | 固定定位 | 07:19 |
| 5 | 定位元素的显示层级 | 15:51 |
| 6 | 定位相关CSS属性 | 01:53 |
| 7 | 定位元素默认宽高 | 09:16 |
小结
- 定位的核心不是“四个偏移属性怎么写”,而是先问一句:它的参照点(包含块)是谁。参照点错了,数值再准也是白搭。
- 三种定位的差别可以压成一句话:相对定位只动自己、不影响别人;绝对定位脱离文档流、按包含块定位;固定定位就是包含块被写死成视口的绝对定位。
- 定位会“赢”过浮动和原有显示模式,但赢不了布局的复杂度——它不参与排列、不自动换行,所以定位是布局的补充,不是布局方式。
- 判断要不要用绝对定位,标准只有一条:这个元素是否需要盖在与自己不相关的元素上层。是则用,否则老老实实回到浮动。
left/right、top/bottom能否同时生效取决于有没有固定宽高——有固定宽高就是二选一,没有就是“拉开”。这条不要背,画个盒子想一想就明白了。z-index只在定位元素上有效;比较时不是只看自己的值,而是看层叠上下文里祖先给出的那层天花板,出问题先往上查。- 遇到“位置不对/被盖住/高度塌陷”这三类现象,排查顺序固定为:参照点是不是预期 → 有没有脱离文档流 → 层级链条上谁拖了后腿。