主题
CSS3 新增盒子相关样式(Day12 3/3)
本页对应 Day12_CSS3,共 5 段视频,约 1 小时 1 分。
学习目标
- 能列举
display的常用值,并通过修改元素display值实现块级、行内块、列表项等显示模式切换,解释list-item对列表标记的影响。 - 能使用
box-sizing在content-box与border-box间切换,计算并验证元素内容宽高、内边距、边框与总宽高之间的关系。 - 能使用
box-shadow设置水平/垂直偏移、模糊值、外延值、颜色、inset内阴影及逗号分隔的多重阴影,并实现输入框悬停、聚焦时的阴影变化效果。 - 能区分
opacity与rgba背景透明度的作用范围,设置0–1的opacity实现元素整体半透明,并验证文字、背景及后代元素一起透明。 - 能使用
position: sticky配合top等偏移实现导航条滚动吸顶,并说明其与固定定位的差异及粘连触发条件。
知识点
display:让元素可切换显示模式
为什么需要:CSS 的初衷是让结构归 HTML、样式归 CSS,因此需要一套机制让元素能切换显示模式。display 不只是 block、inline-block,它还有很多值,可以让元素表现得像列表项、表格行、单元格等。
怎么想:list-style-type 只能对 display: list-item 的元素生效。p 默认是 display: block,所以给 p 设小圆点无效;把 p 改成 list-item 后,小圆点才出现。转写稿里演示的正是这个推导:不是选择器不行,而是元素的 display 不是 list-item。
怎么做:
css
p.item {
display: list-item;
list-style-type: disc;
}易错点:不要用 p、div 硬仿列表,语义不如 ul/li;表格类 display 值能演示,但实际项目没必要“拿 div 装表格”;flex 等值后续再学,先别混用。
box-sizing:调整宽高设置规则
为什么需要:默认 content-box 下,width/height 只表示内容区,总宽高还要加 padding 和 border。设计稿量出 400×300 时,开发者要反算内容宽高,容易算错。
怎么想:border-box 让 width/height 表示总宽总高,浏览器自动把 padding 和 border 算进去,内容区自动缩小。转写稿调试两个盒子:同样 width:400; height:300; padding:20; border:3px dashed #900;,content-box 总宽高是 446×346,border-box 总宽高是 400×300。
怎么做:
content-box width和height设置的内容宽高,默认值
border-box width和height设置的总宽总高,也称为怪异模式易错点:border-box 常被叫“怪异模式”,这是历史叫法,来自早期 IE 的宽高计算方式,正式规范不这么命名;全局设置后内容区可能变小,要检查内容是否溢出。
盒子阴影 box-shadow
为什么需要:阴影能让盒子更有立体感,输入框内阴影也能表达状态。转写稿里鼠标悬停上移并加阴影,就是典型应用。
怎么想:长度值按顺序解析:前两个必写,是 X、Y 偏移;第三个是模糊值;第四个是外延值。颜色可写在长度前或后;inset 表示内阴影;多阴影用逗号分隔。转写稿还调试出:默认阴影颜色跟随 color;偏移不能用百分比;长度必须连续写,颜色和 inset 位置较灵活。
怎么做:
css
box-shadow: x偏移 y偏移 模糊值 外延值 颜色 内阴影;css
/* 设置阴影的偏移位置 x方向 y方向 */
box-shadow: 10px 5px;
/* 设置阴影的 偏移位置 颜色 */
box-shadow: -5px 10px #ccc;
box-shadow: #099 -5px -10px;
/* 设置阴影的模糊值 */
box-shadow: 5px 5px 10px;
/* 设置阴影的模糊值 颜色 */
box-shadow: 5px 5px 10px #ccc;
box-shadow: rgba(0,0,0,.3) 5px 5px 10px;
/* 阴影不偏移 靠模糊值向四周扩散 */
box-shadow: 0 0 15px #000;
/* 设置外延值 */
box-shadow: 3px 3px 5px 1px #080;
/* 设置内阴影 */
box-shadow: 10px 10px inset;
box-shadow: -10px 10px inset;
box-shadow: inset -10px -10px #000;
/* 多阴影 */
box-shadow: 5px 0 5px #f00,
0 5px 5px #080,
-5px 0 5px #088,
0 -5px 5px #880;易错点:长度值必须连续,别把颜色插在长度中间;外延值一般少用;多阴影最后用逗号,不是分号;内阴影常用于输入框,但别把阴影调得太清晰。
不透明度 opacity
为什么需要:有时要让整个元素半透明,包括背景、文字和子元素。rgba() 只改变某个颜色,不会让文字一起透明。
怎么想:转写稿对比了 background: rgba(0,0,0,.5) 和 opacity:.5:前者文字仍不透明,后者整体半透明。opacity 取 0 到 1,1 完全不透明,0 完全透明。
怎么做:
css
.box {
opacity: 0.5;
}易错点:不要把 opacity 和 rgba 背景混为一谈;opacity 会影响后代元素,做遮罩层时要注意。
粘连定位 position: sticky
为什么需要:导航条吸顶时,如果直接 position: fixed,它会一直固定;而 sticky 可以在滚动到视口顶部时粘住,滚回去还能恢复。
怎么想:转写稿调试时先给导航设 position: sticky,页面没变化,因为还要告诉它“粘到哪里”,于是加 top: 0,滚动到距视口顶部 0 时粘连。
怎么做:
css
.page-nav {
position: sticky;
top: 0;
}易错点:必须设置 top(或 bottom 等阈值),否则效果不明显;sticky 不是所有场景都适用,兼容性要查;别和 fixed 混淆。
属性选择器应用:按 href 结尾设置背景图
为什么需要:同一类链接可能指向不同文件类型,如果靠手写 class 区分,链接一多就容易漏、容易改错。属性选择器可以直接根据 href 的结尾匹配,让样式跟着链接地址走。
怎么想:作业要求“根据 href 属性值的结尾”设置背景图,结尾匹配用 $=。例如 .pdf 链接给 PDF 图标,.jpg 链接给图片图标;背景图放在右侧,再给链接留出右内边距,避免文字压住图标。
怎么做:
html
<a href="file.pdf">下载 PDF</a>
<a href="file.jpg">查看图片</a>css
a[href$=".pdf"] {
background: url("pdf.png") no-repeat right center;
padding-right: 20px;
}
a[href$=".jpg"] {
background: url("jpg.png") no-repeat right center;
padding-right: 20px;
}易错点:属性值要加引号;$= 表示“以……结尾”,^= 是开头,*= 是包含,别混用;背景图路径要正确;只设背景不设 padding,图标容易和文字重叠;不要写成 href=".pdf" 这种精确匹配。
:target 应用:点击链接切换图片
为什么需要:不写 JavaScript 也能做简单的图片切换。点击链接后 URL 的 hash 变化,:target 正好匹配当前 hash 指向的元素。
怎么想:准备多个图片,每张图有唯一 id;链接的 href="#id" 指向它。默认隐藏所有图片,被 :target 匹配的图片显示。
怎么做:
html
<a href="#pic1">图片一</a>
<a href="#pic2">图片二</a>
<img id="pic1" class="pic" src="1.jpg" alt="图片一">
<img id="pic2" class="pic" src="2.jpg" alt="图片二">css
.pic {
display: none;
}
.pic:target {
display: block;
}易错点:href 里的 #pic1 要和元素 id="pic1" 完全一致;默认全部隐藏时页面初始可能空白,需要额外处理默认显示;同一时刻通常只有一个 :target 生效;不要把 class 名当成 hash 目标。
:checked:用单选框控制图片切换
为什么需要::target 依赖地址栏 hash,刷新和前进后退会影响状态;:checked 借助表单控件的选中状态,更适合做一组互斥的图片切换,而且仍然不需要 JavaScript。
怎么想:一组同名 radio 天然互斥;用 label 的 for 绑定 input 的 id,点击文字就能选中单选框;图片默认隐藏,再用 :checked ~ 图片 显示对应图片。
怎么做:
html
<div class="gallery">
<input type="radio" name="pic" id="pic1" checked>
<input type="radio" name="pic" id="pic2">
<label for="pic1">图片一</label>
<label for="pic2">图片二</label>
<img class="pic pic1" src="1.jpg" alt="图片一">
<img class="pic pic2" src="2.jpg" alt="图片二">
</div>css
.gallery input {
position: absolute;
opacity: 0;
}
.gallery .pic {
display: none;
}
#pic1:checked ~ .pic1 {
display: block;
}
#pic2:checked ~ .pic2 {
display: block;
}易错点:label 的 for 必须等于对应 input 的 id;input 要放在图片前面,后面的 ~ 兄弟选择器才能选中图片;同名 radio 才能互斥;别忘了给默认项加 checked;隐藏 input 时不要影响可访问性,可用透明定位而不是简单粗暴删掉。
阴影作业:鼠标悬停加阴影
为什么需要:卡片、按钮、输入框加阴影能增强立体感和悬停反馈。转写稿里调试阴影时,先只写两个长度,阴影会像硬边色块;补上第三个长度“模糊值”后才变得朦胧。颜色可以写在前或后,但几个长度必须连续写,浏览器要按顺序解析偏移、模糊、外延。转写稿中同音出现的“阴养”“外颜值”“内一鸟”,对应的正确术语是阴影、外延值、内阴影。
怎么想:默认给卡片一个浅阴影或不给,:hover 时加大偏移和模糊,并用 rgba() 半透明黑色,让阴影自然。若做输入框,可用 inset 做内阴影;多阴影用逗号分隔。
怎么做:
css
.card {
width: 300px;
padding: 20px;
background: #fff;
}
.card:hover {
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.25);
}内阴影示例:
css
.input:focus {
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.2);
}多阴影示例:
css
.box {
box-shadow:
5px 0 5px #f00,
0 5px 5px #080,
-5px 0 5px #088,
0 -5px 5px #880;
}易错点:偏移位置不要用百分比,转写稿调试时百分比会被划掉;box-shadow 最少写两个长度,模糊值、外延值可选,但长度要连续;颜色可前可后;inset 表示内阴影;悬停变化不要太夸张,阴影本身应是朦朦胧胧的。
课堂画面





代码示例
示例一:box-sizing 调整宽高设置规则
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>调整宽高设置规则</title>
<style>
* { margin: 0; padding: 0; }
.box01,
.box02 {
width: 400px; /* 两个盒子写的是同样的宽高 */
height: 300px;
padding: 20px; /* 内边距 */
border: 3px dashed #900; /* 边框 */
background-color: #ccc;
display: inline-block; /* 让两个盒子排到一行 */
margin-left: 10px;
margin-top: 20px;
}
.box01 { box-sizing: content-box; } /* 默认值:宽高 = 内容宽高 */
.box02 { box-sizing: border-box; } /* 宽高 = 总宽总高(怪异模式) */
</style>
</head>
<body>
<div class="box01">box01</div>
<div class="box02">box02</div>
</body>
</html>关键行与易错点
.box01是默认的content-box:width:400px只框住内容区,实际占位 = 400 + 20×2(左右内边距)+ 3×2(左右边框)= 446px;高度 = 300 + 20×2 + 3×2 = 346px。.box02改成border-box:width:400px; height:300px就是总宽总高,内容区被自动压缩成 354×254,不用自己拿设计稿尺寸去减内边距和边框。- 易错点:两个盒子写了完全一样的宽高,量出来却一大一小,原因就在这里——先确认
box-sizing是什么值。 - 易错点:
border-box被老程序员叫“怪异模式”,是因为早期 IE 就这么算,并非它真的怪;现在绝大多数项目会统一* { box-sizing: border-box; }。 - 易错点:
border-box下若内边距 + 边框超过设置的宽高,内容区会被压到很小,不要反过来再手动加宽。
示例二:盒子阴影 box-shadow 全套写法
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>元素阴影</title>
<style>
body { background: #f5f5f5; }
.box {
width: 400px;
height: 100px;
padding: 10px;
margin: 20px 0 0 10px;
background: #fff;
}
/* ① 只写偏移:颜色默认跟随文字颜色 */
.box01 { box-shadow: 10px 5px; color: #f00; }
/* ② 偏移 + 模糊 + 颜色 */
.box02 { box-shadow: 5px 5px 10px #ccc; }
/* ③ 偏移 + 模糊 + 外延值 + 颜色 */
.box03 { box-shadow: 3px 3px 5px 1px #080; }
/* ④ 不偏移,靠模糊值向四周扩散 */
.box04 { box-shadow: 0 0 15px #000; }
/* ⑤ 内阴影:inset 关键字写前写后都行 */
.box05 { box-shadow: inset -10px -10px 10px rgba(0,0,0,.3); }
/* ⑥ 多阴影:逗号分隔 */
.box06 {
box-shadow: 5px 0 5px #f00,
0 5px 5px #080,
-5px 0 5px #088,
0 -5px 5px #880;
}
</style>
</head>
<body>
<div class="box box01">box01</div>
<div class="box box02">box02</div>
<div class="box box03">box03</div>
<div class="box box04">box04</div>
<div class="box box05">box05</div>
<div class="box box06">box06</div>
</body>
</html>关键行与易错点
- 完整语法:
box-shadow: x偏移 y偏移 模糊值 外延值 颜色 内阴影;。前两个长度必写(X 方向、Y 方向),正值向右/向下,负值向左/向上;第三、四个长度(模糊值、外延值)可省。 - 易错点:几个长度必须连续写,浏览器是按顺序解析每个长度的含义的;但颜色可以写在长度前面,也可以写在长度后面,
inset同理,写哪都行。 - 易错点:不写颜色时默认取
color(文字颜色),所以.box01我把文字设成红色,阴影也变红了——不是黑色。 - 易错点:偏移值不能用百分比(写了会被浏览器划掉),只能用长度。
- 易错点:外延值和模糊值不一样——模糊相当于“把墨水滴进水里稀释”,外延是整体放大;外延值实际项目里很少用。
- 易错点:只写
0 0而不给模糊值,是看不见阴影的,必须配合模糊值才会向四周发散。 - 多阴影之间只能用逗号分隔,最后一条后面不加逗号;换行只是为了可读性。
示例三:粘连定位 position: sticky + 不透明度 opacity
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>粘连定位 & 不透明度</title>
<style>
* { margin: 0; padding: 0; }
body {
background: #f5f5f5;
font-family: sans-serif;
}
.container { width: 1100px; margin: 0 auto; }
.page-header { padding: 30px 0; }
/* ===== 粘连定位 ===== */
.nav {
height: 40px;
line-height: 40px;
background: #900;
position: sticky; /* 粘连定位 */
top: 0; /* 距视口顶部 0 时粘住,必须写 */
}
.nav a {
color: #fff;
text-decoration: none;
margin: 0 15px;
}
/* ===== 不透明度对比 ===== */
.main { padding: 20px 0; }
.box {
width: 400px;
height: 300px;
padding: 20px;
display: inline-block;
vertical-align: top;
margin-right: 10px;
color: #fff;
font-size: 2em;
}
/* 只有背景半透明,文字不透明 */
.box01 { background: rgba(0, 0, 0, .5); }
/* 整个元素半透明,文字也跟着透 */
.box02 { background: #000; opacity: .5; }
.main img { display: block; width: 100%; margin-top: 20px; }
</style>
</head>
<body>
<div class="page-header container">
<h1>小乐的交友网站</h1>
</div>
<div class="nav">
<div class="container">
<a href="#">首页</a><a href="#">相册</a><a href="#">留言</a>
</div>
</div>
<div class="main container">
<div class="box box01">box01</div>
<div class="box box02">box02</div>
<!-- 换成自己的图片,图片撑开高度才能看到滚动粘住的效果 -->
<img src="images/01-xiaole.jpg" alt="">
<img src="images/02-xiaole.jpg" alt="">
</div>
</body>
</html>关键行与易错点
position: sticky必须配合top(或 bottom 等)才生效,只写sticky和不写一样;top: 0表示“滚到距视口顶部 0 的位置就粘住”,写top: 10px就是距顶部还有 10px 时就粘住。- 易错点:
sticky和fixed不是一回事——fixed一上来就固定不动,sticky是到达阈值才固定,页面往回滚时还会回到原来的位置。 - 易错点:
sticky的老版本浏览器需要加私有前缀,移动端兼容性一般(新版 Chrome/Edge/Safari/Firefox 没问题)。 opacity取值 0~1 的小数:1 完全不透明,0 完全透明,数字越大越不透明。- 易错点:
opacity是整个元素半透明(背景、文字、背景图、后代元素全都透),所以.box02的白字变灰了;而rgba()只让背景色半透明,文字依旧清晰。要“背景透、文字不透”,用rgba背景;要“整块都透”,用opacity。
常见错误
1. 阴影写了却不生效,DevTools 里整条声明被划掉
- 现象:
box-shadow: 10px 10px #ccc 5px;完全没有阴影。 - 原因:浏览器按位置顺序解析长度值——第 1、2 个是 X/Y 偏移,第 3 个是模糊值,第 4 个是外延值。颜色插在长度中间会打断解析,导致整条声明非法。
- 修法:颜色只能写在所有长度的最前面或最后面;
inset同理。养成“长度连续书写”的习惯。
2. 换成 border-box 后内容区被压小,以为属性没起作用
- 现象:宽高设成 400×300,检查元素发现内容区只有 354×254,文字挤在一起。
- 原因:
border-box下 width/height 表示的是总宽高,padding 和 border 会从内部扣除,内容区自然变小。这是正常行为,不是 bug。 - 修法:从设计稿量到多大就写多大,不再手工做减法;如果某处确实需要内容区精确等于某个值,那一个元素单独改回
content-box。
3. 给 p / div 设 list-style 加小圆点,没反应
- 现象:
list-style: disc写在段落上,圆点不出现。 - 原因:
list-style只对display: list-item的元素生效,而p的 display 是block。 - 修法:真要实现就补
display: list-item;但更该做的是直接用ul/li——语义正确,样式也省事。这个例子说明的是“display 决定能设什么样式”,不是让你拿 div 假装列表。
4. 想做半透明背景,用了 opacity,结果文字一起变淡
- 现象:卡片背景半透明了,但里面的标题、按钮也全变灰。
- 原因:
opacity作用于元素整体,包括所有后代内容和背景,无法只挑背景。 - 修法:只让背景半透明就用
background: rgba(0,0,0,.5);确实要整块(含子元素)淡化才用opacity,例如遮罩层、禁用态。
5. position: sticky 写了但滚动时元素直接滚走
- 现象:加了
position: sticky,页面一滚导航条照样消失。 - 原因:缺
top(或 bottom/left/right)阈值,没有阈值就不知道该在哪里粘住;另一个常见原因是某个祖先元素有overflow: hidden/auto,粘性被限制在那个滚动容器里。 - 修法:必须补
top: 0;之类的阈值;再逐层检查祖先的overflow,把它去掉或调整结构。还要确认父容器高度足够,否则没有可粘区间。
6. 多阴影只显示了第一条
- 现象:写了 4 组阴影,页面上只有一种颜色。
- 原因:各组之间用了分号,或者漏了逗号,浏览器认为只有一组;也有人用换行当分隔符,换行本身不构成分隔。
- 修法:组与组之间严格用逗号,换行只为可读性。
7. 用百分比写阴影偏移量
- 现象:
box-shadow: 10% 50% #999;声明无效。 - 原因:偏移、模糊、外延只接受长度单位,百分比没有参照基准。
- 修法:一律用 px/em/rem。遇到“试了没用”的属性,先看 DevTools 是否把声明划掉,比反复改数值快得多。
练习
练习 1:卡片悬停立体效果(对应作业 4) 做 3 张卡片横向排列,卡片白底、圆角。默认有一层很淡的阴影;鼠标悬停时卡片上移 3px,阴影变大变柔和。要求:过渡时长 0.3s,且用 border-box 保证三张卡片宽度严格一致、不因边框或内边距错位。 自检:把鼠标移开,卡片应平滑落回原位,不出现跳动。
练习 2:输入框的三态阴影(视频 3 的完整案例) 一个输入框,默认带内阴影(偏移 1px、模糊 2px、半透明黑);:hover 时模糊值加大、颜色加深;:focus 时去掉外轮廓线(outline: none),改成向外的柔和阴影。 自检:三种状态肉眼可区分,但都不能“清晰到像描边”——阴影一旦边缘锐利就不像阴影了。
练习 3:box-sizing 对照实验 同一份结构写两遍:一遍全局 content-box,一遍全局 border-box。卡片都设置宽 300、内边距 20、边框 1px。 要求:在页面上量出两种模式下的实际占位宽度,写出算式,并回答“如果设计稿标注卡片宽 300,哪种模式可以照抄数值”。
练习 4:四边异色多阴影 给一个元素加上四组阴影,分别只朝上、下、左、右偏移 5px,模糊 5px,四组不同颜色。 自检:四条边的颜色互不串色;把任意一组之间的逗号改成换行后,效果不变。
练习 5:粘性导航 + 半透明遮罩 页面包含页头、导航条、若干张图片。导航条滚动到顶部后粘住(top: 0)。再给其中一张图片加一层半透明黑色遮罩,遮罩上的文字必须保持完全不透明。 自检:导航条在往回滚动时能回到原位;遮罩里的文字不随遮罩变淡——如果不是,说明你用错了 opacity。
原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | 关于显示模式 | 06:54 |
| 2 | 调整元素的宽高设置规则 | 07:11 |
| 3 | 元素阴影 | 35:36 |
| 4 | 设置元素的不透明度 | 04:27 |
| 5 | 粘连定位 | 07:33 |
小结
box-sizing: border-box应该成为项目默认值(写进 reset 里),它的价值不是“新特性”,而是让设计稿标注的尺寸可以直接照抄,消灭一整套心算流程。- 阴影好不好看,主要取决于模糊值,偏移量只决定方向。只写偏移不写模糊,出来的是一块生硬的色块;只写模糊不写偏移,才会得到向四周扩散的柔和光晕。
- 阴影参数的解析依赖书写位置,所以“长度必须连续、颜色放任意一端”是唯一安全的写法,不必记特例,只要守住这一条。
opacity和rgba不是二选一,而是作用范围不同:要整块淡化用opacity,要单层颜色透明用rgba。判断标准只有一句——子元素该不该一起变淡。sticky本质是“带阈值的相对定位”:不给阈值它就退化成普通元素,祖先有overflow它就被关进小容器。它比 JS 监听省事,但有明确前提,不适合当万能方案。display之所以能“让任何元素设置任何样式”,是因为可设置的样式取决于 display 的值,而不是标签名——这也是p加不上小圆点的真正原因。- 视觉类属性(阴影、透明度)不要靠肉眼估参数:设计师的稿子可以取色、取偏移量,现成页面可以用 DevTools 直接读
box-shadow的完整值。会读工具,比会背语法更省时间。