Skip to content

小兔鲜儿(一) ​

本页对应 小兔鲜儿,共 8 段视频,约 1 小时 11 分。

学习目标 ​

  • 能够独立搭建热门品牌模块的通栏与版心结构,设置高度 468px、背景色 #F5,并复用头部结构完成标题区。
  • 能够完成热门品牌头部右侧按钮结构:与标题为兄弟关系的 .btn 容器、两个 href="javascript:;" 的链接及字体图标,并使用 Flex 横排、间距和绝对定位完成对齐。
  • 能够实现热门品牌内容区:UL/LI/A/IMG 结构、5 个列表项、LI 固定尺寸 244×306,并保证图片与列表项尺寸一致。
  • 能够搭建生鲜模块头部:版心内 HD/BD 结构,使用 flex: 1 将标题区域撑满以挤压右侧内容,设置列表项间距,并完成鼠标经过变色且文字不抖动。
  • 能够完成生鲜内容区域布局:左右分栏、左侧图片链接、右侧 UL 使用 Flex 换行实现两行两列,列表项固定尺寸 242×304。
  • 能够使用透明边框占位解决 hover 加边框导致的抖动问题,并在鼠标经过时将边框颜色改为绿色。

知识点 ​

结构:标题与按钮是兄弟关系 ​

为什么需要:热门品牌头部左边是“热门品牌 + 副标题”,右边是左右箭头按钮。按钮要独立控制,不能塞进标题里,否则结构和样式都会互相干扰。
怎么想:在 .hd 里放两个并列子元素:h2 管标题,.btn 管两个箭头,二者是兄弟关系。
怎么做:按笔记写 h2 和 .btn,按钮用 a,并写 href="javascript:;",避免点击后跳到页面顶部。
易错点:不要写 href="#";不要把 .btn 放进 h2;span 是副标题,不要误写成主标题。

横排:用 flex 管两个箭头按钮 ​

为什么需要:左右两个箭头要在一行,并且宽高、背景、间距统一。
怎么想:父级 .btn 用 display:flex,两个 a 自动成为一行;每个 a 固定 20×20,再用 margin-left:12px 拉开距离。
怎么做:给 .brand .btn a 设置宽高、背景 #e2e2e2、文字白色,并用 text-align:center 与 line-height:20px 让图标水平垂直居中。
易错点:a 默认是行内元素,若父级不是 flex,单独设宽高可能不生效,需要 display:block/inline-block;margin-left 会给第一个也加左边距,视觉可接受,精确可用 gap 或 :first-child。

定位:按钮贴右,父级相对定位 ​

为什么需要:按钮要贴在头部右侧,又不能用外边距把标题和父盒子挤乱。
怎么想:让 .brand .hd 作为定位参照,.btn 绝对定位,right:0 贴右,top:85px 做视觉微调。
怎么做:.brand .hd { position:relative; },.brand .btn { position:absolute; top:85px; right:0; display:flex; }。
易错点:不要用 margin-top 调 .btn。转写稿调试时发现,.hd 没有固定高度,给子盒子加外边距会把父盒子撑大,甚至带着 h2 一起走;绝对定位脱离标准流,才不会影响标题。父级相对定位要限定在 .brand .hd,避免影响其他模块的 .hd。

高亮:右按钮用变量色,并处理层叠 ​

为什么需要:右箭头要显示绿色高亮,左箭头保持灰色。
怎么想:两个按钮共用 .brand .btn a 的基础样式,再单独给 .btnright 换背景色 var(--lv)。
怎么做:写 .brand .btn .btnright { background-color: var(--lv); }。
易错点:转写稿中颜色一开始没生效,调试时不要猜,打开开发者工具选中元素:若没有黄色感叹号,说明选择器没写错,而是被上面的 .brand .btn a 层叠了;提高权重到 .brand .btn .btnright 即可覆盖。变量 --lv 要确保已定义。

完整代码与检查 ​

以下保留本节笔记代码:

html
<!-- hd  -->
<div class="hd">
  <h2>热门品牌
    <span>国际经典 品质认证</span>
  </h2>
  <!-- 按钮   button-->
  <div class="btn">
    <a href="javascript:;" class="btnleft">
      <i class="iconfont icon-arrow-left-bold"></i>
    </a>
    <a href="javascript:;" class="btnright">
      <i class="iconfont icon-arrow-right-bold"></i>
    </a>
  </div>
</div>
css
/* brand里面的hd 加相对定位 */
.brand .hd {
  position: relative;
}

.brand .btn {
  position: absolute;
  top: 85px;
  right: 0;
  display: flex;
}

.brand .btn a {
  width: 20px;
  height: 20px;
  background-color: #e2e2e2;
  margin-left: 12px;
  text-align: center;
  line-height: 20px;
  color: #fff;
}

.brand .btn .btnright {
  background-color: var(--lv);
}

检查清单:.btn 与 h2 是否兄弟;a 是否写 javascript:;;.hd 是否相对定位;.btn 是否绝对定位并贴右;两个 a 是否横排;宽高、居中、间距、右按钮绿色是否生效。本节只完成头部右侧结构和样式,点击滚动属于后续 JavaScript 轮播逻辑。

本节把“热门品牌”拆成通栏盒子、版心、头部标题、左右按钮和图片列表五块来写。核心思路是:先搭大盒子,再套版心,最后填内容和调细节。

整体盒子与版心 ​

为什么需要:热门品牌有整块浅灰底色,需要通栏;内容又要居中,所以必须“大盒子套版心”。
怎么想:先写 .brand 给高度和背景色,再在里放 .wrapper,不要一上来抠图片。
怎么做:.brand 高 468px、背景 #f5f5f5,并用 margin-top:50px 与上方拉开距离;.wrapper 负责版心。
易错点:大盒子套小盒子时,小盒子写 margin-top 可能发生外边距塌陷,把父盒子一起带下来;这时优先给父盒子或头部用 padding 挤开。

html
<!-- 热门品牌 brand -->
<div class="brand">
  <div class="wrapper">
    <!-- hd -->
    <div class="hd">
      <h2>热门品牌
        <span>国际经典 品质认证</span>
      </h2>
      <!-- 按钮 button -->
      <div class="btn">
        <a href="javascript:;" class="btnleft">
          <i class="iconfont icon-arrow-left-bold"></i>
        </a>
        <a href="javascript:;" class="btnright">
          <i class="iconfont icon-arrow-right-bold"></i>
        </a>
      </div>
    </div>
    <!-- bd -->
    <div class="bd">
      <ul>
        <li><a href="#"><img src="./uploads/hot1.png" alt="热门品牌1"></a></li>
        <li><a href="#"><img src="./uploads/hot2.png" alt="热门品牌2"></a></li>
        <li><a href="#"><img src="./uploads/hot3.png" alt="热门品牌3"></a></li>
        <li><a href="#"><img src="./uploads/hot4.png" alt="热门品牌4"></a></li>
        <li><a href="#"><img src="./uploads/hot5.png" alt="热门品牌5"></a></li>
      </ul>
    </div>
  </div>
</div>

头部标题与按钮结构 ​

为什么需要:头部左边是标题,右边是轮播箭头,二者要在一行内分别靠左、靠右。
怎么想:复用前面模块的 .hd 结构,标题用 h2,说明文字放 span;按钮 .btn 与 h2 是兄弟关系。
怎么做:.hd 内先写标题,再写 .btn,里面放两个 a,每个 a 内放字体图标 i。
易错点:按钮链接不要写 href="#",否则点击会跳回顶部;写 javascript:;。按钮不要塞进 h2 里,避免结构混乱。

左右按钮样式与调试 ​

为什么需要:两个箭头要并排、有大小、有底色,并且右侧按钮用主题绿色。
怎么想:两个 a 共用宽高和底色,父级 .btn 用 display:flex 让它们一行排列;右侧单独覆盖背景色。
怎么做:a 宽高 20px,背景 #e2e2e2,text-align:center、line-height:20px、文字白色;.btnright 用 var(--lv)。
易错点:颜色不生效时不要猜,先看选择器权重和层叠。笔记里 .brand .btn .btnright 比 .brand .btn a 更具体,能覆盖底色;a 默认是行内元素,靠父级 flex 后宽高才稳定生效。

按钮定位与头部微调 ​

为什么需要:按钮要贴到头部右侧指定位置,又不能把标题和头部撑大。
怎么想:用定位让按钮脱离标准流,父级 .hd 加 position:relative,.btn 加 position:absolute。
怎么做:.brand .hd{position:relative},.brand .btn{position:absolute;top:80px;right:0;display:flex}。转写稿调试时试过 85px,最后按效果回到笔记的 80px。
易错点:不要用 margin-top 硬推按钮,按钮变高会把 .hd 撑大,标题也会跟着动;定位后记得给父级相对定位,否则会找错参照物。

内容区图片列表 ​

为什么需要:下方是五张品牌图,需要统一尺寸,后续做轮播时让 ul 滚动。
怎么想:bd 里放 ul,ul 里放 li,li 里放 a 和 img;先固定每个 li 的大小。
怎么做:.brand .bd li{width:244px;height:306px},图片按该尺寸显示。
易错点:不要直接改所有 .bd li,要限定在 .brand .bd li,避免影响其他模块;图片尺寸不一致时先固定 li,再处理图片适配。

css
/* 热门品牌 */
.brand {
  height: 468px;
  background-color: #f5f5f5;
  margin-top: 50px;
}

/* brand里面的hd 加相对定位 */
.brand .hd {
  position: relative;
}

.brand .btn {
  position: absolute;
  top: 80px;
  right: 0;
  display: flex;
}

.brand .btn a {
  width: 20px;
  height: 20px;
  background-color: #e2e2e2;
  margin-left: 12px;
  text-align: center;
  line-height: 20px;
  color: #fff;
}

.brand .btn .btnright {
  background-color: var(--lv);
}

.brand .bd li {
  width: 244px;
  height: 306px;
}

生鲜模块标题效果图

先搭结构:标题区为什么这样分 ​

生鲜标题区要同时放三样东西:模块标题“生鲜”、一排分类导航、右侧“查看全部”。所以不能只写一个 h2,而要有一个头部容器 hd 把三者组织起来。转写稿里反复强调“先把大盒子、版心写出来,再考虑里面的内容”,这里也是同样思路:外层 wrapper 负责版心,里面先放 hd,再填 h2、ul、a.all。

html
<!-- 生鲜模块 -->
  <div class="wrapper">
    <!-- 上侧 hd  -->
    <div class="hd">
      <h2>生鲜</h2>
      <ul>
        <li><a href="#">热门</a></li>
        <li><a href="#">蔬菜</a></li>
        <li><a href="#">肉禽蛋</a></li>
        <li><a href="#">水果</a></li>
        <li><a href="#">海鲜</a></li>
        <li><a href="#">零食</a></li>
        <li><a href="#">饮料</a></li>
      </ul>

      <a href="#" class="all">
        查看全部
        <i class="iconfont icon-arrow-right-bold"></i>
      </a>
    </div>
  </div>

这里易错点是把 ul 或“查看全部”塞进 h2 里。它们应是 hd 下的兄弟关系:h2 是标题,ul 是导航,a.all 是操作入口。先保证结构清楚,后面才方便用 Flex 布局。

让导航横排:ul 先变成 Flex ​

li 默认是块级元素,会一行一个竖着排。笔记里先给出一句核心样式:

css
/* 生鲜 */
.hd ul {
  display: flex;
}

为什么需要它?因为分类项必须横向排列。怎么想?不要急着给每个 li 加浮动,直接把它们的父级 ul 设为 display:flex,让子项自动在一行上排列。怎么做?先写这一句,观察“热门、蔬菜、肉禽蛋……”是否横排。

易错点是:只给 ul 加 Flex 只能解决 li 横排;如果 h2、ul、“查看全部”仍然上下分行,还要检查 hd 这一层是否也具备 Flex 布局。转写稿中提到头部依赖 hd 的 Flex 能力,实际调试时可用检查工具看 hd 的 display 是否为 flex。

用 h2 { flex:1 } 把右侧内容挤过去 ​

转写稿里最关键的一步,是没有用固定 margin-left 把导航推到右边,而是给“生鲜”标题加 flex:1。原因是分类文字可能多也可能少,写死距离后,内容一变布局就难看。思路是:h2 和右侧内容宽度由内容决定,中间剩余空间全部给 h2,它占满后,ul 和“查看全部”自然被挤到右侧。

为避免影响页面中其他 hd,转写稿中给生鲜模块加了 fresh 这一层区分,选择器写成:

css
.fresh .hd h2 {
  flex: 1;
}

易错点:flex:1 要加在 h2 上,不是加在 ul 上;选择器要限定在生鲜模块内,不要写成全局 .hd h2,否则其他模块头部也会被改变。若发现没生效,先用调试工具确认选择器是否命中、父级是否已经是 Flex 容器。

调间距和悬停:先占位,再换色 ​

分类项之间需要距离,转写稿中给 li 加右侧外边距,约 13px;导航整体与“查看全部”之间再留出距离。链接本身要给左右 padding,这样鼠标悬停时背景色有可点击区域。悬停时只换背景色和文字色,不要让盒子尺寸突然变化。

css
.fresh .hd ul li {
  margin-right: 13px;
}

.fresh .hd ul {
  margin-right: 65px;
}

.fresh .hd ul a {
  padding: 0 5px;
}

.fresh .hd ul a:hover {
  background-color: #00b45a;
  color: #fff;
}

易错点:padding 应写在常态的 a 上,hover 里只改颜色;如果把 padding 只写在 hover 里,鼠标经过时文字会“抖”一下。调试距离时不要猜,直接打开检查工具看盒模型,确认是 margin 还是 padding 在起作用。这样生鲜标题区的结构、横排、右推和悬停反馈就完整了。

先看目标:生鲜头部要排成一行 ​

生鲜模块的头部结构并不复杂:左侧是标题“生鲜”,中间是一组分类导航,右侧是“查看全部”。本节笔记截取的是 .hd 部分,外层通常还会有生鲜模块和版心容器,用来限制内容宽度。写之前先想清楚:标题、导航、查看全部三者要在同一行;导航内部的多个 li 也要在同一行;鼠标经过导航链接时要有绿色底色和白色文字。因此布局重点不是堆样式,而是先把 HTML 的兄弟关系和父子关系写对。

结构:h2、ul、a.all 是兄弟关系 ​

笔记中的 HTML 如下,h2、ul、a.all 都放在 .hd 里面,它们是兄弟关系。这样后面才能用 flex 让三者排成一行。

html
 <!-- 上侧 hd  -->
    <div class="hd">
      <h2>生鲜</h2>
      <ul>
        <li><a href="#">热门</a></li>
        <li><a href="#">蔬菜</a></li>
        <li><a href="#">肉禽蛋</a></li>
        <li><a href="#">水果</a></li>
        <li><a href="#">海鲜</a></li>
        <li><a href="#">零食</a></li>
        <li><a href="#">饮料</a></li>
        <li><a href="#">海鲜</a></li>
        <li><a href="#">零食</a></li>
        <li><a href="#">饮料</a></li>
      </ul>

      <a href="#" class="all">
        查看全部
        <i class="iconfont icon-arrow-right-bold"></i>
      </a>
    </div>

为什么需要先确认结构?因为“查看全部”必须和 ul 平级,不能塞进 ul 或某个 li 里;否则 flex 的排列对象就变了。怎么想?把 .hd 看成一排三个子盒子:标题、导航、查看全部。怎么做?保持上面结构不动,样式统一加在 .hd 及其子元素上。

让 ul 和 li 一行显示 ​

笔记 CSS 先处理导航:

css
/* 让生鲜模块里面的li 一行显示 */
.hd ul {
  display: flex;
  margin-right: 65px;
}

.hd ul li {
  margin-right: 13px;
}

.hd ul li a {
  padding: 0 5px;
}

/* 鼠标经过添加底色和文字颜色 */
.hd ul li a:hover {
  background-color: var(--lv);
  color: #fff;
}

.fresh .hd h2 {
  flex: 1;
}

.hd ul 加 display: flex,是为了让多个 li 横向排列;li 的 margin-right: 13px 是分类之间的间距;a 的 padding: 0 5px 是给文字左右留出空间,这样 hover 背景不会只贴着文字。易错点:不要只在 :hover 里加 padding,否则鼠标经过时盒子尺寸变化,文字会抖动。正确做法是默认状态先给 a 左右 padding,hover 只换背景色和文字颜色。

h2 用 flex:1 把右侧内容推过去 ​

.fresh .hd h2 { flex: 1; } 是关键。为什么需要?因为标题字数少,导航和“查看全部”要根据内容宽度靠右,不能写死左边距。怎么想?.hd 本身是 flex 容器时,h2 设置 flex: 1 会占满剩余空间,于是 ul 和 .all 被推到右侧。怎么做?只对生鲜模块下的 h2 设置,避免影响其他模块的 .hd h2。易错点:不要给 h2 写死宽度,也不要用很大的 margin-left 硬挤,因为分类文字数量变化时布局会不自然。.hd ul 上的 margin-right: 65px 用来把导航和“查看全部”拉开距离。

调试顺序:先一行,再间距,最后 hover ​

实际写的时候按这个顺序检查:先看 .hd 是否一行,再看 ul 内 li 是否一行,然后调 li 间距和 ul 右边距,最后给 a 加 padding 和 hover。若发现“查看全部”掉下去,优先检查 .hd 是否 flex、h2 是否 flex:1;若 hover 时文字抖动,检查 a 默认是否已有左右 padding;若其他模块头部被影响,检查 flex:1 是否限定在 .fresh .hd h2 下。这样这一节生鲜头部就完成了。

课件图示(PPTX) ​

day12 课件图

day12 课件图

day12 课件图

代码示例 ​

1. 热门品牌:头部右侧按钮 + 内容区 ​

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>热门品牌</title>
<style>
  :root { --lv: #00be9c; }        /* 占位:项目里用的是全局变量 --lv */
  * { margin: 0; padding: 0; }
  ul { list-style: none; }
  a { text-decoration: none; }
  .wrapper { width: 1240px; margin: 0 auto; }

  /* 热门品牌:通栏大盒子 */
  .brand {
    height: 468px;
    background-color: #f5f5f5;
    margin-top: 50px;
  }

  /* brand里面的hd 加相对定位 */
  .brand .hd {
    position: relative;
    padding-top: 40px;           /* 用内边距把标题挤下来,具体值按设计稿 */
  }
  .brand .hd h2 { font-size: 28px; font-weight: 400; }
  .brand .hd h2 span { font-size: 14px; color: #999; margin-left: 12px; }

  .brand .btn {
    position: absolute;
    top: 85px;
    right: 0;
    display: flex;               /* 让两个 a 在一行 */
  }
  .brand .btn a {
    width: 20px;
    height: 20px;
    background-color: #e2e2e2;
    margin-left: 12px;
    text-align: center;
    line-height: 20px;
    color: #fff;
  }
  .brand .btn .btnright { background-color: var(--lv); }

  /* 内容区 */
  .brand .bd ul { display: flex; }
  .brand .bd li {
    width: 244px;
    height: 306px;
  }
  .brand .bd li img { width: 100%; height: 100%; display: block; }
</style>
</head>
<body>
  <!-- 热门品牌 brand -->
  <div class="brand">
    <div class="wrapper">
      <!-- hd  -->
      <div class="hd">
        <h2>热门品牌
          <span>国际经典 品质认证</span>
        </h2>
        <!-- 按钮   button-->
        <div class="btn">
          <a href="javascript:;" class="btnleft">
            <i class="iconfont icon-arrow-left-bold"></i>
          </a>
          <a href="javascript:;" class="btnright">
            <i class="iconfont icon-arrow-right-bold"></i>
          </a>
        </div>
      </div>
      <!-- bd  -->
      <div class="bd">
        <ul>
          <li><a href="#"><img src="./uploads/hot1.png" alt=""></a></li>
          <li><a href="#"><img src="./uploads/hot2.png" alt=""></a></li>
          <li><a href="#"><img src="./uploads/hot3.png" alt=""></a></li>
          <li><a href="#"><img src="./uploads/hot4.png" alt=""></a></li>
          <li><a href="#"><img src="./uploads/hot5.png" alt=""></a></li>
        </ul>
      </div>
    </div>
  </div>
</body>
</html>

要点:

  • .brand 是通栏盒子(给高 + #f5f5f5),里面再套 .wrapper 版心,这是"通栏套版心"的标准写法。
  • .hd 必须加 position: relative,否则 .btn 的 position: absolute 会去找更外层的定位祖先。
  • 按钮不能用 margin-top 往下推:.btn 在 .hd 里,margin/padding 都会把 .hd 撑大,连带把 h2 顶下去;只有定位脱离标准流,才"爱咋调咋调",不影响别人。
  • 标题下移用 padding-top,不要给子盒子 margin-top——大盒子套小盒子时子盒子的 margin-top 会发生外边距塌陷,把父盒子一起带跑。
  • 权重坑:.brand .btnright(两个类)会被 .brand .btn a(两个类+标签)层叠掉,所以必须写 .brand .btn .btnright(三个类)。调不出来时先看调试工具里样式有没有被划掉。
  • 按钮 a 写 href="javascript:;",写 # 点一下会跳回页面顶部。
  • .brand .bd li 前面一定要带 .brand,直接写 .bd li 会污染页面上其它模块。

2. 生鲜模块头部(h2 + 分类 ul + 查看全部) ​

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>生鲜头部</title>
<style>
  :root { --lv: #00be9c; }
  * { margin: 0; padding: 0; }
  ul { list-style: none; }
  a { text-decoration: none; color: #333; }
  .wrapper { width: 1240px; margin: 0 auto; }

  /* 生鲜 */
  .fresh .hd {
    display: flex;
    align-items: center;
    padding-top: 40px;
  }
  .fresh .hd h2 {
    flex: 1;                     /* 占满剩余空间,把 ul 和“查看全部”挤到右边 */
    font-size: 28px;
    font-weight: 400;
  }

  .hd ul { display: flex; margin-right: 65px; }
  .hd ul li { margin-right: 13px; }
  .hd ul li a { padding: 0 5px; }
  /* 鼠标经过添加底色和文字颜色 */
  .hd ul li a:hover { background-color: var(--lv); color: #fff; }

  .fresh .all { font-size: 14px; color: #999; }
</style>
</head>
<body>
  <!-- 生鲜模块 -->
  <div class="fresh">
    <div class="wrapper">
      <!-- 上侧 hd  -->
      <div class="hd">
        <h2>生鲜</h2>
        <ul>
          <li><a href="#">热门</a></li>
          <li><a href="#">蔬菜</a></li>
          <li><a href="#">肉禽蛋</a></li>
          <li><a href="#">水果</a></li>
          <li><a href="#">海鲜</a></li>
          <li><a href="#">零食</a></li>
          <li><a href="#">饮料</a></li>
        </ul>
        <a href="#" class="all">
          查看全部
          <i class="iconfont icon-arrow-right-bold"></i>
        </a>
      </div>
    </div>
  </div>
</body>
</html>

要点:

  • .fresh .hd 加 display: flex,h2、ul、.all 三个子元素才会排成一行;ul 自己再加 display: flex 让 li 一行显示。
  • 中间那块"自动被挤到右边"靠的是 h2 { flex: 1 } 一等份:两侧宽度由内容决定,剩下的全给 h2,ul 和"查看全部"就被顶到右边。不能写死 margin-left,分类文字多了少了就错位。
  • 间距:li 给 margin-right: 13px 拉开字间距,ul 给 margin-right: 65px 和"查看全部"拉开。
  • a 的 padding: 0 5px 必须一开始就给,只在 :hover 里加背景色。如果 hover 时才加 padding,文字会被"推一下",出现抖动。
  • h2 必须用 .fresh .hd h2 限定,直接改 .hd h2 会影响到上面其它模块的 hd。

3. 生鲜模块内容区(左右布局 + 右侧两行两列) ​

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>生鲜内容区</title>
<style>
  :root { --lv: #00be9c; }
  * { margin: 0; padding: 0; }
  ul { list-style: none; }
  a { text-decoration: none; }
  .wrapper { width: 1240px; margin: 0 auto; }

  /* 内容区域:分左右,所以不用 bd,另起 content */
  .fresh .content {
    display: flex;
    justify-content: space-between;
    margin-top: 20px;
  }
  .fresh .content .left {
    width: 248px;
    height: 610px;
    background-color: pink;      /* 占位,实际放图片 */
  }
  .fresh .content .left img { width: 100%; height: 100%; display: block; }

  .fresh .content .right {
    width: 968px;
    height: 610px;
    background-color: skyblue;   /* 占位 */
  }
  .fresh .content .right ul {
    display: flex;
    flex-wrap: wrap;             /* 强制换行 → 两行两列 */
  }
  .fresh .content .right ul li {
    width: 242px;
    height: 304px;
    border: 2px solid transparent;   /* 先占位,避免 hover 抖动 */
  }
  .fresh .content .right ul li:hover {
    border-color: var(--lv);
  }
</style>
</head>
<body>
  <div class="fresh">
    <div class="wrapper">
      <div class="content">
        <div class="left">
          <a href="#"><img src="./uploads/fresh_left.png" alt=""></a>
        </div>
        <div class="right">
          <ul>
            <li></li><li></li><li></li><li></li>
            <li></li><li></li><li></li><li></li>
          </ul>
        </div>
      </div>
    </div>
  </div>
</body>
</html>

要点:

  • 这里结构是左右分,和上面的 .bd 不一样,所以另起 content 盒子,别复用 bd。
  • left / right 是高频类名,选择器必须带上 .fresh、.content 限定:.fresh .content .left,否则会误伤页面其它地方。
  • 父盒子 display: flex + justify-content: space-between,左右两块自动贴两边。
  • 右侧 ul 只写 display: flex 是一行排开;要两行两列必须再加 flex-wrap: wrap。
  • 边框坑:li 的宽高按 hover 态量(242×304)。如果平时不给边框、:hover 才加 border,边框会占位把内容往里挤,出现"抖一下";正确做法是先给 border: 2px solid transparent 占位,hover 只改 border-color。
  • 图片建议加 display: block(或给 img { width:100% }),否则 img 底部会多出几像素空隙。

常见错误 ​

  1. 热门品牌标题区被整体带下来 / 上间距失效
    现象:.brand .hd 加 margin-top 后,整个 .brand 被一起带下或间距异常。
    原因:大盒套小盒,子盒 margin-top 触发外边距塌陷。
    修法:子盒改用父盒 padding-top;需要整体下移时调 .brand 的 margin-top。

  2. 右侧左右按钮把标题区撑高、影响标题垂直位置
    现象:给 .btn 加 margin-top 后,h2 跟着移动或 .hd 高度变化。
    原因:普通流盒子的 margin/padding 会参与父盒尺寸计算。
    修法:.brand .hd 设 position: relative,.btn 设 position: absolute; top/right,不占文档流。

  3. .btnright 背景色不生效
    现象:写了 .brand .btn .btnright { background-color: var(--lv); } 但仍是灰色。
    原因:被 .brand .btn a 的同等或更高层叠规则覆盖,或选择器权重不足。
    修法:开发者工具看划掉规则;提高权重,如 .brand .btn a.btnright 或 .brand .btn .btnright 并确认书写顺序。

  4. 点击左右箭头页面跳到顶部
    现象:点按钮后页面瞬间回到顶部。
    原因:a 的 href="#" 触发锚点跳转。
    修法:占位链接写 href="javascript:;",后续接轮播逻辑。

  5. 按钮里的 a 不横排、尺寸不生效
    现象:左右箭头竖排,或宽高设置无效。
    原因:a 是行内元素,父级未建立横向布局。
    修法:父级 .btn 用 display:flex;给 a 明确宽高、text-align、line-height。

  6. 生鲜导航项 hover 时文字抖动
    现象:鼠标移入后文字左右跳动。
    原因:初始没给 padding,hover 才加背景/内边距,盒模型尺寸变化。
    修法:初始就给 a 固定 padding: 0 5px;hover 只改 background-color 和 color。

  7. 生鲜右侧 li 鼠标经过加边框时内容抖动
    现象:hover 后 li 内图片/文字向内缩。
    原因:初始无边框,hover 才加边框,边框占位改变盒模型。
    修法:初始写透明边框 border: 2px solid transparent;hover 只改 border-color。

  8. 生鲜右侧 8 个 li 全挤在一行
    现象:只写了一行,未形成两行两列。
    原因:父级只设了 display:flex,未允许换行。
    修法:给 ul 加 flex-wrap: wrap,并限定作用域如 .fresh .content .right li。

  9. 样式污染其他模块
    现象:改 .bd li 或 .hd ul li 后,热门品牌、生鲜等模块互相影响。
    原因:选择器范围过大,复用了公共类名。
    修法:加最近模块父级限定,如 .brand .bd li、.fresh .hd ul li。

  10. 结构嵌套写错,bd 写进 hd 里
    现象:内容区样式错乱、按钮定位异常、后续选择器全受影响。
    原因:写 HTML 时未先闭合 hd,复制结构后未检查层级。
    修法:先闭合 hd 再写 bd;复制模块后先折叠检查父子关系。

练习 ​

  1. 热门品牌头部右侧按钮
    要求:.hd 内左侧标题、右侧两个箭头按钮;按钮横排、右对齐、a 不跳顶部;左按钮灰底、右按钮主题绿;用绝对定位放到标题区右下侧。
    验收:点击按钮页面不跳顶;.btn 不影响 h2 位置;.btnright 背景色生效。

  2. 生鲜头部自适应一行
    要求:h2 + ul + 查看全部 同一行;h2 占剩余空间,ul 靠右;增加/删除若干 li 后,查看全部 仍贴右且不重叠。
    验收:不写死中间大段 margin;增减导航项后布局仍稳定。

  3. 生鲜导航 hover 防抖
    要求:导航 a 初始就有左右内边距;hover 只改变背景色和文字颜色。
    验收:鼠标移入移出文字不左右抖动,背景和文字颜色切换正常。

  4. 生鲜内容右侧两行两列
    要求:.right 内 ul > li 共 8 项,两行两列;每个 li 固定宽高;hover 显示主题色边框。
    验收:ul 能换行;hover 前后内容不位移;样式不影响热门品牌 li。

  5. 层叠问题排查
    要求:故意让 .btnright 背景色被 .btn a 覆盖,用开发者工具定位被划掉的规则,再通过提高权重或调整顺序修复。
    验收:能指出是“层叠/权重”问题而非写错类名,并给出修复后的选择器。

原视频对照 ​

#视频时长
1热门品牌模块头部开始05:20
2热门品牌模块头部右侧制作07:56
3热门品牌头部完成13:19
4热门品牌bd部分结束04:13
5生鲜模块头部开始06:06
6生鲜模块头部调整中间距离09:49
7生鲜模块内容区域布局13:31
8生鲜模块小li修改10:53

小结 ​

  1. 先搭模块大盒与版心,再补头部、内容区,结构层级正确优先于样式微调。
  2. 模块样式必须加父级作用域,避免 .hd、.bd、li、a 等公共类互相污染。
  3. 不影响文档流的小控件优先用绝对定位;父级记得建立定位上下文。
  4. 一行内“左中右”自适应,优先用 flex:1 吃掉剩余空间,不写死大间距。
  5. 交互态要预留占位:hover 改颜色可以,hover 才加 padding 或 border 容易抖动。
  6. 调样式不生效时先看开发者工具:看层叠划掉、看继承来源、看选择器权重,不靠猜。
  7. 占位链接用 javascript:;,避免 # 造成页面跳顶。
  8. 模块完成后先折叠检查再复制,复制后立即改类名与作用域,减少结构性 bug。