Skip to content

页面布局-新闻列表与页面布局-图标列表(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="#">更多 &gt;</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 中有特殊含义,用字符实体 &gt;。

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,刚好盖住精灵图。
易错点:不写背景色时,前期没图看不出来,后期加图才暴露;这类问题要回到父级背景和层叠关系排查。

课堂画面 ​

课堂画面 1

课堂画面 2

代码示例 ​

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="#">更多 &gt;</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,否则父容器高度塌陷。
  • “更多 >” 中的 > 用字符实体 &gt;,不能直接写 >,避免被浏览器当成标签符号。
  • .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 个可按同样方式继续补。

常见错误 ​

  1. 新闻标题区一左一右浮动后,下面的列表整体往上顶 现象:news-title 里的 H3 和“更多”浮起来后,news-list 的第一行贴到了标题文字上。 原因:两个子元素浮动脱离文档流,父容器 news-title 高度塌陷成 0,只剩边框撑着。 修法:在 news-title 上清除浮动(加 clearfix 或 overflow: hidden),保证父级高度包含浮动子元素。

  2. 列表项之间用 margin 调间距,最后一行多出一截,总高对不上设计稿 现象:逐条量出 12px 间距,写成 li { margin-bottom: 12px },第四条下面凭空多 12px,news 高度撑破 156px。 原因:间距应该是“相邻两行之间”的,margin 只加在下边,等于每行间距 12px,但末行下方也留了一份;行高方式是把间距对半分给上下。 修法:用行高控制(26px 行高、12px 字),末项例外可用 li:last-child { margin-bottom: 0 },或改回行高方案。

  3. 给 news 设了 290 宽又加 1px 边框,右侧溢出或换行 现象:width: 290px; border: 1px solid #d9d9d9 后,盒子实际 292px,超出 section-right,右边缘被裁或换行。 原因:标准盒模型下 border 计入总宽,块元素本来就会撑满父级内容区,再写死宽度等于重复计算。 修法:块元素不写 width,让边框往里挤;必须写宽时用 box-sizing: border-box。

  4. 精灵图只有第一张能显示,其余全是同一张图或空白 现象:给所有 .icon-image 加了 background-image 后,12 个格子全显示第一个图标。 原因:只设了背景图没设 background-position,默认取左上角;或坐标顺序写反(先 Y 后 X)、漏写负号。 修法:background-position 先 X 后 Y,取值一律为负的 48 的倍数;写完一个立刻刷新验证一个,不要批量写完再一起看。

  5. span 设了宽高没反应,图片区挤成一条线 现象:.icon-image { width: 48px; height: 48px } 完全不生效。 原因:span 是行内元素,宽高对行内元素无效。 修法:加 display: block(或干脆在结构里用 div)。

  6. 图标一行放不下 4 个,自动换行变成 3 列 现象:290 宽容器里 4 个格子排不下,第 4 个被挤到下一行。 原因:格子尺寸除错(290÷3 当成 ÷4),或给 LI 额外加了边框、内边距、右外边距。 修法:宽高按 290÷3≈96.66 算,去掉 LI 的一切额外盒模型属性;不确定时先给容器一个背景色,用肉眼卡边界。

  7. 子菜单或下拉层没写背景色,底下的精灵图透上来 现象:单独看子菜单正常,等图标列表写完后,下拉面板里出现了图标残影。 原因:面板背景透明,下层内容直接透出;之前没内容所以看不出来。 修法:给浮层面板补 background: #fff,并顺带把宽度加大到能盖住下方元素(如 690px)。

练习 ​

  1. 按设计稿还原“商品快报”模块:section-right 宽 290、总高 458,news 四周 1px 灰边、左右内边距 14,标题区 38px 带底边框,列表 4 条,行间距视觉上为 12px。要求不写死 news 的宽度,并说明你如何保证总高与设计稿一致。

  2. 列表间距分别用“行高法”和“margin 法”各实现一遍,量出两种方案下第 1 行顶部到第 4 行底部的总高,说明差在哪、为什么行高法更贴近设计稿。

  3. 用一张 192×144 的精灵图实现 12 个图标(每格 48×48),要求:一行 4 个自动换行、图标水平居中、图文整体在格子里垂直居中。请写出第 1、6、12 个图标的 background-position 计算过程。

  4. 现有一个 290 宽的容器要放 4 个格子。分别按 290÷4 和 290÷3 各做一版,观察换行与留白差异,说明哪种符合设计稿、误差如何消化(取整 96 还是 96.66)。

  5. 把 12 个图标的定位从行内样式重构成类名方式(.ic-image01~.ic-image12),并思考:如果图标顺序被设计师打乱,你的代码需要改几处?

原视频对照 ​

#视频时长
1页面布局-新闻列表15:02
2页面布局-图标列表21:56

小结 ​

  1. 这类“地方不大、细节挺多”的模块,正确顺序永远是:先量尺寸 → 再写结构 → 最后逐块调样式,不要一边写 HTML 一边猜 CSS。
  2. 浮动必清浮动,这是条件反射;只要写了 float,下一件事就是找父级加 clearfix。
  3. 块元素不设宽度就会自动撑满父级内容区,边框和内边距只会往里挤不会撑宽——利用这一点可以少算很多尺寸。
  4. 相邻文字的间距优先用行高对半分,比 margin 更可控,也不会在首尾多出多余空白。
  5. 精灵图不需要逐个量图,总图尺寸 ÷ 单格尺寸就能反推出网格,坐标永远是 48 的负倍数。
  6. 布局里的取整误差(96 与 96.66)要主动消化:宁可留 1~2px 空白,也不要让第 4 个格子换行。
  7. 尺寸对不上时不要死磕,先把容器背景色打开、把元素描出来看,视觉反馈比计算更快定位问题。
  8. 很多 bug 是写到后面才暴露的(如浮层透明),所以要边写边刷新,别攒到最后一起调。