Skip to content

定位与精灵图(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,后期难维护。转写稿也提醒,类名应使用有意义的单词,多个单词可用短横线连接。

课堂画面 ​

课堂画面 1

课堂画面 2

课堂画面 3

课堂画面 4

课堂画面 5

课堂画面 6

代码示例 ​

示例一:定位元素居中 · 方案一(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 坐标。

常见错误 ​

  1. 定位元素居中后整体偏右下
    现象:left:50%; top:50% 后元素左上角在包含块中心,元素整体偏右下。
    原因:只居中了元素左上角,未用负外边距回退自身总宽高的一半;或回退时只按内容宽高算,漏了 padding、border。
    修法:用 margin-left: -自身总宽度/2; margin-top: -自身总高度/2;,总宽高包含内边距和边框。

  2. 四方向 0 + margin:auto 居中失效或元素被拉伸
    现象:写了 left/right/top/bottom:0 和 margin:auto,元素没有居中,或宽高表现异常。
    原因:元素没有固定宽高,或四个方向没写全,或漏写 margin:auto。
    修法:确认绝对/固定定位元素有明确宽高,四个方向都设为 0,再写 margin:auto。

  3. 精灵图显示错位或显示空白
    现象:背景图放上了,但元素里显示的不是目标图标,甚至什么都看不到。
    原因:background-position 方向写反,用了正坐标;或元素宽高与目标小图尺寸不一致。
    修法:按“背景图相对元素左上角移动”判断,通常用负的 X/Y 坐标;先量准小图尺寸并设置元素宽高。

  4. 重置样式表把自己的样式覆盖了
    现象:自己写的标题、列表、间距样式部分失效。
    原因:reset.css 引入顺序放在自己的 CSS 之后,或误以为重置后元素还保留默认样式。
    修法:先引入重置样式表,再引入自己的样式表;写样式前确认哪些默认样式已被重置。

  5. 通栏背景/边框被版心宽度限制
    现象:顶部条、分隔线、页脚背景没有铺满页面,只和内容区一样宽。
    原因:整页外面只包了一个固定宽度的版心容器,把通栏区域也包进去了。
    修法:通栏外层保持全宽,在需要内容对齐的区域内部再套固定宽度且水平居中的版心。

  6. 类名无意义或命名风格混乱
    现象:出现 a1、box2、aa_bb、aa-bb 混用,后期难维护。
    原因:没有使用有意义的单词,多个单词拼接时分隔符不统一,或滥用 ID。
    修法:用小写有意义单词,多单词统一用短横线连接;CSS 优先用类选择器,ID 只少量用于大区块或后续脚本。

练习 ​

  1. 写一个固定定位盒子,宽 400px、高 200px、左右内边距 20px,要求用“left/top:50% + 负 margin”方案在视口中横向纵向居中,写出关键 CSS。
  2. 在上题基础上,只要求横向居中、纵向不控制,应删除哪些声明?如果改成绝对定位,包含块应如何判断?
  3. 精灵图中目标小图位于大图坐标 (100, 0),元素尺寸为 120px × 56px,写出背景图定位;若目标位于 (48, 197),定位应怎么写?
  4. 页面已有 reset.css 和 index.css,请写出正确的引入顺序,并说明如果标题默认加粗消失应如何排查。
  5. 给定“顶部通栏 + 中间内容区 + 页脚通栏”的页面,请描述 HTML 结构应如何划分版心,避免通栏背景被限制宽度。

原视频对照 ​

#视频时长
1定位元素居中-方案一10:34
2定位元素居中-方案二03:01
3精灵图18:07
4重置样式表18:45
5版心05:04
6编码规范09:49

小结 ​

  1. 定位居中的关键是区分“元素左上角居中”和“元素整体居中”。
  2. 方案一依赖负外边距回退,计算时必须使用元素总宽高。
  3. 方案二写法更省算,但依赖固定宽高、四方向归零和 margin:auto。
  4. 精灵图的核心是控制大图在元素中的显示区域,坐标方向和元素尺寸都要准确。
  5. 重置样式表应先于业务样式引入,使用前要清楚它重置了哪些默认表现。
  6. 版心负责内容对齐,通栏负责铺满,二者通常通过“外层全宽、内层版心”组合实现。
  7. 类名应稳定、可读、风格统一;规范服务于协作和维护,不应混用分隔符。