主题
CSS 高级(三)
本页对应 CSS 高级,共 8 段视频,约 1 小时 13 分。
学习目标
- 能使用
vertical-align: middle实现图片、行内块元素与文字的垂直居中,并解释基线对齐导致图片底部空隙的原因,能用非baseline对齐或display: block两种方法消除空隙。 - 能将
transition写在元素本身,结合:hover实现宽、高、颜色等属性的过渡,并说明过渡属性、持续时间、all的作用以及写在:hover中导致鼠标移出无过渡的问题。 - 能完成学成在线中的过渡效果:侧边栏文字位移、卡片上浮加阴影、输入框聚焦变宽,并正确使用
padding、负margin-top、:focus和transition。 - 能区分
opacity与rgba背景透明:使用opacity实现整个盒子及内容半透明,使用rgba实现仅背景半透明而文字不透明,并说明开发中更常用的方案。 - 能设置常见鼠标样式
default、pointer、text、move、not-allowed,并能为button强制设置小手样式;能完成表格边框、border-collapse: collapse、内容居中和nth-child(2n/odd)隔行变色。 - 能按
ul > li > a > img结构搭建淘宝轮播图外层盒子,设置固定宽高、overflow: hidden、圆角隐藏、图片display: block与宽度适配,并说明轮播图通过整体移动ul实现滚动的原理。
知识点
垂直对齐方式

为什么需要:图片、span 等行内块元素和文字排在一行时,默认按文字基线对齐,常出现“图片不居中”或图片底部多出一条缝隙。转写稿里用京东布局复现过:图片放在盒子中,底部总有几像素空白,原因就是图片默认与文字基线对齐。
怎么想:文字可理解为有顶线、中线、基线、底线几条参考线。图片默认对齐的是 baseline(基线),不是盒子底线。想垂直居中,就把图片的对齐线改到中线 middle。
怎么做:

html
<style>
img {
/* 行内块元素默认和文字基线对齐 */
vertical-align: middle;
}
span {
display: inline-block;
vertical-align: middle;
width: 50px;
height: 50px;
background-color: pink;
}
div {
border: 2px solid red;
}
</style>
<img src="./images/computer.png" alt=""> my name is 刘德华
<span></span> my name is 刘德华
<hr>
<div>
<img src="./images/1.webp" alt="">
</div>去除图片底部缝隙的两种方法:
- 给图片加
display: block;; - 给图片加
vertical-align: middle;等,只要不是baseline即可。
易错点:vertical-align 主要作用于行内元素、行内块元素;块元素独占一行,不靠它做“文字基线对齐”。写 baseline 等于默认值,缝隙仍会出现。
过渡与 focus
为什么需要:hover 直接改宽高、颜色会“嗖”地突变,不自然。transition 让元素在不同状态间平滑过渡。
怎么想:谁做动画,过渡写给谁。转写稿反复强调:“谁做过渡给谁加”,一般写在元素本身,而不是只写在 :hover 里。只写 height 就只过渡高度;写 all 则所有变化属性一起过渡。
怎么做:
css
.box {
width: 200px;
height: 200px;
background-color: pink;
/* 谁做过渡给谁加 */
transition: all .3s;
}
.box:hover {
height: 300px;
width: 300px;
background-color: green;
}
input {
width: 200px;
height: 30px;
transition: all .3s;
}
/* 当表单得到光标的时候 */
input:focus {
width: 300px;
background-color: pink;
}易错点:时间单位是秒 s,0.3s 可写 .3s;把 transition 只写进 :hover,鼠标离开时往往没有“回去”的过渡。:focus 是表单获得光标,不是鼠标经过。
透明度 opacity
为什么需要:有时要让整个盒子半透明,有时只想背景半透明而文字清楚。二者效果不同。
怎么想:opacity 作用于整个元素,包含背景和内容;rgba() 只让背景色透明,内容不受影响。转写稿对比过:opacity 盒子里文字也半透明,而 rgba 盒子文字仍是白色不透明。
怎么做:
css
.box1 {
width: 200px;
height: 200px;
background-color: pink;
opacity: 0.2; /* 0 完全透明,1 不透明 */
}
.box2 {
width: 200px;
height: 200px;
background-color: rgba(0, 0, 0, 0.3);
color: #fff;
}易错点:opacity 的取值范围是 0–1;开发中更常用 rgba 做“背景半透明、文字不透明”,避免文字看不清。
光标类型 cursor
为什么需要:不同元素有不同交互含义:可点击、可选文本、可移动、禁止操作。鼠标指针能提示用户。

怎么做:
css
div:nth-child(1) { cursor: default; }
div:nth-child(2) { cursor: pointer; } /* 小手 */
div:nth-child(3) { cursor: text; } /* 文本 */
div:nth-child(4) { cursor: move; } /* 移动 */
div:nth-child(5) { cursor: not-allowed; } /* 禁止 */
button { cursor: pointer; }
易错点:button 默认常是普通箭头,想提示可点击要手动加 cursor: pointer;。not-allowed 常用于“数量不能再减”等不可操作状态。
表格样式与合并相邻边框

为什么需要:表格默认每个单元格都有自己的边框,相邻边框会形成双线缝隙,不像真正表格。
怎么想:转写稿演示过:只给 table 加边框,只有外框;行列边框属于 tr、td。相邻两个边框要用 border-collapse: collapse; 合并成一条。
怎么做:
css
table {
width: 700px;
height: 400px;
margin: 0 auto;
text-align: center;
}
table, tr, td {
border: 1px solid pink;
/* 合并相邻的两个边框 */
border-collapse: collapse;
}
tr:nth-child(even) { background-color: #eee; } /* 2n 偶数 */
tr:nth-child(odd) { background-color: #ddd; } /* 2n+1 奇数 */html
<table>
<tr>
<td>内</td><td>内</td><td>内</td><td>内</td><td>内</td>
</tr>
</table>易错点:只写 table 边框不会自动出现单元格内线;不写 border-collapse: collapse; 相邻边框会分开。2n 等价 even,2n+1 等价 odd,隔行变色时注意奇偶顺序。
案例目标与整体结构

为什么需要:轮播图一次只展示一张图,但图片本身要横向排成一排,后续才能通过移动整体容器实现切换。
怎么想:先看大盒子:.banner 固定宽高并 overflow: hidden,只露出第一张;里面用 ul > li > a > img,让 ul 横向排列。转写稿里反复强调:轮播图不是让每张图片单独乱动,而是“ul 包小 li,li 里再放 a 和图片”,后期让 ul 整体移动。
怎么做:先搭图片区结构。
html
<div class="banner">
<!-- 图: ul > li -->
<ul>
<li><a href="#"><img src="./images/banner1.jpg" alt=""></a></li>
<li><a href="#"><img src="./images/banner2.jpg" alt=""></a></li>
<li><a href="#"><img src="./images/banner3.jpg" alt=""></a></li>
</ul>
</div>css
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
li {
list-style: none;
}
.banner {
position: relative;
margin: 100px auto;
width: 564px;
height: 315px;
/* background-color: pink; */
overflow: hidden;
}
/* 图片 */
.banner img {
width: 564px;
border-radius: 12px;
vertical-align: middle;
}
.banner ul {
display: flex;
}易错点:.banner 必须 overflow: hidden,否则横向排列的图片会全部露出来;ul 用 display: flex 让 li 在一行;图片宽度要和盒子宽度一致。转写稿还提到图片默认和文字基线对齐,底部容易出现小缝隙,所以这里用 vertical-align: middle 处理。若按转写稿的调试思路,也可以给图片加 display: block 去除底侧缝隙;父盒子加圆角并配合 overflow: hidden 更稳妥。
箭头:父相子绝与垂直居中
为什么需要:用户需要知道可以上一张、下一张;箭头默认不显示,鼠标进入轮播区域再出现,画面更干净。
怎么想:箭头以 .banner 为定位参照,所以 .banner 写 position: relative,箭头写 position: absolute。垂直居中用 top: 50% 加 transform: translateY(-50%)。转写稿讲定位时也强调“父相子绝”,这里正合适。
怎么做:
html
<!-- 箭头 -->
<!-- 上一张 prev -->
<a href="#" class="prev">
<i class="iconfont icon-zuoce"></i>
</a>
<!-- 下一张 next -->
<a href="#" class="next">
<i class="iconfont icon-youce"></i>
</a>css
/* 箭头 */
.banner .prev,
.banner .next {
/* 隐藏 */
display: none;
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 20px;
height: 30px;
background-color: rgba(0,0,0, 0.3);
text-decoration: none;
color: #fff;
line-height: 30px;
}
/* 鼠标滑到banner区域,箭头要显示 display:block */
.banner:hover .prev,
.banner:hover .next {
display: block;
}
.banner .prev {
left: 0;
border-radius: 0 15px 15px 0;
}
.banner .next {
right: 0;
border-radius: 15px 0 0 15px;
text-align: center;
}易错点:箭头默认 display: none,要在 .banner:hover 下改回 display: block;top: 50% 后必须加 translateY(-50%) 才是真正垂直居中;a 要去下划线并设文字颜色;i 使用 iconfont 图标类,实际页面要保证图标字体已引入。转写稿讲圆角时提到按顺时针写四个值,这里左右箭头的圆角方向不同,是为了贴边更像半圆按钮。
圆点:底部居中与当前项标识
为什么需要:圆点告诉用户一共有几张图、当前在第几张。
怎么想:圆点整体在底部水平居中,所以 ol 绝对定位:bottom: 20px; left: 50%; transform: translateX(-50%);内部 li 用 flex 排成一行;当前项加 .active 变橙色。
怎么做:
html
<!-- 圆点 -->
<ol>
<li></li>
<li class="active"></li>
<li></li>
</ol>css
/* 圆点 */
.banner ol {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
height: 13px;
background-color: rgba(255,255,255,0.3);
display: flex;
border-radius: 10px;
}
.banner ol li {
margin: 3px;
width: 8px;
height: 8px;
background-color: #fff;
border-radius: 50%;
cursor: pointer;
}
/* 橙色的li */
.banner ol .active {
background-color: #ff5000;
}易错点:left: 50% 只是把左边缘放到中间,必须再 translateX(-50%) 才水平居中;ol 也要 position: absolute,否则不会贴在轮播图底部;li 要 border-radius: 50% 才是圆点;当前项靠 .active 区分。转写稿中提到的“黑电的”就是 hidden,本节核心仍是 .banner 的 overflow: hidden 和 ul 横向排列;切换逻辑属于后续 JS 部分,本节先把结构和样式搭稳。
课件图示





代码示例
示例一:vertical-align 垂直对齐(含图片底部缝隙)
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
img {
/* 行内块元素 默认和文字的基线对齐*/
vertical-align: middle;
}
span {
display: inline-block;
vertical-align: middle;
width: 50px;
height: 50px;
background-color: pink;
}
div {
/* width: 300px;
height: 300px; */
border: 2px solid red;
}
</style>
</head>
<body>
<img src="./images/computer.png" alt=""> my name is 刘德华
<span></span> my name is 刘德华
<hr>
<div>
<img src="./images/1.webp" alt="">
</div>
</body>
</html>关键行与易错点
img { vertical-align: middle; }:图片是行内块元素,默认与文字基线(baseline)对齐,改成middle才和文字中线对齐;top、bottom同理,只要不是baseline都行。span必须先display: inline-block才和图片一样参与行内对齐,否则宽高不生效;vertical-align: middle与display: inline-block这两个常一起写。- 图片底部缝隙:图片默认基线对齐,基线下方还留着文字下沿的空间,所以盒子底部会出现几像素空白。两种解法:①
vertical-align改成middle等非baseline值;② 给图片display: block(块元素独占一行,不存在基线对齐问题)。 - 易错点:
vertical-align只对行内元素、行内块元素有效,给块元素加是无效的;属性写在图片/行内块自身身上,不是写在父盒子上。 - 代码里的
./images/xxx.png是笔记中的图片路径,实际运行请换成自己的图片,否则图片不显示(span的居中效果仍然可见)。
示例二:transition 过渡 + :focus 表单获得焦点
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box {
width: 200px;
height: 200px;
background-color: pink;
/* 谁做过渡给谁加 */
transition: all .3s;
}
.box:hover {
height: 300px;
width: 300px;
background-color: green;
}
input {
width: 200px;
height: 30px;
transition: all .3s;
}
/* 当表单得到光标的时候 */
input:focus {
width: 300px;
background-color: pink;
}
</style>
</head>
<body>
<div class="box"></div>
<input type="text">
</body>
</html>关键行与易错点
transition: all .3s;:复合属性,第一个值是过渡的属性(all表示所有变化的属性都过渡,也可以写height、width等具体属性),第二个值是花费时间,单位秒。- 最重要的一条:谁做过渡给谁加。
transition必须写在.box、input这些元素本身的样式里,不能写在:hover、:focus里。写在:hover里,鼠标移入有过渡、移出瞬间弹回,没有“慢慢回去”的效果。 input:focus:表单**得到光标(被点击、可以开始输入)**时生效,注意它和:hover(鼠标经过)是两种不同状态。- 易错点:时间必须带单位,
.3s正确,写成.3无效;0.3s的 0 可以省略。另外别把transition(过渡)和transform(变形)写混。
示例三:表格样式——合并相邻边框与隔行变色
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
table {
width: 700px;
height: 400px;
margin: 0 auto;
text-align: center;
}
table,
tr,
td {
border: 1px solid pink;
/* 合并相邻的两个边框 */
border-collapse: collapse;
}
/* 2n 偶数 / even */
/* tr:nth-child(2n) {
background-color: #eee;
} */
tr:nth-child(even) {
background-color: #eee;
}
/* 2n+1 奇数 odd */
tr:nth-child(odd) {
background-color: #ddd;
}
</style>
</head>
<body>
<table>
<tr>
<td>内</td>
<td>内</td>
<td>内</td>
<td>内</td>
<td>内</td>
</tr>
<tr>
<td>内</td>
<td>内</td>
<td>内</td>
<td>内</td>
<td>内</td>
</tr>
<tr>
<td>内</td>
<td>内</td>
<td>内</td>
<td>内</td>
<td>内</td>
</tr>
<tr>
<td>内</td>
<td>内</td>
<td>内</td>
<td>内</td>
<td>内</td>
</tr>
<tr>
<td>内</td>
<td>内</td>
<td>内</td>
<td>内</td>
<td>内</td>
</tr>
<tr>
<td>内</td>
<td>内</td>
<td>内</td>
<td>内</td>
<td>内</td>
</tr>
</table>
</body>
</html>关键行与易错点
- 边框要写成
table, tr, td三个一起加:只给table加边框,只有外面一个大方框,里面没有横竖线,因为表格的横线竖线是由行和单元格撑出来的。 border-collapse: collapse;:合并相邻的两个边框。默认每个单元格都是独立的四方块,相邻边框会变成“双线+缝隙”,collapse 后两条线折叠成一条,才像真正的表格。写表格基本离不开这句。tr:nth-child(even)等价于tr:nth-child(2n)(偶数行),tr:nth-child(odd)等价于tr:nth-child(2n+1)(奇数行),两种写法都要认识。- 易错点:
nth-child的数字是从 1 开始、按所有同级tr计数,不是“第几个变色”;另外text-align: center写在table上可以继承给单元格里的文字实现水平居中。
常见错误
图片下方多出几像素缝隙 现象:
div包一张图,容器总比图片高一点,出现白边。 原因:img是行内块元素,默认与文字基线 baseline 对齐,基线下方还要给字母下沉部分留空间。 修法:给img加display: block;或vertical-align取middle / top / bottom任一非baseline值。过渡只"去"不"回" 现象:鼠标移入有动画,移出瞬间跳回原状。 原因:
transition写在了:hover里,只在悬停态生效。 修法:transition写在元素本身的选择器上(谁做过渡给谁加)。动画只有一半属性生效 现象:宽高都变了,只有高度渐变,宽度"嗖"地跳过去。 原因:
transition属性值只写了height。 修法:transition: all .3s;,需要分别控制时用逗号分隔多组「属性 时间」。遮罩层把文字也变模糊了 现象:给盒子加
opacity: .3后,里面的文字一起半透明。 原因:opacity作用于整个元素,含背景与内容。 修法:改用background: rgba(0,0,0,.3),只让背景透明。表格边框出现双线缝隙 现象:
table, tr, td都加border后,单元格之间是两条线。 原因:相邻单元格边框各自独立、叠加显示。 修法:在table上加border-collapse: collapse;。轮播图圆角处露出直角 现象:盒子给了
border-radius,但图片四角仍是方的、溢出到圆角外。 原因:圆角只作用于父盒子,图片是矩形且溢出。 修法:给父盒子补overflow: hidden;(图片本身不必加圆角)。轮播图多张图片竖着排 / 只显示第一张 现象:
li换行,父盒子里只看到一张图。 原因:li是块级元素独占一行;或ul宽度不足、父级没裁剪。 修法:ul设display: flex(或li浮动),ul宽度足以容纳全部li,父级.banner加overflow: hidden。:focus写了没反应 现象:点进输入框宽度不变。 原因:把:focus写成:hover,或拼写/冒号出错。 修法:input:focus { ... },并确认宽度变化有transition才平滑。
练习
图文对齐:一行内放一张
img和一段文字,让图片与文字垂直居中;再把图片放进带红色边框的div中,分别用两种方法消除底部缝隙,并在注释里写出各自原理。过渡卡片:
.box尺寸 200×200 粉色,鼠标悬停变 300×300 且背景变绿。要求宽、高、颜色三者同时渐变,时间 0.3s;完成后故意把transition挪到:hover里观察差异,并说明原因。搜索框:
input宽 200、高 30,聚焦时宽度变 300、背景变粉,带过渡与圆角。再用浏览器开发者工具在任意网站找一个"聚焦变宽"的输入框,对照其写法。半透明遮罩:
body铺一张背景图,上面放一个 200×200 的遮罩盒,要求背景半透明、文字完全不透明;另建一个用opacity实现的版本,对比两者文字清晰度。斑马纹表格:6 行 5 列,宽 700、高 400 居中,单元格文字居中,相邻边框合并;奇数行
#ddd、偶数行#eee,分别用2n/2n+1和even/odd各写一遍。轮播图骨架:搭建
.banner(564×315,居中,overflow: hidden)+ul>li>a>img三张图,实现图片横向排列、圆角显示;再补左右箭头(默认隐藏、悬停.banner显示、垂直居中)与底部三个圆点(第二个为激活态)。
原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | 垂直居中 | 17:18 |
| 2 | 过渡 | 06:02 |
| 3 | 学成在线效果 | 08:40 |
| 4 | 盒子半透明opacity | 05:41 |
| 5 | 鼠标样式 | 09:22 |
| 6 | 表格样式 | 07:09 |
| 7 | 淘宝开始 | 12:21 |
| 8 | 作业布置 | 07:13 |
小结
vertical-align只对行内 / 行内块元素生效,块级元素独占一行不存在这个问题——这是图片缝隙类问题的根因。- 消除图片底部缝隙两条路:
display: block(跳出对齐规则)或vertical-align取非baseline值(改对齐线),后者更常用于图文混排。 transition的记忆口诀是"谁做动画给谁加",写在元素本体而非:hover,否则只有单向效果。- 过渡值优先写
all .3s,需要精细控制时再拆成逗号分隔的多组;时间单位是秒,0.3s可写.3s。 opacity与rgba的分工:整体(含内容)透明用opacity,仅背景透明用rgba;实际开发中后者使用频率远高于前者。cursor是提示性属性:可点击的a、button(button 默认不是小手,需手动加pointer)用pointer,不可用状态用not-allowed。- 表格样式的必备一句是
border-collapse: collapse,配合:nth-child(2n/2n+1)完成斑马纹,:nth-child(even/odd)与之等价。 - 轮播图布局的本质是"
ul装多个li横向排列 + 父级裁剪",后续的滚动切换动的是ul整体,所以结构与overflow: hidden必须一次搭对。