Skip to content

小兔鲜儿(二) ​

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

学习目标 ​

  1. 能独立完成底部帮助模块的 DT/DD 结构样式,包括字号、间距、链接颜色、悬停下划线及字体图标定位。
  2. 能使用 Flex 布局将帮助模块各 DL 横向排列,并完成右侧二维码图片与说明文字的布局和尺寸控制。
  3. 能编写版权模块的 P、A、span 结构,实现链接分隔线、水平居中、行高、颜色及悬停变色效果。
  4. 能搭建首页 banner 的版心、UL、LI、A、IMG 结构,并设置高度、背景色和溢出隐藏。
  5. 能通过 Flex 与 UL 宽度百分比使轮播图片横向排列,并说明 overflow: hidden 的裁剪作用。
  6. 能使用绝对定位、伪元素、圆角、rgba 和 active 类完成小圆点布局及激活态效果,并设置鼠标指针样式。

知识点 ​

结构:用 ul 作为轮播图轨道 ​

为什么需要:banner 区域不是一张静态图,而是多张图组成轮播。后续要用 JS 切换图片时,最好把图片放在同一条“轨道”里,点击左右箭头或小圆点只移动轨道,而不是临时改每一张图的位置。

怎么想:一条轨道用 ul,每一张图用 li,图片外面包 a,这样图片本身可点击跳转。小圆点先不急着写,只留注释占位,避免结构一开始就混在一起。

怎么做:保留本节笔记结构,图片 alt 改成中文,方便说明图片内容:

html
<!-- 轮播图图片 -->
<ul>
  <li><a href="#"><img src="./uploads/banner1.png" alt="轮播图图片"></a></li>
  <li><a href="#"><img src="./uploads/banner1.png" alt="轮播图图片"></a></li>
  <li><a href="#"><img src="./uploads/banner1.png" alt="轮播图图片"></a></li>
</ul>
<!-- 小圆点 -->

易错点:不要把“小圆点”的 li 混进图片 ul 里;图片 alt 不要留空;src 路径要指向 uploads 下真实存在的图片。

横向排列:给 ul 加 flex ​

为什么需要:li 默认是块级元素,会一张一张竖着排。轮播图需要三张图横向组成一条轨道。

怎么想:让 li 在一行上,最直接的是给它们的父级 ul 加 display:flex。这样 ul 的子项会沿主轴横向排列。

怎么做:

css
.banner .wrapper>ul {
  display: flex;
  width: 300%;
  /* width: 3720px; */
}

易错点:只写 display:flex 还不够。转写稿里调试时发现,ul 默认宽度大约等于父级 .wrapper 的宽度,flex 会把三个 li 压进父宽里,图片会变窄。所以还要继续处理 ul 的宽度。

宽度推导:300% 与 3720px ​

为什么需要:轮播轨道要能同时容纳三张图。如果 ul 只有父级那么宽,flex 会压缩子项,三张图挤在一起,图片被拉扁或缩小。

怎么想:父级 .wrapper 是版心,转写稿中宽度约 1240px。三张图就需要约 1240 × 3 = 3720px 的轨道宽度。写成 width:300% 表示父级宽度的 3 倍;写成 3720px 是固定值写法。笔记里两种都保留,固定值被注释掉。

怎么做:优先用百分比,图片数量变化时更好改:

css
.banner .wrapper>ul {
  display: flex;
  width: 300%;
  /* width: 3720px; */
}

调试时可打开检查工具看 ul 的实际宽度。转写稿中验证到:写 300% 后,ul 实际宽度为 3720px,说明三张图有足够空间。

易错点:3720px 是按父级 1240px 算出来的,父级宽度变了就不能照抄;如果轮播图是 4 张,倍数要改成 400%;还要保证 li 或图片有明确宽度,否则仍可能被 flex 压缩。

溢出隐藏与验证 ​

为什么需要:ul 比 .wrapper 宽,后面两张图会露到版心外面。轮播图默认只应看到当前一张。

怎么想:让有固定宽度的父级 .wrapper 把超出部分裁掉,而不是裁 .banner 通栏背景。转写稿调试时就是把 overflow:hidden 加在 .wrapper 上。

怎么做:在 .banner .wrapper 上设置溢出隐藏,刷新后只看到第一张图;检查工具里第二、第三个 li 仍然存在,只是被裁掉,后续学 JS 后再做切换动画。

易错点:overflow:hidden 不要加在通栏 .banner 上,否则可能裁不到版心内的轨道;也不要误以为第二、三张图被删了,它们只是被隐藏。

小圆点:先占位,后定位 ​

为什么需要:小圆点用于指示当前图片,也方便后续点击切换。但它不是图片轨道本身,结构要分开。

怎么想:先把图片 ul 和宽度调好,再做小圆点容器。转写稿强调“先把圆点容器位置调好,再做里面的 li”,否则容易跑偏。

怎么做:本节只保留 <!-- 小圆点 --> 注释占位。后续可用 ol/ul + li 做圆点,父级 .wrapper 设相对定位,圆点容器绝对定位到 banner 底部。圆点可加鼠标小手,提示可点击。

易错点:不要一上来就写圆点 li 而打乱图片结构;圆点容器要相对 .wrapper 定位,不要相对整个页面定位。

先摆位置:小圆点为什么用绝对定位 ​

为什么需要:banner 小圆点是轮播图的指示器,要盖在图片右下角,不能把图片往下挤,所以它应脱离文档流。
怎么想:转写稿强调“先把 circle 的位置调好,再做里面的 li,不要上来就做小 li,容易跑偏”。也就是先确定整组点的位置,再处理每个点。
怎么做:用 ol.circle 做整组容器,position: absolute; bottom: 10px; right: 10px; 定位到右下角。转写稿里还强调 circle 的父级(wrapper)要加 position: relative,否则绝对定位会找别的祖先当参照。笔记只截取了圆点样式,实际项目要检查父级定位。
易错点:父级没有定位,圆点会跑偏;先写 li 再调容器,位置很难对齐。

结构:用 ol + li 表示一组指示点 ​

为什么需要:小圆点是一组有序指示项,用 ol > li 语义清楚,也方便用 active 标记当前张。
怎么想:三个点就是三个 li,当前点加 active,其余不加。
怎么做:笔记结构如下:

html
<!-- 小圆点 -->
<ol class="circle">
  <li></li>
  <li class="active"></li>
  <li></li>
</ol>

易错点:active 拼写要统一;不要每个 li 都加 active,否则当前项不突出。

横排与尺寸:flex 排点,padding 留出外圈 ​

为什么需要:li 默认竖排,必须让它们在一行;同时每个点要有可点击区域和外圈留白。
怎么想:转写稿里“思ec考”就是 circle,“小粒/小利”就是 li,“拍令”就是 padding。外层 li 当作可点击区域,里面的白点用 ::after 画。
怎么做:.circle 加 display: flex;li 设 22px × 22px、padding: 4px、margin-left: 10px、border-radius: 50%;::after 设 14px × 14px 白点。注意 ::after 必须 display: block 才有宽高。
易错点:转写稿提到项目里通常是 box-sizing: border-box,这样 22px 含 padding,内容区正好 14px,白点居中;如果没有这个设置,22px + padding 会把盒子撑大,白点容易偏。第一个 li 也会吃到 margin-left,实际可用 :first-child 去掉左边距。

笔记 CSS 如下:

css
.banner .circle {
  display: flex;
  position: absolute;
  bottom: 10px;
  right: 10px;
}

.banner .circle li {
  width: 22px;
  height: 22px;
  padding: 4px;
  margin-left: 10px;
  /* background-color: pink; */
  border-radius: 50%;
  /* 小手 */
  cursor: pointer;
}

.banner .circle .active {
  background-color: rgba(255, 255, 255, 0.5);
}

.banner .circle li::after {
  content: "";
  /* 转换块级才有大小 */
  display: block;
  width: 14px;
  height: 14px;
  background-color: #fff;
  border-radius: 50%;
}

激活态:active 只给外层加半透明底 ​

为什么需要:当前轮播张要和其他点区分。
怎么想:转写稿里先试过用边框做外圈,但白色底会透出来,效果不好;最后改成“外层 li 给半透明背景,里面用 ::after 放纯白小点”。
怎么做:.active 加 background-color: rgba(255, 255, 255, 0.5)。非激活 li 背景透明,只看到白点;激活项露出半透明外圈。
易错点:不要把半透明背景加到 ::after 上,否则白点被盖住;rgba 的透明度别太高,否则外圈不明显。

调试与收尾 ​

为什么需要:小圆点尺寸小,位置和层级容易看错。
怎么想:转写稿说先看 circle 有没有到右下角,再看 li 是否横排,最后看 ::after 白点大小。
怎么做:用浏览器检查工具选中 li 和伪元素,确认宽高、padding、定位;鼠标小手用 cursor: pointer。以后点击切换由 JS 控制,本节只完成样式。
易错点:::after 漏写 content: "" 不显示;漏写 display: block 宽高无效;父级没定位会跑偏。

先看目标:侧导航是盖在 banner 上的独立盒子 ​

这一节做的是首页 banner 左侧的侧导航。转写稿里在讲 banner 时反复强调一个思路:侧边栏不要一上来就写,先把 banner 和轮播图的大盒子搭好,最后再加一个定位盒子“往这一盖”。原话里说“我不在位置,我才能盖住他们”,意思就是侧导航要用绝对定位脱离普通文档流,才能覆盖在 banner 上方。转写稿里的“通蓝”应理解为“通栏”,“版型/百型”应理解为“版心”,“rappper”应理解为 wrapper。本节笔记中的 .banner .subnav 正是这个覆盖层:position: absolute; left: 0; top: 0; width: 250px; height: 500px;。

HTML:用 ul > li > a 表达“一行分类 + 多个子链接” ​

为什么需要这样分组?因为侧导航每一行是一个一级分类,后面跟若干二级分类。用 li 表示一行,行内放多个 a,结构清楚,后面做行高、悬浮背景和右侧箭头都方便。怎么做:保留下面结构,不要把所有链接平铺成一个列表。

html
<!-- 侧边栏 -->
<div class="subnav">
  <ul>
    <li>
      <a href="#">生鲜</a>
      <a href="#">水果</a>
      <a href="#">蔬菜</a>
    </li>
    <li>
      <a href="#">美食</a>
      <a href="#">面点</a>
      <a href="#">干果</a>

    </li>
    <li>
      <a href="#">餐厨</a>
      <a href="#">数码产品</a>  
    </li>
    <li>
      <a href="#">电器</a>
      <a href="#">床品</a>
      <a href="#">四件套</a>
      <a href="#">被枕</a>  
    </li>
    <li>
      <a href="#">居家</a>
      <a href="#">奶粉</a>
      <a href="#">玩具</a>
      <a href="#">辅食</a>  
    </li>
    <li>
      <a href="#">洗护</a>
      <a href="#">洗发</a>
      <a href="#">洗护</a>
      <a href="#">美妆</a>  
    </li>
    <li>
      <a href="#">孕婴</a>
      <a href="#">奶粉</a>
      <a href="#">玩具</a>  
    </li>
    <li>
      <a href="#">服饰</a>
      <a href="#">女装</a>
      <a href="#">男装</a>  
    </li>
    <li>
      <a href="#">杂货</a>
      <a href="#">户外</a>
      <a href="#">图书</a>  
    </li>
    <li>
      <a href="#">品牌</a>
      <a href="#">品牌制造</a>  
    </li>
  </ul>
</div>

易错点:一行里的多个 a 默认会挨在一起,后面要靠 margin-right 或空格拉开;第一项字号更大,用 a:first-child 单独控制,不要给所有 a 都放大。

CSS:先定位外层,再修每一行 ​

为什么先写外层?转写稿在小圆点部分说“先把这个父盒子调好位置,再去做里面的小圆点,要不然容易跑偏”。侧导航同理:先把 .subnav 固定到 banner 左上角,再调 li。怎么做:absolute 定位,宽 250、高 500,背景用半透明黑。注意 .banner 要有定位上下文,否则绝对定位可能参照更外层,这是常见调试点。

css
.banner .subnav {
  position: absolute;
  left: 0;
  top: 0;
  width: 250px;
  height: 500px;
  background-color: rgba(0, 0, 0, .42)
}

.banner .subnav li {
  position: relative;
  height: 50px;
  padding-left: 29px;
  line-height: 50px;
  /* background-color: pink; */
}

.banner .subnav li::after {
  /* 到iconfont.css 里面去复制 */
  content: "\e687";
  position: absolute;
  top: 0px;
  right: 29px;
  color: #fff;
  /* 声明字体图标的字体 */
  font-family: iconfont;
}

.banner .subnav li:hover {
  background-color: var(--lv);
}

.banner .subnav li a {
  color: #fff;
  font-size: 14px;
}

.banner .subnav li a:first-child {
  font-size: 16px;
  margin-right: 5px;
}

行高、内边距和伪元素箭头 ​

每个 li 高 50px,line-height: 50px 让文字垂直居中;padding-left: 29px 把文字从左侧推开。右侧箭头不是图片,而是字体图标:li::after 用 content: "\e687",并声明 font-family: iconfont。易错点:content 的编码必须和 iconfont.css 里一致;li 要 position: relative,伪元素才能用 right: 29px 定位到行右侧。var(--lv) 依赖前面已定义的绿色变量,没有定义时悬浮背景不会生效。

悬浮和链接样式 ​

li:hover 给整行换背景,a 默认白色、14px;第一个 a 是主分类,改成 16px,并加 margin-right: 5px 和后面的子链接拉开。易错点:链接颜色要写在 a 上,不能只写在 li 上就以为一定生效;a:first-child 只选每行第一个 a,不要误写成 li:first-child。这样侧导航就完成了:外层定位盖住 banner,内部每行高度一致,右侧字体图标统一,悬浮有反馈。

课件图示(PPTX) ​

day11 课件图

day11 课件图

代码示例 ​

1. banner 图片横排 ​

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>banner 图片横排</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    ul {
      list-style: none;
    }

    .banner {
      height: 500px;
      background-color: #f5f5f5;
    }

    .banner .wrapper {
      position: relative;
      width: 1240px;
      height: 500px;
      margin: 0 auto;
      overflow: hidden;
    }

    .banner .wrapper > ul {
      display: flex;
      width: 300%;
      /* width: 3720px; */
    }

    .banner .wrapper > ul li {
      width: 1240px;
    }

    .banner .wrapper > ul img {
      display: block;
      width: 100%;
      height: 500px;
      object-fit: cover;
    }
  </style>
</head>
<body>
  <div class="banner">
    <div class="wrapper">
      <!-- 轮播图图片 -->
      <ul>
        <li><a href="#"><img src="./uploads/banner1.png" alt=""></a></li>
        <li><a href="#"><img src="./uploads/banner1.png" alt=""></a></li>
        <li><a href="#"><img src="./uploads/banner1.png" alt=""></a></li>
      </ul>
    </div>
  </div>
</body>
</html>

要点解释

  • .banner .wrapper > ul 使用 display:flex,让多个 li 横向排列。
  • width: 300% 表示 ul 是父级 wrapper 的 3 倍宽,用来放开 3 张轮播图;也可以写成 3720px。
  • wrapper 必须设置 overflow: hidden,否则超出的第 2、3 张图会露出来。
  • li 需要固定宽度,避免 flex 布局把图片压缩;图片再用 width: 100% 撑满 li。

2. banner 小圆点 ​

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>banner 小圆点</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    ol {
      list-style: none;
    }

    .banner {
      height: 500px;
      background-color: #333;
    }

    .banner .wrapper {
      position: relative;
      width: 1240px;
      height: 500px;
      margin: 0 auto;
      background-color: #555;
    }

    .banner .circle {
      display: flex;
      position: absolute;
      bottom: 10px;
      right: 10px;
    }

    .banner .circle li {
      width: 22px;
      height: 22px;
      padding: 4px;
      margin-left: 10px;
      border-radius: 50%;
      cursor: pointer;
    }

    .banner .circle .active {
      background-color: rgba(255, 255, 255, 0.5);
    }

    .banner .circle li::after {
      content: "";
      display: block;
      width: 14px;
      height: 14px;
      background-color: #fff;
      border-radius: 50%;
    }
  </style>
</head>
<body>
  <div class="banner">
    <div class="wrapper">
      <!-- 小圆点 -->
      <ol class="circle">
        <li></li>
        <li class="active"></li>
        <li></li>
      </ol>
    </div>
  </div>
</body>
</html>

要点解释

  • .circle 使用绝对定位,必须保证父级 .wrapper 有 position: relative,否则会相对页面定位。
  • li::after 必须写 display: block,否则伪元素是行内元素,宽高不生效。
  • li 的 padding: 4px 配合内部 14px 白点,可以做出“大圈套小点”的效果;注意 box-sizing 会影响实际盒子尺寸。
  • active 类加在 li 上,用来显示当前小圆点的半透明底色。

3. banner 侧导航 ​

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>banner 侧导航</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    ul {
      list-style: none;
    }

    :root {
      --lv: #27ba9b;
    }

    .banner {
      position: relative;
      height: 500px;
      background-color: #f5f5f5;
    }

    .banner .wrapper {
      position: relative;
      width: 1240px;
      height: 500px;
      margin: 0 auto;
      background-color: #ddd;
    }

    .banner .subnav {
      position: absolute;
      left: 0;
      top: 0;
      width: 250px;
      height: 500px;
      background-color: rgba(0, 0, 0, .42);
    }

    .banner .subnav li {
      position: relative;
      height: 50px;
      padding-left: 29px;
      line-height: 50px;
      /* background-color: pink; */
    }

    .banner .subnav li::after {
      /* 到 iconfont.css 里面去复制 */
      content: "\e687";
      position: absolute;
      top: 0;
      right: 29px;
      color: #fff;
      /* 声明字体图标的字体 */
      font-family: iconfont;
    }

    .banner .subnav li:hover {
      background-color: var(--lv);
    }

    .banner .subnav li a {
      color: #fff;
      font-size: 14px;
      text-decoration: none;
    }

    .banner .subnav li a:first-child {
      font-size: 16px;
      margin-right: 5px;
    }
  </style>
</head>
<body>
  <div class="banner">
    <div class="wrapper">
      <!-- 侧边栏 -->
      <div class="subnav">
        <ul>
          <li>
            <a href="#">生鲜</a>
            <a href="#">水果</a>
            <a href="#">蔬菜</a>
          </li>
          <li>
            <a href="#">美食</a>
            <a href="#">面点</a>
            <a href="#">干果</a>
          </li>
          <li>
            <a href="#">餐厨</a>
            <a href="#">数码产品</a>
          </li>
          <li>
            <a href="#">电器</a>
            <a href="#">床品</a>
            <a href="#">四件套</a>
            <a href="#">被枕</a>
          </li>
          <li>
            <a href="#">居家</a>
            <a href="#">奶粉</a>
            <a href="#">玩具</a>
            <a href="#">辅食</a>
          </li>
          <li>
            <a href="#">洗护</a>
            <a href="#">洗发</a>
            <a href="#">洗护</a>
            <a href="#">美妆</a>
          </li>
          <li>
            <a href="#">孕婴</a>
            <a href="#">奶粉</a>
            <a href="#">玩具</a>
          </li>
          <li>
            <a href="#">服饰</a>
            <a href="#">女装</a>
            <a href="#">男装</a>
          </li>
          <li>
            <a href="#">杂货</a>
            <a href="#">户外</a>
            <a href="#">图书</a>
          </li>
          <li>
            <a href="#">品牌</a>
            <a href="#">品牌制造</a>
          </li>
        </ul>
      </div>
    </div>
  </div>
</body>
</html>

要点解释

  • .subnav 使用绝对定位,放在 .wrapper 内部,并给 .wrapper 设置 position: relative,这样侧导航才会贴在版心左侧。
  • li 设置 position: relative,是为了让 li::after 的 right: 29px 相对当前 li 定位。
  • li::after 使用 content: "\e687" 和 font-family: iconfont 显示字体图标;实际项目中必须引入对应的 iconfont.css 字体文件。
  • :root 中的 --lv 是示例主题色,笔记中使用 var(--lv) 控制 hover 背景色,实际项目按主题变量替换即可。

常见错误 ​

  1. 现象:三张 banner 图横向排列后整体被压扁。
    原因:ul 仍在父级宽度内参与 flex 收缩,li/img 被压缩。
    修法:让 ul 宽度足够容纳全部图片,如 width: 300% 或按图片总宽写死;必要时给 img 固定宽高。

  2. 现象:轮播超出部分露出第二、第三张图。
    原因:只做了横向排列,没有裁剪溢出区域。
    修法:给有明确宽度的容器(如 .wrapper)加 overflow: hidden,不要误加到无固定宽度的通栏容器上。

  3. 现象:小圆点定位跑到 banner 外面或位置漂移。
    原因:绝对定位元素找不到正确的定位父级。
    修法:先给 .wrapper 设置 position: relative,再给 .circle 设置 position: absolute 并调整 bottom/right。

  4. 现象:圆点用边框模拟半透明外圈时,内部白点不明显或外圈发白。
    原因:边框与白色背景叠加,视觉层次被白底吃掉。
    修法:改用“外层圆点 + ::after 内层白点”的结构,外层用 rgba() 背景表现半透明,内层单独设白底和圆角。

  5. 现象:侧导航覆盖不住 banner,或 hover 背景错位。
    原因:侧导航未相对 banner 定位,或 li 缺少相对定位上下文。
    修法:.banner 或 .wrapper 作为定位父级,.subnav 绝对定位到左侧;箭头等伪元素相对 li 定位。

  6. 现象:底部版权链接间距过大,点击空白区域也会触发链接。
    原因:把左右间距直接加在 a 上,扩大了可点击范围。
    修法:用 a + span 的结构,间距加在 span 上,只让文字区域保持链接交互。

练习 ​

  1. banner 横向排列修正:现有三张 banner 图被压成窄条,请分别用“固定 ul 总宽”和“百分比宽度”两种方式修正,并说明各自适用场景。

  2. 圆点组件重构:将当前圆点改为“外层半透明圆 + ::after 白色内圆”的结构,补全 active 状态,并保证鼠标移入变小手。

  3. 侧导航定位检查:给侧导航补一个最小可运行结构,要求它压在 banner 左侧、li 高度一致、hover 背景铺满整行、右侧箭头位置固定。

  4. 底部版权模块改写:把一行版权链接改为 p > a + span + a + span ... 结构,要求链接文字变色、竖线不变色、点击空白处不触发链接。

  5. 自查清单演练:任选当前 banner 模块,列出 3 个你最容易出现的布局问题,并写出对应的浏览器检查步骤和修复代码片段。

原视频对照 ​

#视频时长
1底部dl模块制作05:30
2底部帮助模块左侧完成06:34
3底部帮助模块右侧结束11:38
4底部版权模块结束09:46
5首页banner开始09:33
6首页banner轮播图效果制作08:49
7小圆点做法17:43

小结 ​

  1. banner 横向轮播的核心不是“让图片变小”,而是让承载图片的轨道足够宽,再裁剪可视区域。
  2. 绝对定位组件必须先确认定位父级,否则圆点、侧导航、箭头都会出现位置漂移。
  3. 圆点这类小组件优先考虑结构层次清晰的做法,边框模拟在白色背景下容易失效。
  4. 侧导航要与 banner 建立明确的层级和定位关系,hover 状态要作用在整行 li 上。
  5. 底部版权链接要区分“文字可点击区域”和“视觉间隔区域”,避免扩大点击热区。
  6. 公共头部、底部样式与首页独有样式要分文件管理,避免后续页面互相污染。
  7. 调试图片不显示时,优先看控制台 404、路径大小写和文件名,再怀疑 CSS。