主题
CSS 高级(一)
本页对应 CSS 高级,共 8 段视频,约 1 小时 20 分。
学习目标
- 能够说明定位由“定位模式(position)”和“边偏移(left/right/top/bottom)”两部分组成,并在代码中正确书写相对定位、绝对定位、固定定位的基本语法。
- 能够通过代码演示并解释相对定位“不脱标、保留原位置、显示模式不变、相对自身原位置移动”的特点,且能区分其与 margin 移动对其它盒子影响的差异。
- 能够解释绝对定位“脱标不占位、具有行内块特点、相对最近有定位的祖先元素定位,否则相对浏览器可视区定位”的规则,并完成一个元素覆盖另一个元素的绝对定位案例。
- 能够依据“子绝父相”原则为父盒子设置相对定位、子盒子设置绝对定位,使子元素被约束在父盒子指定位置内,同时保证父盒子原位置不被破坏。
- 能够分别使用
left/top: 50%配合负 margin,以及left/top: 50%配合transform: translate(-50%, -50%),实现绝对定位盒子的水平垂直居中。 - 能够使用固定定位完成学成在线顶部固定导航和右侧固定侧边栏:处理导航通栏宽度、下方内容被遮挡的间距补偿,并利用
left: 50%加margin-left实现侧边栏随版心定位。
知识点
定位的作用与两部分
为什么需要:只用 flex 能让多个盒子并排,但做不了“压住图片的小图标、滚动不动的顶部导航、右下角广告”等效果。转写稿里用京东的小相机、购物车图标、滚动时顶部速度框和右侧客服说明:这些都要靠定位。
怎么想:定位分两步——先确定“用什么方式定”,即 position 定位模式;再确定“到哪里去”,即 left / right / top / bottom 边偏移。转写稿强调:left 是左,right 是右,top 是上,bottom 是下。
怎么做:
css
盒子 {
position: 定位模式;
left: 值;
top: 值;
}易错点:定位模式决定盒子行为,边偏移只负责移动;不要只写偏移不写 position。同时写 left 和 right 时,按“先左后右、先上后下”理解,不要以为会同时生效。
相对定位
为什么需要:相对定位可以让盒子相对自己原来的位置移动,同时保留原来的占位,不影响其他盒子。
怎么想:转写稿用“人走了,钱还留着”比喻——盒子移动了,但原位置还占着。它不脱标、占位,显示模式保持不变;偏移相对自己原来的位置。
怎么做:
css
div {
position: relative;
top: 100px;
left: 200px;
}调试过程:给盒子加 relative 后再写 top/left,下面的黑色盒子没有升上去,说明它保留位置;若改成 margin-top,下面的盒子会被带着往下走。所以相对定位移动不会挤乱其他盒子。
易错点:相对定位很少单独拿来移动位置,开发中主要给绝对定位当“父级参照”。不要把它和 margin 混淆:margin 会影响其他盒子,相对定位保留原位置。
绝对定位与子绝父相
为什么需要:只要一个盒子要压住另一个盒子,优先想到绝对定位。转写稿中京东小图标、购物车、图片上的小点,都是绝对定位。
怎么想:绝对定位脱标、不占位,显示模式具备行内块特点;偏移相对“最近的已经定位的祖先元素”改变位置。若祖先都没有定位,则相对浏览器可视区。
怎么做:
css
.father {
position: relative;
}
.father span {
position: absolute;
top: 0;
right: 0;
}调试过程:子盒子加 absolute 后,如果父盒子没有定位,即使给父盒子加 margin,子盒子仍贴浏览器左上角;给父盒子加 relative 后,子盒子才被约束到父盒子内。于是得到开发常用结论:子级绝对定位,父级相对定位,即“子绝父相”。
易错点:父级用相对定位是为了保留位置、约束子级;若父级也用绝对定位会脱标,后面的盒子会跑上来。绝对定位找祖先时不一定是亲父,爸爸没有定位就看爷爷,谁最近且已定位就以谁为准。
定位居中
为什么需要:绝对定位盒子用 margin: 0 auto 会失效,需要专门算法做水平垂直居中。转写稿用王者荣耀弹层、页面图片居中说明。
怎么想:先 left: 50%; top: 50% 走到父级/可视区中心,但盒子左上角到了中心,整体偏右下;再向左、向上移动自身宽高的一半。

怎么做:可用负 margin,也可用 transform: translate(-50%, -50%),后者不用计算具体尺寸。
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
/* 让绝对定位的盒子水平和垂直居中 */
.box {
position: absolute;
/* 移动父亲的50% */
left: 50%;
/* 往左走自己宽度的一半 */
/* margin-left: -100px; */
top: 50%;
/* margin-top: -100px; */
/* 让子盒子走自己宽度和高度的一半 */
transform: translate(-50%, -50%);
width: 200px;
height: 200px;
background-color: pink;
/* 绝对定位让margin 0 auto 失效 */
/* margin: 0 auto; */
}
img {
position: absolute;
top: 50%;
left: 50%;
/* 让子盒子走自己宽度和高度的一半 */
transform: translate(-50%, -50%);
/* 注意,translate 百分比相对于盒子自身的宽度和高度来说 */
}
</style>
</head>
<body>
<!-- <div class="box"></div> -->
<img src="./images/down-open.png" alt="下箭头图标">
</body>
</html>易错点:translate 的百分比相对盒子自身宽高,不是父级;绝对定位后 margin: 0 auto 不能拿来水平居中。
固定定位
为什么需要:页面滚动时元素位置不变,如京东顶部、淘宝客服、右下角广告。转写稿中滚动页面观察顶部和客服不动,就是固定定位。
怎么想:固定定位脱标、不占位,显示模式具备行内块特点;偏移永远相对浏览器窗口,和父级无关。
怎么做:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.header {
position: fixed;
left: 0;
top: 0;
/* width: 200px; */
width: 100%;
height: 80px;
background-color: pink;
}
</style>
</head>
<body>
<div class="header">123</div>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
<p> 里面有很多的文字</p>
</body>
</html>调试过程:把学成在线顶部导航改 fixed 后,会出现两个坑:盒子变短,因为行内块特点下不写宽度只占内容宽,通栏要写 width: 100%;下面内容被盖住,因为固定定位不占位,要给下面盒子补 margin-top,数值等于固定盒子高度。侧边栏则可用 left: 50% 跟版心,再用 margin-left: 600px 左右微调。
易错点:固定定位一般不需要父级;想做通栏必须给宽度;不要忘了给下方内容留出高度。
堆叠层级 z-index
为什么需要:多个定位盒子重叠时,默认按标签书写顺序后来者居上;需要改变显示顺序时用 z-index。

怎么想:z-index 是整数,默认 auto,数值越大层级越高。
怎么做:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
div {
position: absolute;
top: 0;
left: 0;
/* 默认的层级 z-index: auto; */
/* 根据标签的书写顺序排列 */
/* 越往后,层级越高 */
width: 200px;
height: 200px;
}
.box1 {
background-color: red;
/* 层级属性 整数 不要跟单位*/
/* 数字越大,层级越高 */
z-index: 1;
}
.box2 {
background-color: green;
left: 20px;
top: 20px;
z-index: 2;
}
.box3 {
background-color: blue;
left: 40px;
top: 40px;
}
</style>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
</body>
</html>易错点:z-index 写整数,不要带单位;它主要作用于定位元素,默认书写顺序靠后的层级更高。
CSS精灵
为什么需要:网页里若每个小背景图都单独请求,会增加服务器请求次数,拖慢加载。CSS精灵把一些背景图整合到一张图片文件里,再用background-position定位。

怎么想:先准备一张“精灵图”,页面中的小图不再单独引入,而是把精灵图作为盒子背景,通过坐标移动,只露出需要的那一块。
怎么做:1)创建盒子,盒子尺寸与小图尺寸相同;2)设置盒子背景图为精灵图;3)添加background-position,用PxCook测量小图左上角坐标,取负数作为属性值,让背景图向左上移动。

易错点:盒子宽高必须等于小图尺寸;坐标要取负值;精灵图只适合背景图场景;精灵图更新后坐标可能变化,要重新测量。
案例:写出自己的名字
为什么需要:用“写出自己的名字”练习精灵图定位,能把“盒子尺寸、背景图、负坐标”三件事串起来。
怎么想:每个字母用一个盒子,盒子尺寸对应字母在精灵图中的尺寸;background-position决定露出哪个字母。后面的span:hover用于练习切换坐标。
怎么做:按笔记代码建立.l、.i、.u三个盒子,分别设置宽高和负坐标;span默认一个位置,悬停时切换background-position。
易错点:字母盒子尺寸写错会露出相邻图案;坐标正负写反会看不到图;background简写会覆盖位置时要小心;hover坐标要测量准确。
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
div {
display: inline-block;
margin: 0 15px;
background: url(./images/abcd.jpg) no-repeat;
}
.l {
width: 96px;
height: 112px;
background-color: pink;
background-position: -5px -275px;
}
.i {
width: 62px;
height: 107px;
background-position: -324px -141px;
}
.u {
width: 112px;
height: 112px;
background-position: -476px -421px;
}
span {
display: block;
width: 106px;
height: 118px;
background: url(./images/abcd.jpg) no-repeat;
/* 过渡 */
transition: .2s;
}
span:hover {
/* background-position: -118px -12px; */
background-position: -484px -10px;
/* width: 95px; */
/* background-position: -3px -137px; */
}
</style>
</head>
<body>
<div class="l"></div>
<div class="i"></div>
<div class="u"></div>
<span></span>
</body>
</html>字体图标(重点)
为什么需要:网页中常有简单的、颜色单一的小图标。图片图标改颜色、改尺寸不方便,字体图标“展示的是图标,本质是字体”,更灵活。

怎么想:把图标当字体用,就能用font-size、color改尺寸和颜色;体积小、渲染快、降低请求次数,兼容性也好。
怎么做:到iconfont下载字体,引入样式表,再用类名使用。优点是灵活、轻量、兼容、使用方便。
易错点:字体图标适合简单单色图标;复杂彩色图标不适合;必须正确引入字体样式表;类名不能漏。
下载字体
为什么需要:字体图标要先有字体文件,页面才能通过类名显示图标。
怎么想:在iconfont选图标,加入购物车,添加至项目,再下载至本地。
怎么做:登录 → 素材库 → 官方图标库 → 进入图标库 → 选图标,加入购物车 → 购物车,添加至项目,确定 → 下载至本地。

易错点:下载后要找到iconfont.css及字体文件;项目更新后要重新下载替换;路径写错会导致图标显示成方框。
使用字体
为什么需要:下载后只有正确引入和写类名,图标才会显示。
怎么想:先引入iconfont.css,标签上写两个类名:iconfont是基础样式,icon-xxx是对应图标类名。
怎么做:引入样式表,再在标签上使用类名。

html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./fonts/iconfont.css">
<style>
.iconfont {
font-size: 300px;
color: pink;
}
</style>
</head>
<body>
<!-- 必须2个类名,第一个类名iconfont -->
<i class="iconfont icon-shouji"></i>
<span class="iconfont icon-zhaoxiangji"></span>
</body>
</html>易错点:必须写两个类名,第一个是iconfont;icon-xxx要和下载项目中的类名一致;样式表路径要正确;字体图标本质是字体,不能用图片思维随意换彩色图。
课件图示








代码示例
1. 子绝父相:相对定位 + 绝对定位
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>子绝父相</title>
<style>
.father {
/* 父级相对定位:不脱标、占位,作为绝对定位子级的参照 */
position: relative;
width: 300px;
height: 200px;
margin: 50px;
background-color: #fcc;
}
.father span {
/* 子级绝对定位:脱标、不占位,相对最近的定位祖先移动 */
position: absolute;
top: 0;
right: 0;
width: 80px;
height: 40px;
background-color: pink;
}
.normal {
width: 200px;
height: 80px;
background-color: skyblue;
}
</style>
</head>
<body>
<div class="father">
<span>绝对定位</span>
</div>
<div class="normal">标准流盒子</div>
</body>
</html>关键行和易错点:
.father { position: relative; }是“子绝父相”的父级关键行:相对定位不脱标、保留原位置,同时给绝对定位子级提供参照。.father span { position: absolute; top: 0; right: 0; }:绝对定位脱标、不占位,top/right相对最近的已定位祖先元素移动。- 易错点:父级忘记写
position: relative;时,绝对定位子级会相对浏览器可视区定位,容易“跑飞”。 - 绝对定位具备行内块特点,可以直接给宽高;但脱标后不占位,父级高度最好明确设置或由内容撑开。
2. 绝对定位盒子水平垂直居中
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>绝对定位居中</title>
<style>
* {
margin: 0;
padding: 0;
}
.box {
position: absolute;
/* 先移动父级/浏览器可视区的 50% */
left: 50%;
top: 50%;
/* 再让盒子走自身宽度、高度的一半 */
transform: translate(-50%, -50%);
width: 200px;
height: 200px;
background-color: pink;
/* 绝对定位后 margin: 0 auto; 失效 */
/* margin: 0 auto; */
}
</style>
</head>
<body>
<div class="box"></div>
</body>
</html>关键行和易错点:
position: absolute; left: 50%; top: 50%;:先把盒子左上角移动到参照容器的中心位置。transform: translate(-50%, -50%);:再向左、向上移动自身宽高的一半,实现盒子整体居中。- 易错点:只写
left: 50%; top: 50%;是盒子左上角到达中心,不是盒子整体居中。 translate的百分比相对于盒子自身宽高,不需要知道盒子具体尺寸;不要误认为它相对父级宽度。- 绝对定位后
margin: 0 auto;会失效,不能再用它做水平居中。
3. 固定定位顶部导航
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>固定定位</title>
<style>
* {
margin: 0;
padding: 0;
}
.header {
/* 固定定位:相对浏览器窗口定位,滚动页面时位置不变 */
position: fixed;
left: 0;
top: 0;
/* 固定定位具备行内块特点,通栏必须写 width: 100% */
width: 100%;
height: 80px;
background-color: pink;
z-index: 1;
}
.main {
/* 固定定位脱标不占位,下面内容会上去,需要留出头部高度 */
margin-top: 80px;
}
p {
line-height: 40px;
}
</style>
</head>
<body>
<div class="header">123</div>
<div class="main">
<p>里面有很多的文字</p>
<p>里面有很多的文字</p>
<p>里面有很多的文字</p>
<p>里面有很多的文字</p>
<p>里面有很多的文字</p>
<p>里面有很多的文字</p>
<p>里面有很多的文字</p>
<p>里面有很多的文字</p>
<p>里面有很多的文字</p>
<p>里面有很多的文字</p>
<p>里面有很多的文字</p>
<p>里面有很多的文字</p>
<p>里面有很多的文字</p>
<p>里面有很多的文字</p>
<p>里面有很多的文字</p>
<p>里面有很多的文字</p>
<p>里面有很多的文字</p>
<p>里面有很多的文字</p>
<p>里面有很多的文字</p>
<p>里面有很多的文字</p>
</div>
</body>
</html>关键行和易错点:
position: fixed; left: 0; top: 0;:固定定位相对浏览器窗口定位,页面滚动时盒子位置不变。width: 100%;:固定定位具备行内块特点,不写宽度时宽度由内容决定,顶部导航想通栏必须写width: 100%;。.main { margin-top: 80px; }:固定定位脱标、不占位,下面内容会钻到头部下面,需要给下面盒子留出与头部高度相同的距离。- 易错点:固定定位不需要父级定位,它始终相对浏览器窗口;同时写
left和right时,按“先左后右、先上后下”的规则处理。 z-index是整数,不要加单位;一般用于定位元素,取值越大层级越高。
常见错误
1. 子元素加了 absolute 后直接飞到页面左上角
- 现象:明明想让小图标待在卡片右上角,结果跑到整页最顶上去了。
- 原因:父级没有写
position,绝对定位找不到"最近已定位的祖先",只能参照浏览器可视区。 - 修法:写了
position: absolute的第一件事就是回头给父级补position: relative(子绝父相,形成条件反射)。
2. 绝对定位盒子用 margin: 0 auto 居不中
- 现象:
margin: 0 auto写了没反应,盒子仍贴左边。 - 原因:盒子一旦定位,
margin: 0 auto的水平居中逻辑失效,位置只认边偏移。 - 修法:
left: 50%; top: 50%; transform: translate(-50%, -50%);,别去算负 margin。
3. 居中偏了"半个自己"
- 现象:
left: 50%之后盒子右半边跑到中线右边,看着像没居中。 - 原因:只移动了父级的 50%,没有回退自身宽高的一半。
- 修法:补
transform: translate(-50%, -50%);用负 margin 时记得写负值且必须是自身尺寸的一半。
4. 固定顶部导航后,下面首屏内容被盖住一截
- 现象:导航固定住了,但 banner 顶部被压掉一段。
- 原因:固定定位脱标不占位,后面的盒子直接顶上来。
- 修法:给下面的内容盒(不是给导航)加
margin-top或padding-top,值等于导航高度。
5. 固定定位的导航"不通栏"
- 现象:导航只有文字那么宽,粉色背景缩成一小条。
- 原因:定位后具备行内块特点,不给宽度就由内容撑开。
- 修法:必须显式写
width: 100%(或具体宽度),不要指望它自动撑满。
6. z-index 写了没效果
- 现象:给盒子写了
z-index: 999还是被压住。 - 原因:
z-index只对定位元素生效;或者写成了999px带了单位。 - 修法:确认该元素有
position,值写纯整数不带单位,同时检查父级是否形成了层叠上下文。
7. 精灵图取到的位置是空白
- 现象:盒子空空如也,或者露出半张别的图。
- 原因:
background-position写成了正数(图往右下跑了),或盒子尺寸与小图不一致。 - 修法:坐标一律取负值;盒子宽高必须严格等于要截取的那张小图尺寸。
练习
练习 1|搜索框里的小相机 用 input + 一个定位的小图标,做出"相机图标压在输入框右端"的效果。要求:缩放浏览器时图标始终贴着输入框右侧;不许用 flex 的 position: relative 之外的取巧写法。
练习 2|万能居中卡片 一个 300×200 的卡片,在浏览器可视区里水平+垂直居中。要求分别用两种写法实现(负 margin 版 / transform 版),并说明哪种写法在尺寸改成 233×157 时不用重算。
练习 3|顶部固定导航 + 侧边小栏 复制昨天的学成在线页面,做两件事: ① 顶部导航改为固定定位,滚动时不动,且通栏、有阴影; ② 加一个 80×200 的侧边栏,要求放大缩小浏览器时它始终跟着版心(1200px)右边,不贴浏览器右边缘。提示:left: 50% + margin-left 推出版心一半的距离。
练习 4|精灵图 + 字体图标混排 用精灵图拼出自己名字的 3 个字母,再用字体图标做一排"手机 / 相机 / 购物车"小图标,统一调成 40px、粉色。要求:字母之间间距一致,图标和字母在同一行对齐。
练习 5|层叠顺序实验 三个 200×200 的盒子相互错开 20px 叠放,写三组 z-index 让显示顺序变成"蓝在最上、红在中、绿在最下",然后删掉 position 观察会发生什么,用一句话记录结论。
原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | 反馈和今日内容 | 02:30 |
| 2 | 相对定位 | 18:18 |
| 3 | 绝对定位 | 14:13 |
| 4 | 子绝父相 | 06:47 |
| 5 | 绝对定位盒子水平垂直居中 | 09:24 |
| 6 | 更简洁的写法 | 05:52 |
| 7 | 学成在线固定导航 | 14:43 |
| 8 | 侧边栏的做法 | 08:49 |
小结
- 定位永远是两件事:先选
position定模式,再写边偏移定位置,少写一半就不成立。 - 三种定位的差别只有一个问题的答案:"我是相对于谁在动"——相对是自己,绝对是最近的已定位祖先,固定是浏览器窗口。
- "要不要占位"决定选谁:需要压住别人就用绝对/固定(脱标),需要自己站住不挤乱页面就用相对(不脱标)。这是选型的第一判断。
- 子绝父相不是背诵口诀,而是推导结果:孩子要压住别人所以脱标,父亲要稳住布局所以不脱标,两者必须配对。
- 定位盒子的居中是固定套路:
50% / 50%+translate(-50%, -50%),不要再用margin: 0 auto,也不要每次去算负 margin。 - 固定定位有两个必踩的坑——不给宽度不通栏、不占位会盖住下面内容,写完立刻检查这两点。
- 侧边栏这类"跟着版心跑"的需求,用
left: 50%对齐中线再用margin-left推固定距离,比写right更稳,缩放时不会跑偏。 - 小图标的三种方案按场景选:颜色单一的小图标用字体图标(可改色改大小),多张零散背景图合成精灵图(减少请求),内容型图片才用 img 定位压层。