主题
页面布局-新闻列表与页面布局-图标列表(Day10)
本页对应 Day10_页面布局,共 2 段视频,约 36 分钟。
学习目标
- 能够根据设计稿将右侧区域拆分为“新闻列表”和“图标列表”两个模块,并写出包含标题、更多链接、无序列表及超链接的语义化 HTML 结构。
- 能够运用盒模型为新闻模块设置宽度、高度、边框和内边距,并解释块元素不显式设置宽度时总宽度不超出父容器的原因。
- 能够根据文字尺寸与行间间距推算行高,通过设置
line-height使新闻列表条目间距与设计稿一致。 - 能够使用浮动与清除浮动完成新闻标题的左右布局,以及图标列表“一行四个、自动换行”的多列布局。
- 能够计算图标列表项尺寸并设置宽高,使 12 个列表项按四列三行排列且整体尺寸符合设计稿。
- 能够使用精灵图背景定位为不同图标设置对应背景位置,并定位、修复因背景透明导致的层叠显示问题。
知识点
先看整体:右栏拆成“新闻”和“图标列表”
为什么需要:右栏细节多、文字多,如果直接堆标签,后面调样式会找不到对应关系。怎么想:先按设计稿把右栏分成上下两块,上面是新闻区,下面是图标列表区。怎么做:外层用 section-right,里面放 news 和 icons;新闻区再分标题和列表。易错点:命名要统一,转写稿里的 newose、iconss 是口误/同音,落到代码里应整理为 news、icons。
原笔记未附可引用图片,以下按转写稿口述尺寸记录:右栏约 290×458,新闻区高约 156,图标区约 290×290,精灵图 192×144。
html
<section class="section-right">
<div class="news">
<div class="news-title">
<h3>商品快报</h3>
<a href="#">更多 ></a>
</div>
<ul class="news-list">
<li><a href="#">超大容量的满足</a></li>
<li><a href="#">每日一件,衣柜满到塞不下</a></li>
<li><a href="#">媳妇再美,我就敷给他看</a></li>
<li><a href="#">更多新闻标题</a></li>
</ul>
</div>
</section>新闻区:宽度、边框和内边距
为什么需要:新闻区是右栏上部的独立卡片,需要边框和左右留白。怎么想:宽度不重复写,让它跟父级一样宽;高度按设计稿约 156,边框算在总宽内。怎么做:.news 设 height:156px; border:1px solid #d9d9d9; padding:0 14px;。易错点:块元素不设宽度时会撑满父级内容区,加边框和内边距不会把总宽撑大,而是往里挤;不要再多写一个固定宽度。
css
.section-right {
width: 290px;
height: 458px;
float: right;
}
.news {
height: 156px;
border: 1px solid #d9d9d9;
padding: 0 14px;
}新闻标题:左右浮动与清除浮动
为什么需要:标题左边是“商品快报”,右边是“更多 >”,必须一左一右。怎么想:h3 左浮动,a 右浮动;父级要清浮动,否则高度塌陷。怎么做:.news-title 设 height:38px; line-height:38px; border-bottom:1px solid #d9d9d9;,并清浮动;h3 字号调到 14px。易错点:有浮动就要清浮动,转写稿反复提醒的 clearfix 不能忘;“>”在 HTML 中有特殊含义,用字符实体 >。
css
.news-title {
height: 38px;
line-height: 38px;
border-bottom: 1px solid #d9d9d9;
overflow: hidden; /* 简易清浮动 */
}
.news-title h3 {
float: left;
font-size: 14px;
}
.news-title a {
float: right;
}新闻列表:用行高推间距
为什么需要:新闻条目之间要有约 12px 的视觉间距。怎么想:文字区约 14px,两行间距约 12px,把一行行高做成 26px,上下各分一半间距,列表看起来就均匀。怎么做:给 .news-list li 设 line-height:26px;,文字大小约 12px。易错点:不要急着上下加 margin,先用行高整体控制;行高是“文字行盒”的高度,不是单纯字间距,调完要刷新对比设计稿。
css
.news-list li {
line-height: 26px;
font-size: 12px;
}图标列表:UL + LI + 浮动排格子
为什么需要:图标列表是一行四个、共三行的格子。怎么想:可以用表格,也可以更轻地用 ul>li 浮动,每个格子等宽等高,自动换行。怎么做:把 icons 做成 ul,每个 li 里放 a,a 里放两个 span:图片区和文字区。宽高按 290÷3≈96.66,转写稿最终取 96px,高也 96px,li 左浮动。易错点:一开始容易误算成 290÷4=72.5,但一行要放 4 个,列数应按 3 列算;li 浮动后父级要清浮动。
html
<ul class="icons">
<li>
<a href="#">
<span class="icon-image" style="background-position:-144px -96px;"></span>
<span class="icon-text">话费</span>
</a>
</li>
<!-- 其余 li 同理 -->
</ul>css
.icons {
height: 290px;
overflow: hidden;
}
.icons li {
float: left;
width: 96px;
height: 96px;
}
.icon-image {
display: block;
width: 48px;
height: 48px;
margin: 12px auto 0;
background: url("./icon-list.png") no-repeat;
}
.icon-text {
display: block;
height: 24px;
line-height: 24px;
font-size: 14px;
text-align: center;
}精灵图定位:算坐标而不是逐张量
为什么需要:12 个小图标如果拆成 12 张图,请求多、管理乱。怎么想:整张精灵图 192×144,每个小图 48×48,横向 4 个、纵向 3 个;用 background-position 负坐标取图。怎么做:例如话费取 -144px -96px,火车票 -96px -96px,加油卡 -48px -96px,白条 0 -96px;第二排电影票 -144px -48px 等。易错点:坐标是“负的左上偏移”,不是正数;图顺序可能被打乱,要按实际图位置写行内 background-position,调试时可先给 icon-image 加红色背景确认区域。
调试:子菜单透明导致“透图”
为什么需要:写完精灵图后发现下方内容透出来,说明上层容器没有背景。怎么想:不是精灵图错,而是下拉子菜单背景透明。怎么做:回到 .sub-menu 加白色背景,如 background:#fff;,并适当加宽到约 690px 盖住精灵图区域。易错点:这类问题只有页面元素叠在一起才暴露;调试时先查层级和背景,不要盲目改定位。
小结
这一节核心不是背代码,而是按设计稿拆结构:右栏→新闻区→标题/列表;图标区→ul>li>a>span;再用宽度、内边距、行高、浮动和精灵图坐标逐步逼近设计稿。尺寸量不准时先算格子,再刷新微调;有浮动就清浮动,有透明遮挡就补背景。
先搭结构:图标列表用 UL + LI 组织
为什么需要:图标列表是“多行多列、每项都可点击”的模块,用无序列表最贴合语义,也方便统一控制每格尺寸。
怎么想:外层是 section-right,下面分新闻区和图标区;图标区用 ul.icons,每项 li 里放一个超链接 a,a 内再分“图片 span”和“文字 span”。
怎么做:
html
<div class="section-right">
<!-- 新闻区省略 -->
<ul class="icons">
<li>
<a href="#">
<span class="icon-image" style="background-position:-144px -96px;"></span>
<span class="icon-text">话费</span>
</a>
</li>
<li>
<a href="#">
<span class="icon-image" style="background-position:-96px -96px;"></span>
<span class="icon-text">火车票</span>
</a>
</li>
<!-- 其余 li 同理:加油卡、白条、电影票、酒店、理财、机票等 -->
</ul>
</div>易错点:span 默认是行内元素,直接设宽高无效;后面必须配合 display:block。另外类名别写成 iconss、newose 这类转写同音错字。
尺寸推导:290÷3,不是÷4
为什么需要:每格宽高不统一,浮动后就会参差不齐。
怎么想:图标区总宽 290px,一行放 3 个,所以 290÷3≈96.66,实操取 96px;总高 290px。
怎么做:
css
.icons {
height: 290px;
}
.icons li {
width: 96px;
height: 96px;
float: left;
list-style: none;
}
/* 别忘了清除浮动,课程中用 clearfix 处理 */易错点:转写稿里一开始按 290÷4 算成 72.5px,这是算错了列数;按 4 列做会明显偏窄。li 浮动后必须清除浮动,否则父容器高度会出问题。
格子内部:图片 48×48,文字 24 高
为什么需要:每格要“上图下文”,而且整体要纵向居中。
怎么想:图片区 48×48,文字区高 24、行高 24、字号 14;li 高 96,内容共 48+24=72,剩余 24,上下各 12,所以图片 span 给 margin-top:12px。
怎么做:
css
.icons .icon-image {
display: block;
width: 48px;
height: 48px;
margin: 12px auto 0;
background: url(./icon-list.png) no-repeat;
}
.icons .icon-text {
display: block;
height: 24px;
line-height: 24px;
font-size: 14px;
text-align: center;
}易错点:span 不加 display:block 就设不了宽高;文字要居中,可用 text-align:center;图片区居中用 margin:0 auto 或 margin:12px auto 0。
精灵图坐标:横向 4 个、纵向 3 个
为什么需要:多个小图标合成一张精灵图,减少请求。
怎么想:总图 192×144,每个小图 48×48,正好横向 4 个、纵向 3 个。坐标公式:x = -列号×48,y = -行号×48。
怎么做:按实际图位置写行内 background-position,例如:
html
<span class="icon-image" style="background-position:-144px -96px;"></span> <!-- 话费 -->
<span class="icon-image" style="background-position:-96px -96px;"></span> <!-- 火车票 -->
<span class="icon-image" style="background-position:-48px -96px;"></span> <!-- 加油卡 -->
<span class="icon-image" style="background-position:0 -96px;"></span> <!-- 白条 -->
<span class="icon-image" style="background-position:-144px -48px;"></span> <!-- 电影票 -->
<span class="icon-image" style="background-position:-96px -48px;"></span> <!-- 酒店 -->
<span class="icon-image" style="background-position:-48px -48px;"></span> <!-- 理财 -->
<span class="icon-image" style="background-position:0 -48px;"></span> <!-- 机票 -->易错点:坐标是负值;顺序是 x y;路径要写 ./icon-list.png;精灵图顺序若被打乱,要按实际图找位置,不能死记“第几个”。
调试:透明背景暴露的 bug
为什么需要:图标图出来后,发现下面菜单把精灵图透出来了。
怎么想:不是图片错,而是 submenu 没加背景色,默认透明。
怎么做:给 submenu 加白色背景,并适当加大宽度到约 690px,刚好盖住精灵图。
易错点:不写背景色时,前期没图看不出来,后期加图才暴露;这类问题要回到父级背景和层叠关系排查。
课堂画面


代码示例
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>页面布局-新闻列表</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
padding: 20px;
}
.section-right {
width: 290px;
height: 458px;
float: right;
}
.news {
height: 156px;
border: 1px solid #d9d9d9;
padding: 0 14px;
}
.news-title {
height: 38px;
line-height: 38px;
border-bottom: 1px solid #d9d9d9;
}
.news-title h3 {
float: left;
font-size: 14px;
}
.news-title a {
float: right;
font-size: 12px;
text-decoration: none;
color: #333;
}
.clearfix::after {
content: "";
display: block;
clear: both;
}
.news-list {
list-style: none;
}
.news-list li {
line-height: 26px;
font-size: 12px;
}
.news-list li a {
text-decoration: none;
color: #333;
}
</style>
</head>
<body>
<div class="section-right">
<div class="news">
<div class="news-title clearfix">
<h3>商品快报</h3>
<a href="#">更多 ></a>
</div>
<ul class="news-list">
<li><a href="#">超大容量的满足</a></li>
<li><a href="#">每日一件儿,衣柜满到塞不下</a></li>
<li><a href="#">媳妇儿再美,我就敷给他看</a></li>
</ul>
</div>
</div>
</body>
</html>要点解释:
.section-right固定宽度290px、高度458px,右侧区域尺寸先定好,后续新闻和图标列表都受它约束。.news设置height:156px,配合box-sizing:border-box,让高度包含边框,避免总高变成158px。.news-title内部h3左浮动、a右浮动,所以必须给标题容器加.clearfix,否则父容器高度塌陷。- “更多 >” 中的
>用字符实体>,不能直接写>,避免被浏览器当成标签符号。 .news-list li用line-height:26px控制新闻行距,这是转写稿中按文字区域和间距推算出来的做法。- 易错点:
h3、ul默认有外边距,需先重置;新闻标题是超链接,记得写a并处理下划线。
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>页面布局-图标列表</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
padding: 20px;
}
.section-right {
width: 290px;
height: 458px;
}
.icons {
height: 290px;
margin-top: 12px;
list-style: none;
}
.icons li {
float: left;
width: 72.5px;
height: 96.66px;
}
.icons a {
display: block;
text-decoration: none;
color: #333;
}
.icon-image {
display: block;
width: 48px;
height: 48px;
margin: 12px auto 0;
background-image: url("./icon-list.png");
background-repeat: no-repeat;
}
.icon-text {
display: block;
height: 24px;
line-height: 24px;
font-size: 14px;
text-align: center;
}
.clearfix::after {
content: "";
display: block;
clear: both;
}
</style>
</head>
<body>
<div class="section-right">
<ul class="icons clearfix">
<li>
<a href="#">
<span class="icon-image" style="background-position: -144px -96px;"></span>
<span class="icon-text">话费</span>
</a>
</li>
<li>
<a href="#">
<span class="icon-image" style="background-position: -96px -96px;"></span>
<span class="icon-text">火车票</span>
</a>
</li>
<li>
<a href="#">
<span class="icon-image" style="background-position: -48px -96px;"></span>
<span class="icon-text">加油卡</span>
</a>
</li>
<li>
<a href="#">
<span class="icon-image" style="background-position: 0 -96px;"></span>
<span class="icon-text">白条</span>
</a>
</li>
<li>
<a href="#">
<span class="icon-image" style="background-position: -144px -48px;"></span>
<span class="icon-text">电影票</span>
</a>
</li>
<li>
<a href="#">
<span class="icon-image" style="background-position: -96px -48px;"></span>
<span class="icon-text">酒店</span>
</a>
</li>
<li>
<a href="#">
<span class="icon-image" style="background-position: -48px -48px;"></span>
<span class="icon-text">理财</span>
</a>
</li>
<li>
<a href="#">
<span class="icon-image" style="background-position: 0 -48px;"></span>
<span class="icon-text">机票</span>
</a>
</li>
</ul>
</div>
</body>
</html>要点解释:
.icons高度按设计稿设为290px,margin-top:12px用来衔接上方新闻列表,使右侧区域总高接近156 + 12 + 290 = 458px。li的宽度按290 / 4 = 72.5px计算,高度按290 / 3 ≈ 96.66px计算,配合float:left实现一行四个、自动换行。.icon-image是span,行内元素不能直接设宽高,所以必须写display:block;再用width:48px; height:48px定位精灵图小格。- 精灵图通过
background-image和行内background-position定位,坐标用负值取图;例如话费为-144px -96px。 .icon-text同样要display:block,并设置height:24px; line-height:24px,让文字在自身区域内垂直居中。- 易错点:
li浮动后父级ul要清除浮动;精灵图路径./icon-list.png要按实际文件位置修改;示例保留转写稿中已给出定位的 8 个图标,后 4 个可按同样方式继续补。
常见错误
新闻标题区一左一右浮动后,下面的列表整体往上顶 现象:
news-title里的 H3 和“更多”浮起来后,news-list的第一行贴到了标题文字上。 原因:两个子元素浮动脱离文档流,父容器news-title高度塌陷成 0,只剩边框撑着。 修法:在news-title上清除浮动(加 clearfix 或overflow: hidden),保证父级高度包含浮动子元素。列表项之间用 margin 调间距,最后一行多出一截,总高对不上设计稿 现象:逐条量出 12px 间距,写成
li { margin-bottom: 12px },第四条下面凭空多 12px,news高度撑破 156px。 原因:间距应该是“相邻两行之间”的,margin 只加在下边,等于每行间距 12px,但末行下方也留了一份;行高方式是把间距对半分给上下。 修法:用行高控制(26px 行高、12px 字),末项例外可用li:last-child { margin-bottom: 0 },或改回行高方案。给
news设了 290 宽又加 1px 边框,右侧溢出或换行 现象:width: 290px; border: 1px solid #d9d9d9后,盒子实际 292px,超出section-right,右边缘被裁或换行。 原因:标准盒模型下 border 计入总宽,块元素本来就会撑满父级内容区,再写死宽度等于重复计算。 修法:块元素不写 width,让边框往里挤;必须写宽时用box-sizing: border-box。精灵图只有第一张能显示,其余全是同一张图或空白 现象:给所有
.icon-image加了background-image后,12 个格子全显示第一个图标。 原因:只设了背景图没设background-position,默认取左上角;或坐标顺序写反(先 Y 后 X)、漏写负号。 修法:background-position先 X 后 Y,取值一律为负的 48 的倍数;写完一个立刻刷新验证一个,不要批量写完再一起看。span设了宽高没反应,图片区挤成一条线 现象:.icon-image { width: 48px; height: 48px }完全不生效。 原因:span是行内元素,宽高对行内元素无效。 修法:加display: block(或干脆在结构里用 div)。图标一行放不下 4 个,自动换行变成 3 列 现象:290 宽容器里 4 个格子排不下,第 4 个被挤到下一行。 原因:格子尺寸除错(290÷3 当成 ÷4),或给 LI 额外加了边框、内边距、右外边距。 修法:宽高按 290÷3≈96.66 算,去掉 LI 的一切额外盒模型属性;不确定时先给容器一个背景色,用肉眼卡边界。
子菜单或下拉层没写背景色,底下的精灵图透上来 现象:单独看子菜单正常,等图标列表写完后,下拉面板里出现了图标残影。 原因:面板背景透明,下层内容直接透出;之前没内容所以看不出来。 修法:给浮层面板补
background: #fff,并顺带把宽度加大到能盖住下方元素(如 690px)。
练习
按设计稿还原“商品快报”模块:
section-right宽 290、总高 458,news四周 1px 灰边、左右内边距 14,标题区 38px 带底边框,列表 4 条,行间距视觉上为 12px。要求不写死news的宽度,并说明你如何保证总高与设计稿一致。列表间距分别用“行高法”和“margin 法”各实现一遍,量出两种方案下第 1 行顶部到第 4 行底部的总高,说明差在哪、为什么行高法更贴近设计稿。
用一张 192×144 的精灵图实现 12 个图标(每格 48×48),要求:一行 4 个自动换行、图标水平居中、图文整体在格子里垂直居中。请写出第 1、6、12 个图标的
background-position计算过程。现有一个 290 宽的容器要放 4 个格子。分别按 290÷4 和 290÷3 各做一版,观察换行与留白差异,说明哪种符合设计稿、误差如何消化(取整 96 还是 96.66)。
把 12 个图标的定位从行内样式重构成类名方式(
.ic-image01~.ic-image12),并思考:如果图标顺序被设计师打乱,你的代码需要改几处?
原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | 页面布局-新闻列表 | 15:02 |
| 2 | 页面布局-图标列表 | 21:56 |
小结
- 这类“地方不大、细节挺多”的模块,正确顺序永远是:先量尺寸 → 再写结构 → 最后逐块调样式,不要一边写 HTML 一边猜 CSS。
- 浮动必清浮动,这是条件反射;只要写了
float,下一件事就是找父级加 clearfix。 - 块元素不设宽度就会自动撑满父级内容区,边框和内边距只会往里挤不会撑宽——利用这一点可以少算很多尺寸。
- 相邻文字的间距优先用行高对半分,比 margin 更可控,也不会在首尾多出多余空白。
- 精灵图不需要逐个量图,总图尺寸 ÷ 单格尺寸就能反推出网格,坐标永远是 48 的负倍数。
- 布局里的取整误差(96 与 96.66)要主动消化:宁可留 1~2px 空白,也不要让第 4 个格子换行。
- 尺寸对不上时不要死磕,先把容器背景色打开、把元素描出来看,视觉反馈比计算更快定位问题。
- 很多 bug 是写到后面才暴露的(如浮层透明),所以要边写边刷新,别攒到最后一起调。