Skip to content

相对定位与绝对定位(Day9 1/3) ​

本页对应 Day09_页面布局,共 7 段视频,约 1 小时 27 分。

学习目标 ​

  1. 能使用 position 属性及 relative、absolute、fixed 值设置相对定位、绝对定位和固定定位,并说明三者是否脱离文档流。
  2. 能使用 left、right、top、bottom 调整定位元素位置,并准确说明相对定位、绝对定位、固定定位各自的参照点或包含块规则。
  3. 能判断绝对定位元素的包含块:从父元素向上查找第一个已定位祖先元素,若无则参照整个页面或根元素。
  4. 能使用 z-index 调整定位元素的显示层级,并检验“仅定位元素有效、数值越大层级越高、后写元素覆盖先写元素、父元素层级可能拖后腿”等规则。
  5. 能说明定位相关 CSS 属性的作用、默认值和取值要求,包括 position、left/right/top/bottom、z-index。
  6. 能根据是否设置固定宽高,判断绝对定位或固定定位元素的默认宽高计算方式,并检验同时设置 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;可拉满包含块;固定定位可拉满视口。易错点:相对定位不改变显示模式;这些默认宽高规则主要看绝对和固定;不要死记,理解“有固定宽高就不能再拉伸”。

课堂画面 ​

课堂画面 1

课堂画面 2

课堂画面 3

课堂画面 4

课堂画面 5

课堂画面 6

代码示例 ​

示例一:相对定位 + 绝对定位(子绝父相) ​

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 一般也不能让它水平居中。

常见错误 ​

  1. 设了 left:0; right:0,宽度却没被拉伸 现象:明明两个方向都写了 0,元素还是原来的宽度,right 像没写一样。 原因:元素自身写了固定 width,此时 left/right 只能生效一个(优先 left),right 白写。 修法:想用 left/right 拉开宽度就不要给 width;已有固定宽度又想居中,就别指望这对属性。

  2. 子元素绝对定位后“跑”到页面别处,不认父元素 现象:给子元素 position:absolute 后,它跑到了页面左上角或页面右下角,完全脱离父盒子。 原因:绝对定位的参照是“包含块”——从父元素向上找第一个已定位的祖先;一个都没找到就退到初始包含块(整个页面)。父元素没定位,自然不认它。 修法:给父元素加 position:relative(影响最小),形成“子绝父相”;父元素若已定位则不用再加。

  3. 固定定位元素位置不对,或滚动时跟着跑 现象:设置 position:fixed 后元素位置很怪;或者滚动页面时它并没有“钉住”。 原因:① 只写了 fixed 却没写 left/top/right/bottom,元素仍停在原来的文档流位置上(fixed 只是让它不再随流,不等于自动挪位);② 误以为祖先定位会影响它,其实固定定位的包含块永远是视口,与祖先定不定位无关。 修法:设置偏移属性调整位置;确认没有被父级 transform 之类属性改变其参照。

  4. z-index 写得很大,却依然压不住别人 现象:明明写了 z-index: 9999,还是被下面某个元素盖住。 原因:① 元素没定位,z-index 对该元素完全无效;② 元素所在祖先设置了更小的 z-index,整个后代被“拖后腿”,子元素再大也出不了祖先这一层。 修法:先给元素加定位;再沿祖先链检查有没有多余的 z-index,能删就删,删不掉就调整祖先的值。

  5. 绝对定位元素后面的兄弟“消失”了,父元素高度也没了 现象:给中间元素加绝对定位后,后面的兄弟跑到了它下面被盖住,父元素高度塌陷。 原因:绝对/固定定位脱离文档流,后续元素按它“不存在”来排列,同时它又显示在上层。 修法:这是正常机制而非 bug。父元素给固定高度或 overflow(非 visible)撑住;更根本的是——不要用绝对定位做常规排版。

  6. 用绝对定位给所有元素逐个算 left/top 排页面 现象:一开始排得挺整齐,内容一多就完全乱套,改一处崩一片。 原因:定位元素之间不会自动排列换行(不像浮动),只能靠手算坐标硬拼。 修法:定位只作布局补充。常规排列仍用浮动等方案;绝对定位留给“需要盖在不相关元素上层”的场景(下拉菜单、图片上的小按钮等)。

练习 ​

  1. 做一个“子绝父相”的最小验证:父盒子 400×300 带内边距和边框,子盒子 100×100。分别测试父元素不定位、relative、absolute、fixed 四种情况下,子元素 left:0;top:0 的落点,用文字标注每次的参照物是什么。

  2. 用 left/right 拉伸宽度:在同一个定位父盒子里放两个绝对定位元素,A 设 width:200px; left:0; right:0,B 不设宽度只设 left:20px; right:20px。观察两者宽度差异,并用一句话解释原因。再把 B 的 top/bottom 也设成 0,观察高度变化。

  3. 商品列表悬停上浮:三个 250×300 的卡片横向排列(margin-right 20px),鼠标移入时卡片向上移动几像素并加阴影。要求:移动过程中其他卡片位置完全不动,并说明为什么这里选相对定位而不是 margin-top。

  4. 下拉菜单:做一个顶部导航,其中一项鼠标移入时向下弹出一个菜单面板,要求面板浮在下方内容之上、不影响导航条高度。完成后回答:菜单面板和它的父项分别用什么定位?为什么不能两个都用绝对定位?

  5. 层级排查实验:三个重叠的定位盒子 + 一个外部定位元素,先只调各自 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

小结 ​

  1. 定位的核心不是“四个偏移属性怎么写”,而是先问一句:它的参照点(包含块)是谁。参照点错了,数值再准也是白搭。
  2. 三种定位的差别可以压成一句话:相对定位只动自己、不影响别人;绝对定位脱离文档流、按包含块定位;固定定位就是包含块被写死成视口的绝对定位。
  3. 定位会“赢”过浮动和原有显示模式,但赢不了布局的复杂度——它不参与排列、不自动换行,所以定位是布局的补充,不是布局方式。
  4. 判断要不要用绝对定位,标准只有一条:这个元素是否需要盖在与自己不相关的元素上层。是则用,否则老老实实回到浮动。
  5. left/right、top/bottom 能否同时生效取决于有没有固定宽高——有固定宽高就是二选一,没有就是“拉开”。这条不要背,画个盒子想一想就明白了。
  6. z-index 只在定位元素上有效;比较时不是只看自己的值,而是看层叠上下文里祖先给出的那层天花板,出问题先往上查。
  7. 遇到“位置不对/被盖住/高度塌陷”这三类现象,排查顺序固定为:参照点是不是预期 → 有没有脱离文档流 → 层级链条上谁拖了后腿。