主题
定位与精灵图(Day9 2/3)
本页对应 Day09_页面布局,共 6 段视频,约 1 小时 5 分。
学习目标
- 能使用
position: absolute/fixed配合left: 50%; top: 50%和负margin实现定位元素在包含块中水平垂直居中,并正确按元素总宽高计算偏移量。 - 能使用
left/right/top/bottom: 0配合margin: auto实现定位元素居中,并说明其适用定位类型及与方案一的差异。 - 能说明精灵图原理,使用
background-image与background-position在指定元素中显示精灵图中的目标小图,并解释其减少请求次数的作用。 - 能正确引入
reset.css重置样式表,说明重置样式表与normalize.css的核心区别,并保证自身样式表在重置样式之后引入。 - 能按“固定宽度 + 水平居中”的版心思路组织 PC 页面结构,并实现全宽区域与内部版心区域并存的布局。
- 能按编码规范为元素编写有意义的小写类名,使用短横线连接多个单词,并遵循颜色缩写、零值省略单位及常用 CSS 书写顺序等建议。
知识点
本节回顾的定位
这一节标题是“1 回顾”,重点不是继续堆新知识点,而是把前面学过的浮动和行内块元素布局重新串起来。转写稿后面讲了定位元素居中、精灵图、重置样式表、版心和命名规范,但本节笔记只回收浮动与行内块两条线,所以教程正文也按笔记范围展开,不把后续内容硬塞进来。转写稿里的“行为一块”应纠正为“行内块”,“复元素”应理解为“父元素”,“失口”应理解为“视口”。本节笔记没有附图片,因此不额外添加图片。
浮动:文字环绕
为什么需要: 浮动最初要解决的是图文混排问题,让文字能围绕图片排列,而不是只把浮动当成“横向排版工具”。
怎么想: 先回到浮动的基本目的:图片浮动后,文字围绕它。理解这一点,后面才不会把浮动的所有表现都当成布局技巧。
怎么做: 复习时先判断场景是不是“文字环绕”;如果是,就想到浮动;如果不是,再考虑它带来的排列和影响。
易错点: 只记“浮动可以并排”,却忘了文字环绕是浮动的本源,导致后面遇到浮动影响时只会背结论。
浮动元素的特点
为什么需要: 不理解浮动元素的特点,就无法判断它为什么会影响兄弟元素和父元素。
怎么想: 按笔记中的三条依次判断:①脱离文档流;②水平排列、自动换行;③不论原来的显示模式如何,设置为浮动就是浮动。
怎么做: 看到一个元素时,先看它有没有浮动;再看它是否还占普通文档流位置;最后看它原来的显示模式是否被浮动覆盖。
易错点: 以为行内元素设置了浮动还是行内元素;以为浮动元素还像普通元素一样占原来的文档流位置。转写稿里强调“行内块不用自己算就能居中”,说明显示模式会影响布局思路,但浮动会覆盖原显示模式,不能混着判断。
浮动元素的影响
为什么需要: 浮动脱离文档流后,最容易出现兄弟错位和父元素高度异常,排查时必须知道影响对象。
怎么想: 分两头看:对后面兄弟元素,可能产生覆盖或环绕;对父元素,因为浮动子元素脱离文档流,父元素可能不再被正常撑开。
怎么做: 复习时先问“父元素有没有包含浮动子元素”,再问“后面的兄弟有没有被浮动元素影响”。本节不展开具体清除浮动写法,先把影响路径记清楚。
易错点: 只盯浮动元素本身,忽略父元素和后面兄弟;一看到错位就改浮动元素,却不检查父元素高度和兄弟位置。
行内块元素布局:会被父元素当成文本
为什么需要: 行内块既有块级元素可设宽高的特点,又有行内元素的排列特点,父元素会把它当成文本处理,这直接决定居中和对齐思路。
怎么想: 先判断父元素是否把行内块当文本;如果是,就不能直接套纯块级的居中思路。
怎么做: 布局前先看父元素的文本环境,再决定用文本排列思路还是盒模型思路。
易错点: 拿块级元素的 margin: auto 直接套行内块;忽略父元素文本环境带来的空白和对齐问题。
行内块居中的思路
为什么需要: 居中很常用,但不同显示模式的参照物不同,混用方案就会失效。
怎么想: 转写稿在讲定位元素居中时强调:先设 left/top: 50%,发现只是左上角到了包含块中心,并不是整体居中,再用负 margin 偏移自身总宽高的一半。这个调试过程提醒我们:居中先问“参照物是谁、哪个点在居中”。行内块被父元素当文本,思路应回到父元素的文本处理,而不是照搬定位的负 margin 算法。
怎么做: 本节笔记只写到“居中”,没有展开具体属性,因此复习时先掌握判断路径:先确认行内块的父元素文本环境,再选择对应居中思路。
易错点: 把定位居中的方案误套到行内块;把行内块当纯块级元素处理。
行内块布局的典型问题
为什么需要: 行内块常出现左右空白、底部空白、对不齐,这些问题不一定是 margin 写错。
怎么想: 左右空白先想父元素是否把它当文本,源码换行和空格可能产生空白;底部空白先想行内块的基线对齐;对不齐则按“没有文字、一行文字、多行文字”分类看基线差异。
怎么做: 排查时先分类:是左右空白、底部空白,还是内容行数不同导致的对不齐;再回到行内块被父元素当文本这一根上。
易错点: 所有空白都归因于 margin;一套对齐方案套所有内容,不区分无文字、一行文字和多行文字。
回顾清单与自检
本节笔记的回顾清单保留如下:
1. 浮动
1.1 文字环绕
1.2 浮动元素的特点
① 脱离文档流
② 水平排列,自动换行
③ 不论原来的显示模式如何,设置为浮动就是浮动
1.3 浮动元素的影响
① 对后面兄弟元素
② 对父元素的影响
2. 行内块元素布局 会被父元素当成文本
2.1 居中
2.2 布局中的问题
① 左右空白
② 底部空白
③ 对不齐 没有文字、一行文字、多行文字自检时问自己:浮动为什么会影响父元素和兄弟?行内块为什么不能直接套块级居中?左右空白、底部空白、对不齐分别先查什么?能按“为什么需要→怎么想→怎么做→易错点”讲清楚,才算真正回顾到位。
定位元素居中:方案一
为什么需要:绝对定位、固定定位元素脱离文档流后,眼里只有包含块;固定定位的包含块是视口,绝对定位则要看最近的定位祖先。要让它在包含块中横向、纵向都居中,不能靠普通文档流的居中思路。
怎么想:先写 left:50%; top:50%,此时居中的是元素“左上角”,不是整体。调试时会看到元素偏右下,所以再把元素往左、往上各移动自身总宽、总高的一半。
怎么做:
css
.box {
position: fixed;
left: 50%;
top: 50%;
width: 400px;
height: 200px;
padding: 20px;
background-color: #900;
color: #fff;
margin-left: -220px; /* (400 + 20*2) / 2 */
margin-top: -120px; /* (200 + 20*2) / 2 */
}只做横向居中时,保留 left:50% 和 margin-left,不写 top、margin-top 即可。
易错点:负 margin 要用“总宽/总高”的一半,不能只算内容宽高;left/right 百分比参照包含块宽,top/bottom 百分比参照包含块高;绝对定位时要确认包含块到底是谁。
定位元素居中:方案二
为什么需要:方案一要算自身总宽高,元素尺寸变化后还要改负 margin。方案二想省掉计算。
怎么想:给固定或绝对定位元素同时设置 left:0; right:0; top:0; bottom:0;,再用 margin:auto 让浏览器分配剩余空间。转写稿里强调:这种写法原理不必深究,可理解为浏览器支持的便捷方案,不是按传统 W3C 规则推导出来的。
怎么做:
css
.box {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
width: 400px;
height: 200px;
padding: 20px;
margin: auto;
background-color: #900;
color: #fff;
}易错点:元素必须有固定宽高;四个方向和 margin:auto 要配套;兼容性以实际项目为准,不能把它当成所有场景都通用的标准推导。
精灵图:背景定位的应用
为什么需要:页面里很多小图标如果各自一张图,会增加服务器请求次数。把多张小图合并成一张大图,只请求一次,浏览器还会复用缓存,从而提高加载速度。
怎么想:元素小、背景图大,默认只显示背景图左上角。用 background-position 调整背景图在元素上的位置,负值向左、向上移动背景图,就能露出指定区域。
怎么做:
css
.btn1 {
width: 120px;
height: 56px;
border: none;
background: url("./images/bus.png") no-repeat -100px 0;
}
.btn2 {
width: 120px;
height: 56px;
border: none;
background: url("./images/bus.png") no-repeat right top;
}
.delete-icon {
width: 18px;
height: 18px;
background: url("./images/bus.png") no-repeat -48px -197px;
}坐标可用设计稿或精灵图工具量取。
易错点:坐标通常是负值;不要把“背景图移动方向”和“元素移动方向”弄反;精灵图一般由设计师合并,自己制作时可用工具生成图片和坐标。
重置样式表
为什么需要:标题、列表、段落等元素自带外边距、内边距、列表符号等默认样式,不同浏览器还可能不一致。先重置,大家起步一致,写样式更可控。
怎么想:reset.css 简单粗暴,把自带样式清掉;normalize.css 则重新设置一套统一标准。转写稿建议:如果设计稿没有采用 normalize 标准,优先用 reset。
怎么做:
html
<link rel="stylesheet" href="./css/reset.css">
<link rel="stylesheet" href="./css/index.css">先引入重置样式,再引入自己的样式,避免自己的样式被覆盖。
易错点:用了 reset 后,标题不粗不大、列表没符号是正常现象;发现元素样式“不对”,先想是不是被 reset 重置了;normalize 好用的前提是设计稿也遵循同一标准。
版心
为什么需要:PC 页面通常需要固定宽度并水平居中,避免内容随屏幕无限拉宽。但页面里又有通栏背景、通栏边框,不能用一个总版心把整页都包死。
怎么想:版心核心只有两点:固定宽度、水平居中。若某部分有通栏背景,就让外层通栏,内层再套版心。
怎么做:
css
.header {
background: #f5f5f5;
}
.header .inner,
.main .inner {
width: 1200px; /* 实际以设计稿为准 */
margin: 0 auto;
}易错点:不要用一个总版心包住所有通栏背景,否则背景无法通栏;每一部分内部套版心时,结构要分清“通栏层”和“内容层”。
编码规范
为什么需要:类名乱写如 A1、a_b,后期维护和协作都困难。规范命名能让结构一眼可读。
怎么想:用有意义的小写单词;多个单词用短横线连接;不要混用下划线和短横线;ID 不要滥用,CSS 优先用类。
怎么做:
css
/* 推荐 */
.news-box {}
.news-item {}
.btn-primary {}
/* 不推荐 */
.A1 {}
.a_b {}CSS 书写顺序可参考:定位 → 盒子模型(宽高、内外边距)→ 文字字体 → 背景边框等视觉样式。
易错点:短横线和下划线不要混用;命名要有含义;书写顺序只是建议,团队有规范时以团队规范为准。
精灵图要解决什么问题
为什么需要:页面里的小图标如果一张一张下载,请求次数会变多;请求次数多,页面打开就更容易变慢。转写稿里说得很直白:四个小图就要下载四次,合成一张大图只需要请求一次。浏览器还会缓存,第二个元素再用同一张大图时,不会重新去服务器下载。
怎么想:把很多小图片合并到一张大图上,这张大图就是精灵图。前端不直接用 img 把整张大图显示出来,而是把大图作为元素的背景图,再通过背景定位只露出需要的那一小块。
怎么做:一般由设计师做好精灵图;前端拿到图片后,给元素设置宽高、background-image 和 background-position。如果极端情况下要自己做,也可以用工具把小图拖进去生成 PNG,并拿到每块小图的坐标。
易错点:精灵图不是“新技术”,本质是背景图定位;元素本身必须有宽高,否则背景图没有显示区域。不要把整张大图直接当 img 塞进页面。
原理:元素小、背景图大,靠背景定位取局部
为什么需要:精灵图往往比单个元素大得多。转写稿中背景图是 54 × 207,而某个元素只有 25 × 23,所以元素只能显示大图的一部分。
怎么想:背景图的原点在元素左上角。默认情况下,元素显示的是背景图左上角那一块。要显示大图上的其他区域,就要把背景图往左、往上移动,因此 background-position 里常见负值。
怎么做:写 background-image: url(...),再写 background-position: x y。第一个值是横向,第二个值是纵向。要让背景图往左移,X 写负值;要往上移,Y 写负值。
易错点:正负方向容易反。X 写正值是往右偏,Y 写正值是往下偏,偏着偏着可能就把需要的图案偏没了。还要记住:设置的是“背景图在元素上的位置”,不是元素在页面里的位置。
从精灵图上量坐标
为什么需要:知道原理还不够,必须知道目标小图在大图上的坐标。转写稿中演示时,把图片放进马克鳗一类量图工具,鼠标放到目标区域,就能看到 X、Y 坐标。
怎么想:量出来的是目标块在大图上的位置。比如“即将开始”那块量到 X 是 100、Y 是 0,那么设置到元素上时应写成 -100px 0。删除图标量到大约 48、197,设置时就写成 -48px -197px。
怎么做:先量 X、Y,再把它们写成负值放进 background-position。如果目标在右上角,也可以根据情况用 right top 这类关键字,但坐标法更直观。
易错点:不要把量出来的正坐标直接写进去;不要用尺子硬量透明图边界,工具坐标更可靠。不同元素复用同一张精灵图时,坐标不要抄错。
写一个按钮示例
为什么需要:只看原理容易忘,写两个按钮最能感受“同一张背景图,只换位置”。
怎么想:两个按钮共用一张 bus.png,宽高按设计稿量。第一个按钮显示“即将开始”,第二个显示“即将结束”,再做一个删除小按钮。
怎么做:
html
<button class="btn btn1"></button>
<button class="btn btn2"></button>
<div class="delete-btn"></div>css
.btn {
width: 120px;
height: 56px;
border: none;
background-image: url("./images/bus.png");
background-repeat: no-repeat;
}
.btn1 {
background-position: -100px 0;
}
.btn2 {
background-position: right top;
}
.delete-btn {
width: 18px;
height: 18px;
display: inline-block;
background-image: url("./images/bus.png");
background-repeat: no-repeat;
background-position: -48px -197px;
}调试时可以先只写背景图,会看到默认露出左上角那块;再把 background-position 改成 -100px 0,图案就切到“即将开始”;删除按钮改成 -48px -197px 后,才会露出删除图标。
易错点:按钮自带边框,需要时用 border: none 去掉;元素宽高要和目标小图区域匹配;background-position 两个值顺序是“先 X 后 Y”。
精灵图的使用检查
为什么需要:精灵图容易“图放上了但显示不对”,检查顺序能快速定位问题。
怎么想:先确认元素有没有宽高,再确认背景图路径,再确认坐标正负和数值。
怎么做:按“宽高 → 背景图 → 是否重复 → 坐标”的顺序排查。多个元素共用一张图时,只改坐标,不重复换图。
易错点:坐标混用关键字和像素值;元素没有宽高导致看不见;精灵图更新后旧坐标失效;类名随意写成 a1、b2,后期难维护。转写稿也提醒,类名应使用有意义的单词,多个单词可用短横线连接。
课堂画面






代码示例
示例一:定位元素居中 · 方案一(left/top 50% + 负外边距)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>定位元素居中 - 方案一</title>
<style>
.box {
width: 400px;
height: 200px;
padding: 20px;
background: #900;
color: #fff;
position: fixed; /* 包含块 = 视口 */
left: 50%; /* 元素左上角对齐包含块横向中点 */
top: 50%; /* 元素左上角对齐包含块纵向中点 */
margin-left: -220px; /* 负的自身总宽一半:(400 + 20*2) / 2 */
margin-top: -120px; /* 负的自身总高一半:(200 + 20*2) / 2 */
}
</style>
</head>
<body>
<div class="box">我要在视口中居中</div>
</body>
</html>关键行与易错点
left/right的百分比参照包含块的宽,top/bottom的百分比参照包含块的高。固定定位的包含块是视口;换成absolute时,包含块是最近的定位祖先(不一定是父元素),值要按那个包含块算。left: 50%; top: 50%居中的是元素的左上角,不是元素整体,所以必须再用负外边距把元素往左、往上拽回“自身一半”。- 负外边距取的是总宽 / 总高的一半,包含
padding(和border),不是内容宽高。本例如写成-200px / -100px就会偏右下。 - 只想横向居中:只写
left: 50%和margin-left,不要写top和margin-top;只想纵向居中同理。 - 不要试图再用
position: relative去微调——一个元素只能有一个position值,已经fixed了就不能同时relative。
示例二:定位元素居中 · 方案二(四方向 0 + margin auto)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>定位元素居中 - 方案二</title>
<style>
.box {
width: 400px;
height: 200px;
padding: 20px;
background: #900;
color: #fff;
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto; /* 四个方向外边距都是 auto,元素被“挤”到中间 */
}
</style>
</head>
<body>
<div class="box">我要在视口中居中</div>
</body>
</html>关键行与易错点
- 好处是完全不用自己算一半宽高,也不用管
padding加了多少。 - 前提是元素必须有固定宽高:一旦宽或高是
auto,元素会直接撑满包含块,margin: auto就无从居中。 - 有固定宽高时,
left和right同时设置本来“没用”,这里能居中属于浏览器行为(转写稿称为“语法糖”),不必强行推导原理,会写会用即可。 - 同样适用于
absolute,只是居中的参照物变成绝对定位的包含块,不再是视口。
示例三:精灵图(background-position 截取大图局部)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>精灵图</title>
<style>
/* 假设精灵图 sprite.png 尺寸远大于各元素,图上坐标已量好 */
.btn {
width: 120px;
height: 56px;
border: none; /* 去掉 button 自带边框 */
background: url(./images/sprite.png) no-repeat;
}
/* 注意:background-position 必须写在 background 简写之后,否则被重置为 0 0 */
.btn1 { background-position: -100px 0; } /* 往左偏 100,取“即将开始” */
.btn2 { background-position: right top; } /* 该小图在大图右上角 */
.delete-btn {
display: inline-block; /* div 转行内块,才能和文字并排 */
width: 18px;
height: 18px;
background: url(./images/sprite.png) no-repeat -48px -197px;
}
</style>
</head>
<body>
<button class="btn btn1"></button>
<button class="btn btn2"></button>
<div class="delete-btn"></div>
</body>
</html>关键行与易错点
- 精灵图本质是:元素小、背景图大,用
background-position决定背景图在元素上的位置,从而只露出大图的某一块。原点永远是元素(不是图片)的左上角。 - 坐标基本都是负值(或 0):负值是把图片往左/往上推,才露得出后面/下面的部分;写正值会把图片推出元素外,什么也看不见。
- 量坐标的方法:在设计稿 / 图片查看器里把鼠标放到目标小图左上角,读出的 X、Y 就是偏移量,写成
-X -Y。 background复合属性会把background-position重置为0 0,所以位置要么写在简写里(url(...) no-repeat -48px -197px),要么写在简写之后的独立规则里。- 用
<button>模拟按钮时自带边框和背景色,必须border: none(背景反正会被自己的background覆盖)。 - 精灵图的意义:多张小图合成一张,减少 HTTP 请求次数,浏览器对同一张图只下载一次,页面打开更快;小图合并由设计师用工具生成,并会直接给出每个小图的 CSS 坐标。
常见错误
定位元素居中后整体偏右下
现象:left:50%; top:50%后元素左上角在包含块中心,元素整体偏右下。
原因:只居中了元素左上角,未用负外边距回退自身总宽高的一半;或回退时只按内容宽高算,漏了padding、border。
修法:用margin-left: -自身总宽度/2; margin-top: -自身总高度/2;,总宽高包含内边距和边框。四方向
0 + margin:auto居中失效或元素被拉伸
现象:写了left/right/top/bottom:0和margin:auto,元素没有居中,或宽高表现异常。
原因:元素没有固定宽高,或四个方向没写全,或漏写margin:auto。
修法:确认绝对/固定定位元素有明确宽高,四个方向都设为0,再写margin:auto。精灵图显示错位或显示空白
现象:背景图放上了,但元素里显示的不是目标图标,甚至什么都看不到。
原因:background-position方向写反,用了正坐标;或元素宽高与目标小图尺寸不一致。
修法:按“背景图相对元素左上角移动”判断,通常用负的X/Y坐标;先量准小图尺寸并设置元素宽高。重置样式表把自己的样式覆盖了
现象:自己写的标题、列表、间距样式部分失效。
原因:reset.css引入顺序放在自己的 CSS 之后,或误以为重置后元素还保留默认样式。
修法:先引入重置样式表,再引入自己的样式表;写样式前确认哪些默认样式已被重置。通栏背景/边框被版心宽度限制
现象:顶部条、分隔线、页脚背景没有铺满页面,只和内容区一样宽。
原因:整页外面只包了一个固定宽度的版心容器,把通栏区域也包进去了。
修法:通栏外层保持全宽,在需要内容对齐的区域内部再套固定宽度且水平居中的版心。类名无意义或命名风格混乱
现象:出现a1、box2、aa_bb、aa-bb混用,后期难维护。
原因:没有使用有意义的单词,多个单词拼接时分隔符不统一,或滥用 ID。
修法:用小写有意义单词,多单词统一用短横线连接;CSS 优先用类选择器,ID 只少量用于大区块或后续脚本。
练习
- 写一个固定定位盒子,宽
400px、高200px、左右内边距20px,要求用“left/top:50%+ 负margin”方案在视口中横向纵向居中,写出关键 CSS。 - 在上题基础上,只要求横向居中、纵向不控制,应删除哪些声明?如果改成绝对定位,包含块应如何判断?
- 精灵图中目标小图位于大图坐标
(100, 0),元素尺寸为120px × 56px,写出背景图定位;若目标位于(48, 197),定位应怎么写? - 页面已有
reset.css和index.css,请写出正确的引入顺序,并说明如果标题默认加粗消失应如何排查。 - 给定“顶部通栏 + 中间内容区 + 页脚通栏”的页面,请描述 HTML 结构应如何划分版心,避免通栏背景被限制宽度。
原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | 定位元素居中-方案一 | 10:34 |
| 2 | 定位元素居中-方案二 | 03:01 |
| 3 | 精灵图 | 18:07 |
| 4 | 重置样式表 | 18:45 |
| 5 | 版心 | 05:04 |
| 6 | 编码规范 | 09:49 |
小结
- 定位居中的关键是区分“元素左上角居中”和“元素整体居中”。
- 方案一依赖负外边距回退,计算时必须使用元素总宽高。
- 方案二写法更省算,但依赖固定宽高、四方向归零和
margin:auto。 - 精灵图的核心是控制大图在元素中的显示区域,坐标方向和元素尺寸都要准确。
- 重置样式表应先于业务样式引入,使用前要清楚它重置了哪些默认表现。
- 版心负责内容对齐,通栏负责铺满,二者通常通过“外层全宽、内层版心”组合实现。
- 类名应稳定、可读、风格统一;规范服务于协作和维护,不应混用分隔符。