主题
学成在线(二)
本页对应 学成在线,共 8 段视频,约 1 小时 11 分。
学习目标
- 能独立完成“精品推荐”模块的 HTML 结构搭建,正确使用
h3、ul、li、a组织标题、链接列表和“修改兴趣”入口。 - 能使用 Flex 布局实现模块内元素同行排列、两端对齐及中间内容自适应,并说明
justify-content: space-between与flex: 1在该布局中的作用。 - 能通过
padding、margin、行高、边框和:last-child后代选择器完成链接间距、竖线分隔及最后一个链接右边框去除,并避免选择器误选。 - 能按“HD + BD”结构复用课程/前端模块头部,完成
h3、查看全部链接及热门/初级/中级/高级导航的样式与当前项高亮。 - 能完成课程产品列表项布局,使用固定宽高、
display: block、height: 100%、标题固定高度和margin保证多行标题下底部信息对齐。 - 能使用
flex-wrap: wrap、间距控制和box-shadow完成产品模块多行排列与悬停阴影效果,并验证增删列表项后布局仍保持稳定。
知识点

先搭区域骨架:三部分放在同一个容器里
精品推荐区域可以拆成三块:左侧标题“精品推荐”、中间标签列表、右侧“修改兴趣”。为什么需要先看结构?因为后面所有样式都围绕“谁和谁在一行、谁是谁的父级”展开;怎么想?先把三块都放进 .recommend,再考虑排版;怎么做?保留笔记结构:
html
<!-- 精品推荐 -->
<div class="recommend wrapper">
<h3>精品推荐</h3>
<ul>
<li><a href="#">HTML</a></li>
</ul>
<a href="#" class="modify">修改兴趣</a>
</divcss
/* 精品推荐 */
.recommend {
display: flex;
margin-top: 11px;
padding: 0 20px;
height: 60px;
background-color: #fff;
box-shadow: 0px 1px 2px 0px rgba(211, 211, 211, 0.5);
line-height: 60px;
}易错点:原笔记最后的 </div 少了 >,实际书写要补全;.wrapper 负责版心,.recommend 负责本区域布局,不要把两者混成一个概念。
行高解决垂直居中
为什么需要?标题、标签、修改兴趣都在 60px 高的盒子里,如果逐个写上下 padding 会很麻烦。怎么想?它们都在一行文字流里,可以利用继承性:父级设置行高,子级文字默认继承。怎么做?在 .recommend 上写 line-height: 60px;,与容器高度一致,文字就垂直居中。易错点:行高不是高度,容器仍需 height: 60px;如果子元素后来变成多行内容,行高继承可能不合适,要单独覆盖。
用 Flex 让标题和列表同行
为什么需要?h3 和 ul 都是块级元素,默认会上下排列。怎么想?找它们的“亲爸爸”——.recommend,给父级加 Flex,孩子就在一行。怎么做?.recommend { display: flex; }。转写稿中反复强调:不要给 ul 乱加,要给 .recommend 加。易错点:h3 和 ul 的父级是 .recommend,不是 ul;Flex 只影响直接子元素。
标签列表的间距与竖线:边框给 A,不给 li
为什么需要?标签之间要有距离和竖线。怎么想?可以给每个 li 加右边框,但转写稿调试发现:li 受父级 line-height: 60px 影响,高度会被撑得和盒子差不多,竖线很高、很丑;a 是行内元素,默认没有这么大的高度,边框更合适。怎么做?给 ul 加 Flex,让 li 横排;给 a 加左右 padding 和右边框,例如 padding: 0 24px; border-right: 1px solid #ddd;。易错点:不要给 li 加竖线边框;距离用 padding 撑开,才能把边框推到文字外侧。
去掉最后一项竖线:选“最后一个 li 里面的 a”
为什么需要?最后一项右侧不应有竖线。怎么想?结构是 ul > li > a,每个 a 在各自 li 里都是“独生子”,所以 a:last-child 会命中所有 a。正确思路是先选最后一个 li,再选它里面的 a。怎么做?.recommend ul li:last-child a { border-right: 0; }。易错点:last-child 选的是亲兄弟中的最后一个;这里要选最后一个 li,再用后代选择器选 a。
修改兴趣:加类名隔离,再用两端对齐
为什么需要?右侧“修改兴趣”也是 a,如果直接写 .recommend a 会把标签列表里的 a 一起改色。怎么想?用类名隔离,笔记中用了 .modify。怎么做?.modify 单独设颜色和字号;父级 .recommend 用 justify-content: space-between; 让左侧标题和右侧修改兴趣贴两边;中间 ul 加 flex: 1; 占满剩余空间,文字仍默认左对齐。易错点:不给 modify 加类名会误伤其他链接;只写 space-between 时中间列表可能被推到中间,ul { flex: 1; } 才能让剩余空间归列表,同时文字靠左。
先看结构:标题、链接列表、修改入口
为什么需要:精品推荐模块通常由三部分组成——左侧标题、中间技术链接列表、右侧“修改兴趣”入口。结构清晰,后续才能用 Flex 布局把三块排到一行。
怎么想:链接列表天然适合用 ul > li > a。ul 的直接子元素只能是 li,链接放在 li 里面的 a 上,点击区域和语义都更合理。
怎么做:先按笔记保留 HTML 结构:
html
<ul>
<li><a href="#">HTML</a></li>
<li><a href="#">CSS</a></li>
<li><a href="#">JavaScript</a></li>
<li><a href="#">Node.js</a></li>
<li><a href="#">Ajax</a></li>
<li><a href="#">Vue2.0</a></li>
<li><a href="#">Vue3.0</a></li>
<li><a href="#">TypeScript</a></li>
<li><a href="#">React</a></li>
</ul>实际模块外层还会有 .recommend,右侧补一个“修改兴趣”链接,并给类名隔离:
html
<a href="#" class="modify">修改兴趣</a>易错点:不要写成 a 包 li,ul 里也不能直接放 a。否则结构不合法,后面选样式也容易乱。
让文字垂直居中:行高与内边距
为什么需要:标题、链接、修改入口都在同一行,如果不处理,文字容易贴顶或贴左,视觉不整齐。
怎么想:转写稿里强调“不要想复杂,行高等于高度就行”。给父级 .recommend 设置 line-height: 60px,子元素继承后自然垂直居中;再给左右 padding: 0 20px,避免内容贴边。
怎么做:可补充:
css
.recommend {
line-height: 60px;
padding: 0 20px;
}易错点:不要给每个子元素分别写上下 padding 硬凑居中;行高具有继承性,给父级更简单。左右内边距也不要写成上下左右都给,否则会改变整体高度。
父级与列表横向:Flex 与 flex:1
为什么需要:h3 和 ul 都是块级元素,默认各占一行。精品推荐需要标题在左、列表在右,并且“修改兴趣”贴最右侧。
怎么想:先找 h3、ul、.modify 的共同父级 .recommend,给它 display:flex;再让 ul 使用 flex:1 占满标题和修改入口之外的剩余空间。
怎么做:笔记 CSS 中列表部分为:
css
.recommend ul {
/* 除去标题和修改兴趣的尺寸,父级剩余尺寸都给ul,实现把修改兴趣挤到最右侧 */
flex: 1;
display: flex;
}配合父级可写:
css
.recommend {
display: flex;
justify-content: space-between;
}易错点:只给 ul 写 flex:1,但父级没有 display:flex,是无效的。ul 自身也要 display:flex,里面的 li 才会横排。
竖线与间距:边框给 a,不要给 li
为什么需要:每个技术链接之间需要小间距和一条竖线。转写稿中先尝试给 li 加 border-right,发现竖线很高,因为 li 的高度会被行高撑开。
怎么想:a 是行内元素,高度主要由文字内容决定,把右边框给 a 更合适;间距用左右 padding 撑开,而不是用 margin,这样边框位置和点击区域更自然。
怎么做:
css
.recommend ul li a {
padding: 0 24px;
border-right: 1px solid #e0e0e0;
font-size: 18px;
}易错点:给 li 加右边框会出现“线很高”的问题。这里不是不能用 margin,而是用 padding 能把 a 的盒子撑大,竖线位置更稳定。
最后一个竖线与右侧修改入口
为什么需要:最后一个链接右边不需要竖线;右侧“修改兴趣”要和其他链接颜色不同,不能被统一选择器误伤。
怎么想:去掉最后一个竖线,要选“最后一个 li 里面的 a”,写成 .recommend ul li:last-child a。不能写 a:last-child,因为每个 li 里只有一个 a,每个 a 都是独生子,会把所有 a 都选中。
怎么做:笔记 CSS 已给出:
css
.recommend ul li:last-child a {
border-right: 0;
}
.recommend .modify {
font-size: 16px;
color: #00a4ff;
}易错点:.recommend a 会把列表里的 a 和修改入口一起改色,所以“修改兴趣”必须加 .modify 类隔离。last-child 选的是亲兄弟中的最后一个,这里要先选最后一个 li,再用后代选择器选里面的 a。
完整样式回顾
css
.recommend h3 {
font-size: 18px;
color: #00a4ff;
font-weight: 400;
}
.recommend ul {
/* 除去标题和修改兴趣的尺寸,父级剩余尺寸都给ul,实现把修改兴趣挤到最右侧 */
flex: 1;
display: flex;
}
.recommend ul li a {
padding: 0 24px;
border-right: 1px solid #e0e0e0;
font-size: 18px;
}
.recommend ul li:last-child a {
border-right: 0;
}
.recommend .modify {
font-size: 16px;
color: #00a4ff;
}调试时按“先结构、再横排、再间距竖线、最后处理最后一个边框和修改入口”的顺序做,出问题就回头检查父级有没有 display:flex、边框是不是误给 li、最后一个 a 的选择器有没有写错。
先看效果与结构

本节只做“精品推荐课程”的标题区域:左边是标题,右边是“查看全部”链接,下面 .bd 先放占位内容。转写中反复强调一个调试习惯:先写一两句结构就保存看效果,确认盒子正常显示,再补样式。标题区域虽然简单,但它涉及的“公共类复用、行高垂直居中、flex左右分布、链接图标留白”后面还会反复用到。
html
<!-- 精品推荐课程 -->
<div class="course wrapper">
<!-- 标题 -->
<div class="hd">
<h3>精品推荐</h3>
<a href="#" class="more">查看全部</a>
</div>
<!-- 内容 -->
<div class="bd">1</div>
</div>结构划分与公共类
为什么需要:标题区域不是只出现一次,转写中提到下面还有类似模块,头部结构大体相同,所以命名要考虑复用。
怎么想:把标题区域单独放进 .hd,内容区域放 .bd,这是常见的“头部/身体”划分;.hd 作为公共类,不写成 .course .hd 这种带父级的复合选择器,方便其他模块共用。
怎么做:HTML 中 .course 作为模块外层,里面先写 .hd,再写 .bd;.hd 内放 h3 和 a.more。
易错点:转写里做到后面发现页面还有别的 A,如果直接写裸 a 选择器,容易把“热门、初级”等链接一起改掉。所以“查看全部”要加 .more 类,CSS 写成 .hd .more,把范围限定住。
标题栏垂直居中
为什么需要:标题和“查看全部”在同一行,且都要垂直居中;如果用上下 padding 硬调,字号或行高变化后容易偏。
怎么想:转写中明确说“不要想复杂,行高等于高度就行了”。父级 .hd 高度是 60px,就把 line-height 也设为 60px,文字会继承这个行高,从而垂直居中。
怎么做:给 .hd 设置 height: 60px; line-height: 60px;。
易错点:高度和行高要一致;不要把行高只写在 h3 上而漏掉 a,否则两者基线不齐。转写中先加行高看效果,确认文字都垂直居中后再继续。
左右分布:flex 与 space-between
为什么需要:标题要贴左,“查看全部”要贴右,不能靠猜 margin 把链接推到右边。
怎么想:h3 和 a 都是行内/块级元素,要让它们在一行并分居两端,找共同父级 .hd 加 flex 最直接。转写中反复提醒:flex 要加在父级,不要加错到子元素。
怎么做:.hd 加 display: flex; justify-content: space-between;。
易错点:justify-content: space-between 必须写在 flex 容器 .hd 上;如果只给 a 加 margin-left: auto 也能推右,但本节统一用 flex,结构更清晰。转写中调试时先让它们在一行,再处理两端对齐。
标题与“查看全部”的细节样式
为什么需要:h3 浏览器默认会加粗、字号偏大;“查看全部”右侧有小图标,需要给背景图留出空间。
怎么想:标题用 font-size: 21px; font-weight: 400; 还原设计稿;链接用 padding-right: 20px 把文字和右侧背景图标隔开,背景图用 no-repeat right center 固定在右侧垂直居中。
怎么做:
css
/* 推荐课程 */
.course {
margin-top: 15px;
}
/* 标题 - 公共类,与其他区域共用 */
.hd {
display: flex;
justify-content: space-between;
height: 60px;
line-height: 60px;
}
.hd h3 {
font-size: 21px;
font-weight: 400;
}
.hd .more {
padding-right: 20px;
background: url(../images/more.png) no-repeat right center;
font-size: 14px;
color: #999;
}易错点:padding-right 不够时,背景图标会压住文字;背景图路径要按项目目录写对;.more 的选择器要带 .hd 限定,避免影响其他链接。转写中还提到,后续模块出现别的 A 时,正是因为加了类名并限定选择器,才不会把其它链接颜色、大小一起改掉。
先保留本节笔记结构与样式
为什么需要:推荐课程内容是一个“头部 + 列表”的典型模块,先把公共容器和列表项尺寸定下来,后续推荐、前端开发等模块才能复用。 怎么想:外层用 .bd 管内容区,ul 负责排列,li 负责单个课程卡片。 怎么做:本节笔记代码原样如下。
html
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
</ul>css
/* 课程内容 - 公共类 */
.bd ul {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.bd li {
margin-bottom: 14px;
width: 228px;
height: 271px;
background-color: pink;
}易错点:flex 要加在 li 的亲爸爸 ul 上;只写 display:flex 不会自动换行,必须补 flex-wrap: wrap,再用 space-between 做两端对齐。
精品推荐头部:H3 与链接放一行
为什么需要:头部有“精品推荐”标题和“查看全部”链接,二者在同一行,还要左右分开。 怎么想:先找共同父盒子,给父盒子加 display:flex; justify-content:space-between;;文字垂直居中可用行高解决。 怎么做:转写稿中先给推荐模块父级设置行高 60,再给左右内边距 20;头部 HD 高度 30,上下外边距撑开,内部 H3 和 A 用 flex 两端对齐。链接 A 建议加类名(如 more),避免影响后面其他 A。 易错点:不要一上来给每个文字写上下 padding;父级有行高时,子文字会继承垂直居中效果。给 A 设样式时一定要加父级或类名限定,否则会把模块内所有 A 都改掉。
卡片 li 与 A:让整张卡片可点
为什么需要:课程卡片里有点击需求,用户点图片、标题、说明都应能跳转。 怎么想:结构应是 li 包 A,不能 A 包 li,因为 ul 的直接子元素只能是 li。 怎么做:li 固定宽高 228×271;A 设为 display:block; height:100%;,宽度随父级,整张卡片就都能点。标题用 H4,说明用 P,H4 必须给固定高度(转写中量得约 55px),这样标题一行或两行时,下面的“高级”仍能对齐。 易错点:A 是行内元素,不转块级就没有完整宽高;H4 不给高度时,两行标题会把下面内容顶下去,导致卡片底部错位。
链接竖线与最后一项处理
为什么需要:推荐链接之间要有小竖线和间距。 怎么想:竖线可给 A 加右边框;间距用 A 的左右 padding 撑开。 怎么做:转写稿中先尝试给 li 加右边框,发现竖线跟父级一样高,很难看;因为 li 有高度/行高,而 A 是行内元素,默认不会撑那么高,所以改为给 A 加右边框,并给 A 左右 padding(如 24px)。最后一个竖线要去掉,正确写法是 ul li:last-child A { border-right: 0; }。 易错点:不要写 A:last-child。每个 li 里只有一个 A,它既是第一个也是最后一个孩子,会把所有 A 的右边框都去掉;last-child 选的是亲兄弟,所以要先选最后一个 li,再用后代选择器选里面的 A。
修改兴趣与前端模块复用
为什么需要:“修改兴趣”在右侧,推荐列表在左侧,二者要两端对齐;前端开发模块头部又和精品推荐头部高度相似,应复用 HD。 怎么想:推荐父级用 display:flex; justify-content:space-between;,中间 ul 加 flex:1 占满剩余空间,文字默认左对齐,这样右侧“修改兴趣”贴右,列表也不会跑到中间。 怎么做:给“修改兴趣”的 A 单独加类名(如 modify)隔离样式;前端模块复制 HD 结构,在 H3 和“查看全部”之间补一个 ul,里面放 li>A,ul 加 flex,A 用左右 margin 打开距离,当前“热门”加 hot 类改颜色。 易错点:不要用固定 margin 把“修改兴趣”硬推到右边,内容一多会掉下去;复用 HD 时不要和已有类名冲突,转写稿提醒可加 study-hd 之类前缀避让。
结构设计:用列表承载课程卡片
为什么需要:推荐课程是多条同类内容,用 ul > li 语义清晰,也方便后续用数据循环渲染。怎么想:每张卡片整体可点击,所以让 a 包住“图片区 + 文字区”,li 只作为列表项。怎么做:结构写成 li > a > .pic + .text,文字区里放 h4 和 p。易错点:一定是 li 包 a,不能 a 包 li;图片 alt 要写中文课程名,不要留空。
图片区:先固定高度,保证卡片整齐
为什么需要:课程封面高度不一致时,卡片会参差不齐。怎么想:本节样式给 .pic 固定 height: 156px,让图片区先占住位置。怎么做:.bd li .pic { height: 156px; },图片仍放在 .pic 内。易错点:只写图片高度、不写容器高度时,不同图片容易把文字区顶乱;调试时先写一个 li 看高度,再复制成多条。
文字区:用 padding 和固定高度撑出卡片
为什么需要:文字区要有内边距,且整体高度要稳定。怎么想:转写稿里反复强调“先量盒子再写样式”,本节 .text 给 padding: 20px、height: 115px、白底。怎么做:图片区 156px 加文字区 115px,正好形成完整卡片高度。易错点:height 与 padding 的盒模型关系要清楚;若项目没有全局重置,标题默认外边距要检查,否则会挤动布局。
标题与学习人数:固定标题高度防错位
为什么需要:课程标题有一行也有两行,如果不固定 h4 高度,下方“高级 · 多少人在学习”会上下跳动。怎么想:给 h4 固定高度和行高,让两行标题也能占住同一块区域。怎么做:h4 设 height: 40px; line-height: 20px; font-size: 14px; font-weight: 400; margin-bottom: 13px;。易错点:标题高度必须能容纳两行;p 里级别用 span 变橙色,人数用 i 但要去掉斜体:font-style: normal;。
完整 HTML 结构(图片 alt 已改为中文)
html
<ul>
<li>
<a href="#">
<div class="pic"><img src="./uploads/course01.png" alt="JavaScript数据看板项目实战课程封面"></div>
<div class="text">
<h4>JavaScript数据看板项目实战</h4>
<p><span>高级</span> · <i>1125</i>人在学习</p>
</div>
</a>
</li>
<li>
<a href="#">
<div class="pic"><img src="./uploads/course02.png" alt="Vue.js实战面经全端项目课程封面"></div>
<div class="text">
<h4>Vue.js实战——面经全端项目</h4>
<p><span>高级</span> · <i>2726</i>人在学习</p>
</div>
</a>
</li>
<li>
<a href="#">
<div class="pic"><img src="./uploads/course03.png" alt="玩转Vue全家桶iHRM人力资源项目课程封面"></div>
<div class="text">
<h4>玩转Vue全家桶,iHRM人力资源项目</h4>
<p><span>高级</span> · <i>9456</i>人在学习</p>
</div>
</a>
</li>
<li>
<a href="#">
<div class="pic"><img src="./uploads/course04.png" alt="Vue.js实战医疗项目优医问诊课程封面"></div>
<div class="text">
<h4>Vue.js实战医疗项目——优医问诊</h4>
<p><span>高级</span> · <i>7192</i>人在学习</p>
</div>
</a>
</li>
<li>
<a href="#">
<div class="pic"><img src="./uploads/course05.png" alt="小程序实战小兔鲜电商小程序项目课程封面"></div>
<div class="text">
<h4>小程序实战:小兔鲜电商小程序项目</h4>
<p><span>高级</span> · <i>2703</i>人在学习</p>
</div>
</a>
</li>
<li>
<a href="#">
<div class="pic"><img src="./uploads/course06.png" alt="前端框架Flutter开发实战课程封面"></div>
<div class="text">
<h4>前端框架Flutter开发实战</h4>
<p><span>高级</span> · <i>2841</i>人在学习</p>
</div>
</a>
</li>
<li>
<a href="#">
<div class="pic"><img src="./uploads/course07.png" alt="熟练使用React.js极客园H5项目课程封面"></div>
<div class="text">
<h4>熟练使用React.js——极客园H5项目</h4>
<p><span>高级</span> · <i>95682</i>人在学习</p>
</div>
</a>
</li>
<li>
<a href="#">
<div class="pic"><img src="./uploads/course08.png" alt="熟练使用React.js极客园PC端项目课程封面"></div>
<div class="text">
<h4>熟练使用React.js——极客园PC端项目</h4>
<p><span>高级</span> · <i>904</i>人在学习</p>
</div>
</a>
</li>
<li>
<a href="#">
<div class="pic"><img src="./uploads/course09.png" alt="前端实用技术Fetch API实战课程封面"></div>
<div class="text">
<h4>前端实用技术,Fetch API 实战</h4>
<p><span>高级</span> · <i>1516</i>人在学习</p>
</div>
</a>
</li>
<li>
<a href="#">
<div class="pic"><img src="./uploads/course10.png" alt="前端高级Node.js零基础入门教程课程封面"></div>
<div class="text">
<h4>前端高级Node.js零基础入门教程</h4>
<p><span>高级</span> · <i>2766</i>人在学习</p>
</div>
</a>
</li>
</ul>完整 CSS 样式
css
.bd li .pic {
height: 156px;
}
.bd li .text {
padding: 20px;
height: 115px;
background-color: #fff;
}
.bd li .text h4 {
margin-bottom: 13px;
height: 40px;
font-size: 14px;
line-height: 20px;
font-weight: 400;
}
.bd li .text p {
font-size: 14px;
line-height: 20px;
color: #999;
}
.bd li .text p span {
color: #fa6400;
}
.bd li .text p i {
font-style: normal;
}调试顺序与易错点
转写稿里的调试思路是:先写一个 li 看外形,再复制成多个;先量图片区和文字区高度,再补标题、段落样式。本节要抓住三个易错点:第一,h4 不固定高度时,一行标题和两行标题会让下方信息错位;第二,人数用 i 后浏览器默认斜体,必须 font-style: normal;第三,文字区有 padding 时不要只盯内容高度,要按盒模型检查整体是否把卡片撑乱。按“结构先通、单卡调稳、再复制多条”的顺序做,最不容易返工。
课件图示








代码示例
示例 1:精品推荐区域(.recommend)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>精品推荐</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
li { list-style: none; }
a { text-decoration: none; color: #333; }
body { background-color: #f3f5f7; }
/* 版心(笔记未给出,为了让 demo 居中显示补充) */
.wrapper { width: 1200px; margin: 0 auto; }
/* 精品推荐 */
.recommend {
display: flex;
margin-top: 11px;
padding: 0 20px;
height: 60px;
background-color: #fff;
box-shadow: 0px 1px 2px 0px rgba(211, 211, 211, 0.5);
line-height: 60px;
}
.recommend h3 {
font-size: 18px;
color: #00a4ff;
font-weight: 400;
}
.recommend ul {
/* 除去标题和修改兴趣的尺寸,父级剩余尺寸都给ul,实现把修改兴趣挤到最右侧 */
flex: 1;
display: flex;
}
.recommend ul li a {
padding: 0 24px;
border-right: 1px solid #e0e0e0;
font-size: 18px;
}
.recommend ul li:last-child a {
border-right: 0;
}
.recommend .modify {
font-size: 16px;
color: #00a4ff;
}
</style>
</head>
<body>
<!-- 精品推荐 -->
<div class="recommend wrapper">
<h3>精品推荐</h3>
<ul>
<li><a href="#">HTML</a></li>
<li><a href="#">CSS</a></li>
<li><a href="#">JavaScript</a></li>
<li><a href="#">Node.js</a></li>
<li><a href="#">Ajax</a></li>
<li><a href="#">Vue2.0</a></li>
<li><a href="#">Vue3.0</a></li>
<li><a href="#">TypeScript</a></li>
<li><a href="#">React</a></li>
</ul>
<a href="#" class="modify">修改兴趣</a>
</div>
</body>
</html>关键行与易错点
.recommend { display: flex; line-height: 60px; }:h3、ul、a 三块靠display:flex排成一行;垂直居中不写 padding 上下,直接给父级line-height: 60px,靠继承让所有子文字自动垂直居中(转写稿:“行高等性高不就行了嘛”)。.recommend ul { flex: 1; }:这一句是把“修改兴趣”挤到最右的关键——ul 占满标题和链接之间的剩余全部空间。转写稿反复强调:这里不用justify-content: space-between,否则 ul 会跑到中间。- 竖线写
.recommend ul li a { border-right: 1px solid #e0e0e0; },不要写给 li。给 li 时 li 的高度被行高撑成 60px,竖线会变成一条很高的线;a 是行内元素默认没有高度,竖线只跟文字一样高。 - 左右间距用
padding: 0 24px而不是 margin,因为要让边框跟着字一起被推开。 - 去掉最后一条竖线必须写
.recommend ul li:last-child a { border-right: 0; }。不能写li a:last-child:每个 li 里只有一个 a,a 是“独生子”,first-child和last-child都选中它,会把所有竖线全删掉。转写稿:“A 是没有兄弟的……last-child 只选亲兄弟。” .modify必须单独起类名:如果直接写.recommend a,会把上面所有小链接的颜色一起改掉。
示例 2:精品推荐课程(.course 标题 + .bd 内容 + 课程卡片)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>精品推荐课程</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
li { list-style: none; }
a { text-decoration: none; color: #333; }
body { background-color: #f3f5f7; }
/* 版心(笔记未给出,补充) */
.wrapper { width: 1200px; margin: 0 auto; }
/* 推荐课程 */
.course {
margin-top: 15px;
}
/* 标题 - 公共类,与其他区域共用 */
.hd {
display: flex;
justify-content: space-between;
height: 60px;
line-height: 60px;
}
.hd h3 {
font-size: 21px;
font-weight: 400;
}
.hd .more {
padding-right: 20px;
/* 笔记中的箭头图片,本地无图时会不显示,不影响布局 */
background: url(../images/more.png) no-repeat right center;
font-size: 14px;
color: #999;
}
/* 课程内容 - 公共类 */
.bd ul {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.bd li {
margin-bottom: 14px;
width: 228px;
height: 271px;
background-color: #fff;
}
/* 卡片整体可点击(转写稿:A 转块元素、高度 100%) */
.bd li a {
display: block;
height: 100%;
}
.bd li .pic {
height: 156px;
}
/* 笔记未给,补充:防止图片撑破盒子 */
.bd li .pic img {
width: 100%;
display: block;
}
.bd li .text {
padding: 20px;
height: 115px;
background-color: #fff;
}
.bd li .text h4 {
margin-bottom: 13px;
height: 40px;
font-size: 14px;
line-height: 20px;
font-weight: 400;
}
.bd li .text p {
font-size: 14px;
line-height: 20px;
color: #999;
}
.bd li .text p span {
color: #fa6400;
}
.bd li .text p i {
font-style: normal;
}
</style>
</head>
<body>
<!-- 精品推荐课程 -->
<div class="course wrapper">
<!-- 标题 -->
<div class="hd">
<h3>精品推荐</h3>
<a href="#" class="more">查看全部</a>
</div>
<!-- 内容 -->
<div class="bd">
<ul>
<li>
<a href="#">
<div class="pic"><img src="./uploads/course01.png" alt=""></div>
<div class="text">
<h4>JavaScript数据看板项目实战</h4>
<p><span>高级</span> · <i>1125</i>人在学习</p>
</div>
</a>
</li>
<li>
<a href="#">
<div class="pic"><img src="./uploads/course02.png" alt=""></div>
<div class="text">
<h4>Vue.js实战——面经全端项目</h4>
<p><span>高级</span> · <i>2726</i>人在学习</p>
</div>
</a>
</li>
<li>
<a href="#">
<div class="pic"><img src="./uploads/course03.png" alt=""></div>
<div class="text">
<h4>玩转Vue全家桶,iHRM人力资源项目</h4>
<p><span>高级</span> · <i>9456</i>人在学习</p>
</div>
</a>
</li>
<li>
<a href="#">
<div class="pic"><img src="./uploads/course04.png" alt=""></div>
<div class="text">
<h4>Vue.js实战医疗项目——优医问诊</h4>
<p><span>高级</span> · <i>7192</i>人在学习</p>
</div>
</a>
</li>
<li>
<a href="#">
<div class="pic"><img src="./uploads/course05.png" alt=""></div>
<div class="text">
<h4>小程序实战:小兔鲜电商小程序项目</h4>
<p><span>高级</span> · <i>2703</i>人在学习</p>
</div>
</a>
</li>
<li>
<a href="#">
<div class="pic"><img src="./uploads/course06.png" alt=""></div>
<div class="text">
<h4>前端框架Flutter开发实战</h4>
<p><span>高级</span> · <i>2841</i>人在学习</p>
</div>
</a>
</li>
</ul>
</div>
</div>
</body>
</html>关键行与易错点
.hd写成不带父级前缀的公共类(不是.course .hd),因为下面“前端开发工程师”等模块的头部长得一模一样,可以直接复用(转写稿:“复用的就不能带父亲”)。.hd { display: flex; justify-content: space-between; }:标题靠左、查看全部靠右,一句话解决。.bd ul { display: flex; flex-wrap: wrap; justify-content: space-between; }:flex-wrap: wrap必须写,flex 默认所有子元素挤在一行不换行;space-between让一行 5 个卡片两端对齐。- 卡片间距用
.bd li { margin-bottom: 14px; }给每个 li 挤下来,而不是给 ul 定高 + 多行对齐,这样以后加到 15 个、20 个也不会乱。 .bd li尺寸228 × 271是严格量出来的,156 + 115 = 271,.pic和.text高度加起来不能超过它。.bd li .text h4 { height: 40px; line-height: 20px; }高度必须写死:标题有一行的也有两行的,不写高的话下面“高级 · xx人在学习”会一个高一个低;写死 40px(两行)后不管一行两行,下面的 P 永远对齐。转写稿:“这个 H4 必定有高,这个高度是必定写死的。”.bd li a { display: block; height: 100%; }:a 默认是行内元素,只有文字那么宽;转成块元素并给 100% 高,整张卡片才能点。- 结构必须是
li > a > div.pic + div.text,不能a > li——ul 里只能放 li。 <i>要写font-style: normal,否则“人在学习”前面的数字会变斜体。- 图片路径
./uploads/course01.png与../images/more.png是笔记原路径,本地没图时图片不显示、箭头不显示,但不影响盒子布局。
示例 3:前端开发工程师模块头部(复用 .hd + 导航小 ul)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>前端开发工程师模块头部</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
li { list-style: none; }
a { text-decoration: none; color: #333; }
body { background-color: #f3f5f7; }
.wrapper { width: 1200px; margin: 0 auto; }
.course { margin-top: 15px; }
/* 与上一模块完全相同的公共类,直接复用 */
.hd {
display: flex;
justify-content: space-between;
height: 60px;
line-height: 60px;
}
.hd h3 {
font-size: 21px;
font-weight: 400;
}
.hd .more {
padding-right: 20px;
background: url(../images/more.png) no-repeat right center;
font-size: 14px;
color: #999;
}
/* 新增:中间的导航小 ul */
.hd ul {
display: flex;
}
.hd ul li a {
margin: 0 30px;
font-size: 16px;
}
/* 当前选中项(热门)单独变色 */
.hd .hot {
color: #00a4ff;
}
</style>
</head>
<body>
<!-- 前端模块 -->
<div class="course wrapper">
<div class="hd">
<h3>前端开发工程师</h3>
<ul>
<li><a href="#" class="hot">热门</a></li>
<li><a href="#">初级</a></li>
<li><a href="#">中级</a></li>
<li><a href="#">高级</a></li>
</ul>
<a href="#" class="more">查看全部</a>
</div>
</div>
</body>
</html>关键行与易错点
- 头部整段是从上一模块
.hd整块复制过来的,只把<h3>文字换成“前端开发工程师”、在 h3 和 a 之间补一个 ul(转写稿:“一句话没写,就是复制和粘贴”)。这就是把.hd写成公共类的好处。 .hd ul { display: flex; }:li 默认竖着排,找到 li 的亲爸爸 ul 加 flex 才能横过来(不是给 hd 加)。- 间距用
.hd ul li a { margin: 0 30px; }:转写稿里明确区分——想“只有点字才跳转”就给 margin;想“点旁边空白也能点”就给 padding,按需求选。 - 第一个“热门”是蓝色,必须单独给 A 加类名
hot再.hd .hot { color: #00a4ff; }。如果直接写.hd ul li a改颜色,四个都会变蓝。 .hd .more的箭头图是背景图 +padding-right留位置,本地没有more.png时只是箭头不显示;也可以用<i>字体图标替代,笔记里备注“等讲字体图标时只需调一个类名”。
常见错误
1. 加了 justify-content: space-between 后,「修改兴趣」贴右了,但中间那串标签跑到了正中间
- 现象:标题贴左、修改兴趣贴右,中间的
ul悬在水平中央,与设计稿不符。 - 原因:两端对齐只分配"两侧固定、中间自动"的剩余空间,
ul宽度由内容决定,自然被推到中间。 - 修法:给
ul加flex: 1,让它吃满剩余空间,内部文字默认左对齐,标签就贴在标题右侧。
2. 竖线用 li 的 border-right 画,结果竖线几乎顶满整条 60px 高
- 现象:分隔线又高又丑,比文字高出一大截。
- 原因:
li在 flex 容器里被拉伸,加上继承的line-height: 60px,盒子高度接近整行。 - 修法:把
border-right挪到a上(a是行内元素,高度随文字),间距用a的左右padding撑开。
3. 去掉最后一条竖线时写成 a:last-child 或 li a:last-child,结果所有竖线全没了
- 现象:本想只去掉最后一个,实际全部消失。
- 原因:每个
li里只有一个a,它既是第一个也是最后一个孩子;结构伪类只认亲兄弟,不认"表兄弟"。 - 修法:先选最后一个
li,再选它里面的a:.recommend ul li:last-child a { border-right: 0; }。
4. 用 .recommend a 统一改颜色,导致标签区的链接集体变色
- 现象:只想让"修改兴趣"变蓝,结果
ul里所有链接一起变。 - 原因:后代选择器命中区域内全部
a,没有做隔离。 - 修法:给目标链接单独加类(如
.modify、.more),选择器写成.recommend .modify;同理.hd .more隔离"查看全部"。
5. 课程卡片标题 h4 不给固定高度,「高级 · N人在学习」参差不齐
- 现象:一行标题的卡片,副信息贴着标题;两行标题的卡片,副信息被顶下去,同一行卡片高度不齐。
- 原因:内容多少撑开盒子,
h4高度随文字行数变化。 - 修法:给
h4写死高度(按两行算),内容区用margin而非padding定位,保证副信息基线一致。
6. 卡片尺寸没严格按 228×271 写,一行放不下 5 个 / 换行错位
- 现象:第 5 个卡片被挤到下一行,或右侧留白不均匀。
- 原因:
li宽度加边框/内边距后超出容器,flex-wrap提前折行。 - 修法:
li固定宽高并注意box-sizing,父级ul用flex-wrap: wrap+justify-content: space-between,行间距用margin-bottom控制。
7. 整张课程卡片只有文字能点,图片区域点不动
- 现象:鼠标移到图片上不出现手型,点击无效。
- 原因:
a是行内元素,且未撑满li,可点区域只有内容本身。 - 修法:
a { display: block; height: 100%; },让链接铺满整个卡片。
8. ul 加 display: flex 后卡片全挤在一行,不换行
- 现象:10 个卡片横向溢出,页面出现横向滚动条。
- 原因:flex 默认
nowrap,不会自动折行。 - 修法:
flex-wrap: wrap;配合space-between实现每行两端对齐。
练习
练习 1(排错) 下面这段代码执行后,标签之间的竖线全部消失,请指出问题并给出正确写法:
css
.recommend ul li a:last-child { border-right: 0; }练习 2(需求变更) 标签区原本 9 个标签,产品要求增加到 15 个,同时「修改兴趣」必须始终贴在容器最右侧、不得掉行。请说明你的 CSS 需要满足哪两个条件,并解释为什么不用 margin-left: auto 之外的定宽方案也能成立。
练习 3(交互改造) 要求:鼠标经过任一课程卡片时出现阴影并轻微上浮;点击卡片任意位置(含图片)都能跳转。请写出需要的选择器与关键声明(不需要具体数值)。
练习 4(结构判断) 有同学把课程卡片写成 <a><li>...</li></a>,请判断是否合法、会导致什么后果,并给出正确结构。
练习 5(复用设计) 页面下方还有 3 个结构相同的"标题 + 查看全部"区域。请说明你会如何命名和书写这部分样式,使它能被 4 个模块共用,同时不会误伤其他区域的链接。
原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | 精品推荐h3设置 | 07:07 |
| 2 | 精品推荐ul的制作 | 10:39 |
| 3 | 精品推荐模块完成 | 10:19 |
| 4 | 课程模块hd盒子搭建 | 11:43 |
| 5 | 课程模块li盒子搭建 | 08:29 |
| 6 | 课程模块li盒子完成 | 08:41 |
| 7 | 产品模块布局完成 | 06:00 |
| 8 | 前端模块hd制作 | 08:34 |
小结
- 一行内"左标题 + 中间一堆标签 + 右操作"的布局,标准解法是父级
flex+ 中间容器flex: 1,比用固定margin推算更稳,条目增减都不塌。 - 分隔竖线画在行内元素
a上而不是li上,是这类导航条目的通用经验:li会被 flex 拉伸,a不会。 - 结构伪类(
:first-child/:last-child)只作用于同一父级下的亲兄弟,跨层级的"最后一个"必须先选父再选子。 - 区域内的公共标签样式一定要靠类名隔离,否则后续新增的链接会被"顺手"改掉,这是本页出现两次的同类问题。
- 卡片式列表的三个硬约束:
li尺寸严格、ul必须flex-wrap: wrap、标题区必须固定高度——少一个就会出现错位。 a要承担整卡点击,必须display: block+height: 100%,行内元素天生不撑满。- 可复用模块(
.hd/.bd)命名时不要带父级前缀,直接写独立类名,才能被多个模块复制复用。 - 布局调试的小技巧:临时给
body加大高度拉出滚动条、给占位块加background-color,验证完再删除。