主题
BFC(Day16 3/3)
本页对应 Day16_CSS3,共 6 段视频,约 1 小时 45 分。
学习目标
- 能解释移动优先设计方案的核心逻辑,并按“默认最小屏幕样式 + 从小到大使用
min-width媒体查询逐层覆盖”的方式编写响应式页面样式。 - 能实现响应式图片方案一:在 HTML 中放置多张图片,通过 CSS 媒体查询控制不同断点下仅显示对应图片。
- 能实现响应式图片方案二:使用
background-image、background-size、background-position配合媒体查询,在不同断点切换背景图片。 - 能使用
<picture>、<source media>和默认<img>实现响应式图片方案三,并说明其“从上到下匹配第一个满足条件资源”的加载规则。 - 能使用
img的srcset宽度描述符和默认src实现响应式图片方案四,并能对比方案三与方案四的适用场景和兼容性差异。 - 能实现移动优先的响应式导航:小屏显示菜单按钮并通过定位与过渡实现下拉菜单展开收起,大屏隐藏按钮、显示横向导航列表。
知识点
材料核对:你给的转写稿实际讲的是“移动优先、响应式图片、响应式导航”,没有出现 BFC 的定义、触发条件、布局特性或清除浮动等内容。按“不得编造”的要求,我不能把 BFC 知识硬补进去;下面只依据转写稿扩写。转写稿未附图片和完整代码块,因此无法保留图片;代码只保留转写中明确出现的片段,并纠正同音字,如“命with”应为 min-width、“包底”应为 body、“凹to”应为 auto。
移动优先:先写最小屏,再按顺序覆盖
为什么需要:小屏样式是默认样式,可以少写重复的媒体查询条件,避免每个断点都写 min-width 和 max-width。怎么想:把页面默认状态当成最小屏幕,媒体查询只写 min-width,屏幕变大时用后面的规则覆盖前面冲突的规则。怎么做:转写中阈值设为 768、992、1200,默认 .container 宽 100%、高 200px、红色背景;768 以上宽 750px 并居中,992 以上宽 970px,1200 以上宽 1170px。代码片段如下:
css
.container {
width: 100%;
height: 200px;
background: red;
margin: 0 auto;
}
@media (min-width: 768px) {
.container {
width: 750px;
background: green;
}
}
@media (min-width: 992px) {
.container {
width: 970px;
background: blue;
}
}
@media (min-width: 1200px) {
.container {
width: 1170px;
background: yellow;
}
}易错点:媒体查询必须从小到大写,靠后覆盖靠前;min-width 条件一旦满足,后面的更大断点也会继续满足,所以不能乱序。
媒体查询的推导与调试
为什么需要:理解“哪些样式会执行”才能判断最终生效值。怎么想:视口 600px 时,768、992、1200 的条件都不满足,只执行默认样式;视口 800px 时,默认样式和 768 条件都执行,冲突处由后写的 768 规则覆盖;视口 1000px 时,默认、768、992 都执行,冲突处由 992 覆盖。怎么做:用浏览器调试工具拖动视口,观察宽度和背景色变化;转写中还提到把调试工具关掉来模拟 1200px 以上。易错点:不要把 min-width 写成 max-width;不要以为条件只写一个就不能覆盖,覆盖依赖顺序;无冲突的 margin: 0 auto、高度、body 样式仍会保留。
响应式图片:四种方案的选择
为什么需要:同一张图在小屏和大屏上比例不同,硬缩放会失真或留白。怎么想:方案一是写多张 img,用类名控制显示隐藏;方案二是把图作为背景图,媒体查询只换 background-image;方案三是 picture + source + media;方案四是 img 的 srcset 配 w 描述符。怎么做:方案一默认显示小图,640 以上显示中图,1024 以上显示大图;方案二用 background-size: auto 40px、no-repeat、center;方案三从上到下判断,先满足的 source 先执行,所以大图条件写前面;方案四的 640w/1024w/1440w 是图片宽度描述,不是视口阈值,且元素宽度需为 100%。易错点:display: none/block 可切换图片,但 display 不能过渡;picture 的 source 是“先满足先执行”,与 CSS 后者覆盖前者相反;方案四兼容性不如方案三,转写中更推荐方案三。
响应式导航:小屏收起,大屏展开
为什么需要:小屏空间不足,导航要收起;大屏空间足够,导航直接展开。怎么想:小屏只显示菜单按钮,下拉列表绝对定位并默认 height: 0; overflow: hidden;点击态用 :active 临时模拟展开,因为转写时还没学 JS。怎么做:按钮内放三个 span 做横线,设置宽高、背景、间距;下拉列表定位到 header 下方,top 要加上头部高度、内边距和边框的总和;展开时把高度改为 160px,并加 transition: 600ms。640 以上隐藏按钮,取消列表绝对定位,列表宽 100%,li 用 display: flex 横排。易错点:button 默认是 border-box,加边框内边距不会撑大总宽;display 不能过渡,所以用高度过渡;绝对定位元素的包含块要设置相对定位;:active 只是临时方案,松手就收起,正式交互应等 JS 事件。
易错点汇总
为什么需要:这些点直接决定页面是否“看起来对”。怎么想:先检查盒模型,再检查定位包含块,最后检查媒体查询顺序。怎么做:给需要精确宽度的元素加 box-sizing: border-box;input 的 80% 加内边距会变大,必须改盒模型;button 自带 border-box,不要再误判;下拉菜单的 top 不是 40px,而是头部总高度;position: static 可覆盖绝对定位。易错点:同音字要还原为属性名,如“命with”是 min-width、“第次play”是 display、“闹”是 none、“凹to”是 auto;不要把“媒体查询能触发过渡”当成用户问题,用户打开页面时视口固定,不会像开发者那样来回拖动。
再次说明:以上是转写稿实际内容的教程化整理;若你要的是 BFC,请补充含 BFC 笔记正文、图片和代码的材料,否则不能编造。
移动优先:先写最小屏,再从小到大覆盖
为什么需要:响应式页面要在不同视口下呈现不同形态。若从大屏往小屏写,媒体查询条件容易写成 max-width,断点顺序和覆盖关系更绕。移动优先把“最小屏幕”作为默认样式,后面只做增强。
怎么想:媒体查询外写最小屏样式,以及所有屏幕都共用的样式;媒体查询统一用 min-width,按 768、992、1200 从小到大写。条件只写下限,不写上限,靠“后写覆盖前写”完成断点切换。
怎么做:
css
body { margin: 0; }
.container {
width: 100%;
height: 200px;
background: red;
}
@media (min-width: 768px) {
.container { width: 750px; margin: 0 auto; background: green; }
}
@media (min-width: 992px) {
.container { width: 970px; background: blue; }
}
@media (min-width: 1200px) {
.container { width: 1170px; background: yellow; }
}调试推导:视口 600 时,只有默认样式生效;视口 800 时,默认样式和 min-width:768px 都满足,冲突属性由后者覆盖;视口 1000 时,768 和 992 都满足,最终 992 的宽度和背景生效;视口 1500 时,1200 的规则最后生效。左右 margin:auto 没有冲突,所以仍然保留。
易错点:断点顺序不能乱,必须从小到大;min-width 只写一个条件即可,不必再补 max-width;不要以为后写规则权重更高,它只是同权重下靠顺序覆盖。
响应式导航:默认收起,640 以上展开
为什么需要:小屏空间窄,导航要收起;大屏空间足够,导航应直接展开。转写稿用按钮模拟展开收起,但强调真实项目应使用 JS 点击事件。
怎么想:默认让下拉菜单高度为 0、溢出隐藏;按钮按下时用 :active 临时模拟展开。大屏时隐藏按钮,让下拉菜单取消绝对定位、恢复文档流,并横向排列。
怎么做:
css
.nav-list {
position: absolute;
top: 68px;
width: 100%;
height: 0;
overflow: hidden;
transition: height .6s;
}
.menu-btn:active + .nav-list { height: 160px; }
@media (min-width: 640px) {
.page-nav { width: 25%; }
.menu-btn { display: none; }
.nav-list {
position: static;
height: 40px;
display: flex;
}
.nav-list li { width: 100%; }
}易错点:display:none/block 不能过渡,所以用高度和 overflow:hidden;按钮和下拉菜单是相邻兄弟,必须用 +;:active 只是临时凑合,松手就收起。
响应式图片方案一:多张图显示隐藏
为什么需要:媒体查询只能改 CSS,不能直接改 img 的 src。方案一把多张图都写进 HTML,用 CSS 控制显示哪一张。
怎么做:
html
<img class="small-logo" src="logo-S.png" alt="小屏Logo">
<img class="mid-logo" src="logo-M.png" alt="中屏Logo">
<img class="large-logo" src="logo-L.png" alt="大屏Logo">css
.small-logo { display: block; }
.mid-logo, .large-logo { display: none; }
@media (min-width: 640px) {
.small-logo { display: none; }
.mid-logo { display: block; }
}
@media (min-width: 1024px) {
.mid-logo { display: none; }
.large-logo { display: block; }
}易错点:三张图同时存在,必须保证同一时刻只显示一张;代码量偏多。
响应式图片方案二:背景图换图
为什么需要:背景图属于 CSS,媒体查询换 background-image 更直接。
怎么做:
css
.logo {
background-image: url("logo-S.png");
background-size: auto 40px;
background-repeat: no-repeat;
background-position: center;
}
@media (min-width: 640px) {
.logo { background-image: url("logo-M.png"); }
}
@media (min-width: 1024px) {
.logo { background-image: url("logo-L.png"); }
}易错点:背景图不设 background-size 可能只显示一部分;auto 40px 表示高度 40、宽度按比例自动。
响应式图片方案三:picture + source
为什么需要:希望 HTML 层面按条件选择图片。picture 配合 source media 和 srcset 可实现。
怎么做:
html
<picture>
<source media="(min-width: 1024px)" srcset="banner-L.jpg">
<source media="(min-width: 640px)" srcset="banner-M.jpg">
<img src="banner-S.jpg" alt="响应式横幅">
</picture>css
.banner img { width: 100%; }怎么想:source 从上到下判断,第一个满足条件的生效,后面的不再看。因此要反着写:先写大屏条件,再写中屏,最后 img 作为默认小图。这与移动优先 CSS 的“后覆盖前”相反。
易错点:media 是 HTML 属性,不带 @;srcset 在编辑器里可能没有提示;img 仍建议设 width:100%,避免小图在大容器中溢出。
响应式图片方案四:img 的 srcset
为什么需要:方案四用 srcset 让浏览器根据图片宽度和元素宽度选择资源,写法更短。
怎么做:
html
<img
src="banner-L.jpg"
srcset="banner-S.jpg 640w,
banner-M.jpg 1024w,
banner-L.jpg 1440w"
alt="响应式横幅">易错点:640w/1024w/1440w 是图片文件宽度,不是视口阈值;元素宽度通常要设为 100%;调试时来回拖动可能不刷新,需要刷新页面;兼容性和可读性不如方案三,转写稿更推荐方案三。
课堂画面






代码示例
常见错误
现象:大屏样式被小屏样式覆盖,断点表现错乱。→ 原因:移动优先的媒体查询没有按
min-width从小到大排列,后写覆盖前写的规则失效。→ 修法:默认样式放媒体查询外,断点按 640/768→992→1024/1200 递增书写,冲突属性靠后写覆盖。现象:写了媒体查询但
img的图片不切换。→ 原因:CSS 媒体查询不能修改 HTML 的src属性。→ 修法:改用picture + source、srcset/sizes,或把图片作为背景图用background-image切换。现象:
picture/source中小图先命中,大图始终不加载。→ 原因:source从上到下判断,首个满足条件即停止,不是 CSS 的后写覆盖前写。→ 修法:按大条件到小条件书写,最后用img兜底。现象:背景图切换后只显示局部、平铺或不居中。→ 原因:只换了
background-image,没有处理原图尺寸和定位。→ 修法:同时设置background-size、background-repeat:no-repeat、background-position:center。现象:下拉菜单用
display:none/block切换时没有过渡动画。→ 原因:display不是可过渡属性。→ 修法:改用height:0 + overflow:hidden到目标高度,并配合transition。现象:大屏下导航仍脱离文档流或位置错误。→ 原因:小屏的
position:absolute没有被覆盖。→ 修法:在对应媒体查询中写position:static,再配合flex做横向排列。现象:搜索框
input 80% + button 20%后按钮换行。→ 原因:content-box下宽度不含内边距/边框,且行内块之间存在空隙。→ 修法:给输入框加box-sizing:border-box,父级改display:flex消除空隙。
练习
用移动优先重写一个容器:默认
<768px宽100%、红色;≥768px宽750px、绿色、居中;≥992px宽970px、蓝色、居中;≥1200px宽1170px、黄色、居中。写完后说明为什么断点顺序不能乱。给 banner 做三档响应式图片:
<640px小图,640–1023px中图,≥1024px大图。分别用picture/source和background-image两种方案实现,并比较代码量与兼容性。实现响应式导航关键部分:
<640px显示菜单按钮,按住按钮展开下拉;≥640px隐藏按钮,导航横向显示。写出关键选择器,并标出需要覆盖的定位属性。排查并修复:搜索区
input宽80%、按钮宽20%,实际却换行。给出两种修法,并说明各自原因。制定验收清单:在 375、640、768、992、1200、1440 六个宽度下,列出应检查的 5 项内容,至少包含断点、图片、导航、溢出、过渡。
原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | 移动优先设计方案 | 16:37 |
| 2 | 响应式布局案例-响应式图片方案一 | 19:10 |
| 3 | 响应式布局案例-响应式图片方案二 | 04:36 |
| 4 | 响应式布局案例-响应式导航 | 47:23 |
| 5 | 响应式布局案例-响应式图片方案三 | 10:01 |
| 6 | 响应式布局案例-响应式图片方案四 | 07:45 |
小结
- 移动优先的关键是“默认样式 + 递增
min-width+ 顺序覆盖”,不是简单先写手机样式。 - 断点数量应由设计稿和内容决定,课程中的 640/1024、768/992/1200 只是演示配置。
- 响应式图片优先掌握
picture/source,但要牢记它按首个匹配停止,书写方向与 CSS 覆盖相反。 - 背景图方案适合装饰性图片,必须同时处理
size、position、repeat。 - 响应式导航的难点在状态切换与定位覆盖,不只是隐藏按钮。
display不适合做展开动画,需要换成可过渡的高度或位移方案。- 开发者工具拖动视口会触发媒体查询过渡,真实用户通常固定视口,不必为演示现象过度修补。
- 正式项目应使用 JS 管理菜单展开状态,
:hover/:active只适合临时演示。