CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
HTML 与 CSS 基础/课时/响应式设计
RawBlame
课时目录12 节

HTML 与 CSS 基础

  1. 01网页如何工作
  2. 02HTML 文档结构
  3. 03文本、链接与媒体
  4. 04HTML 表单
  5. 05语义化与可访问性
  6. 06CSS 选择器与层叠
  7. 07盒模型与布局流
  8. 08Flexbox 布局
  9. 09Grid 布局
  10. 10响应式设计
  11. 11综合练习:静态课程页
  12. 12框架与下一步

响应式设计

媒体查询、移动优先、viewport。

30 分钟

响应式设计与现代 CSS

这一课你将能做到

  1. 使用媒体查询(Media Queries)和容器查询(Container Queries)为不同视口和组件状态编写自适应样式
  2. 使用 clamp()、min()、max() 实现流体排版与弹性间距,摆脱「为每个断点写固定值」的繁琐
  3. 结合 prefers-color-scheme 和 CSS 自定义属性,实现跟随系统主题的自动深色模式

为什么要学

用户访问 CodeForge 的设备可能是 27 寸 4K 显示器、13 寸笔记本、iPad 平板或 6 寸手机。响应式设计不是「让网页在手机上能看」,而是「让同一份代码在任何尺寸下都提供最优体验」。媒体查询是传统答案,但它基于视口宽度,无法解决「侧边栏内的组件在宽窄两种状态下的表现」这类组件级问题。

现代 CSS 提供了更精细的工具:clamp() 让字体大小在最小值和最大值之间平滑过渡;容器查询让组件根据所在容器宽度而非视口宽度调整样式;prefers-color-scheme 自动适配系统明暗主题。掌握这些技术,你能写出更简洁、更健壮的样式代码。

先建立图像

响应式设计的三个层次:

1. 流体排版:字号和间距随视口平滑缩放(clamp)
   font-size: clamp(0.875rem, 0.5vw + 0.75rem, 1.125rem);

2. 容器查询:组件根据所在容器宽度自适应(@container)
   @container (min-width: 400px) { .card { flex-direction: row; } }

3. 媒体查询:页面根据视口宽度切换布局(@media)
   @media (min-width: 768px) { .layout { grid-template-columns: 250px 1fr; } }

现代最佳实践:优先使用流体排版和容器查询,媒体查询处理宏观布局切换。

跟着做

步骤 1:流体排版与弹性间距

创建 responsive.html:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>响应式设计练习</title>
  <style>
    :root { --primary: #2563eb; --surface: #fff; --text: #0f172a; --text-muted: #64748b; }
    * { box-sizing: border-box; margin: 0; padding: 0; }
    body { font-family: system-ui, sans-serif; background: #f1f5f9; color: var(--text); line-height: 1.6; }
    .hero-title { font-size: clamp(1.75rem, 1.2rem + 2vw, 2.5rem); line-height: 1.2; }
    .container { padding-inline: clamp(1rem, 0.5rem + 2vw, 3rem); max-width: 1200px; margin-inline: auto; }
    .hero { text-align: center; padding-block: clamp(3rem, 2rem + 4vw, 6rem); background: linear-gradient(135deg, #eff6ff, #f5f3ff); }
    .hero p { font-size: clamp(1rem, 0.9rem + 0.5vw, 1.25rem); color: var(--text-muted); max-width: 560px; margin: 1rem auto 0; }
  </style>
</head>
<body>
  <section class="hero">
    <div class="container">
      <h1 class="hero-title">响应式前端开发</h1>
      <p>一套代码,适配所有设备。从手机到桌面,从窄屏到宽屏,体验始终如一。</p>
    </div>
  </section>
</body>
</html>

保存后打开,拖动浏览器窗口宽度,观察字号和内边距如何平滑变化。clamp(min, preferred, max) 的含义:最终值不低于 min,不高于 max,中间按 preferred(通常含 )计算。

vw

步骤 2:媒体查询实现布局切换

.course-grid { display: grid; gap: 1.5rem; grid-template-columns: 1fr; }
@media (min-width: 640px) { .course-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .course-grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1440px) { .course-grid { grid-template-columns: repeat(4, 1fr); } }

断点选择依据:640px、1024px、1440px 是常用断点。min-width 策略是「移动优先」——基础样式针对小屏,断点逐步增强。

步骤 3:容器查询——组件级响应式

.course-list-wrapper { container-type: inline-size; container-name: courseList; }
.course-card { display: flex; flex-direction: column; gap: 1rem; }
@container courseList (min-width: 500px) {
  .course-card { flex-direction: row; align-items: center; }
  .course-card .cover { width: 160px; height: 100px; flex-shrink: 0; }
}

先给容器声明 container-type: inline-size,再用 @container 根据容器宽度写样式。同一个组件放在窄侧边栏和宽主内容区,可以有不同的布局,而不需要知道视口宽度。

步骤 4:自动深色模式

:root { --bg: #f1f5f9; --surface: #fff; --text: #0f172a; }
@media (prefers-color-scheme: dark) {
  :root { --bg: #0f172a; --surface: #1e293b; --text: #f8fafc; }
}
body { background: var(--bg); color: var(--text); }

在操作系统中切换明暗主题,页面自动跟随。生产环境中还应提供手动切换按钮,通过给 <html> 加 data-theme="dark" 并覆盖变量实现。

步骤 5:实战——响应式导航栏

.site-nav { display: flex; align-items: center; justify-content: space-between; padding: 0.75rem clamp(1rem, 0.5rem + 2vw, 2rem); }
.nav-links { display: none; gap: 1.5rem; list-style: none; }
.menu-btn { background: none; border: none; font-size: 1.5rem; cursor: pointer; }
@media (min-width: 768px) { .nav-links { display: flex; } .menu-btn { display: none; } }

窄屏只显示汉堡菜单按钮,宽屏显示完整导航链接。这是响应式导航的标准模式,配合 JavaScript 实现菜单展开/折叠。

讲清楚要点

  1. 移动优先(Mobile First):先写小屏样式,再用 min-width 媒体查询逐步增强。这样小屏设备不会下载和执行不必要的样式,且代码逻辑更自然——从简单到复杂。

  2. clamp() 的数学原理:clamp(MIN, VAL, MAX) = max(MIN, min(VAL, MAX))。VAL 通常是线性函数(如 0.5rem + 2vw),表示在某一视口宽度下期望的计算值。当视口很小时,VAL 可能小于 MIN,最终取 MIN;当视口很大时,VAL 可能超过 MAX,最终取 MAX。

  3. 容器查询是媒体查询的补充而非替代:媒体查询适合页面级布局切换(如侧边栏显隐),容器查询适合组件级自适应(如卡片横竖切换)。两者结合使用,可以实现「组件不关心自己在哪,只关心容器有多宽」的封装目标。

  4. 断点选择的依据:断点不应基于设备型号(如「iPhone 尺寸」「iPad 尺寸」),而应基于内容何时开始「崩坏」。如果你发现课程卡片在 620px 时变得太窄,那个就是断点。常用参考值:640px(sm)、768px(md)、1024px(lg)、1280px(xl)。

  5. prefers-color-scheme 的优先级:它匹配操作系统级别的主题设置。如果用户浏览器或系统设为深色模式,网站自动切换。这比手动切换更无感,但应同时提供手动切换能力(因为用户可能只想让某个网站是深色,而不是整个系统)。

  6. min()、max() 的用法:width: min(100%, 600px) 表示「宽度最大 600px,但在窄屏下不超过容器 100%」。padding: max(1rem, 3vw) 表示「内边距至少 1rem,宽屏下更大」。这两个函数与 clamp() 共同构成了现代流体布局的数学工具箱。

你可能会懵的地方

  • 「@media (min-width: 768px) 和 @media (max-width: 767px) 有什么区别?」 min-width: 768px 表示「视口宽度 ≥ 768px 时生效」,是移动优先的增强写法。max-width: 767px 表示「视口宽度 ≤ 767px 时生效」,是桌面优先的降级写法。现代开发推荐移动优先。

  • 「为什么容器查询需要 container-type: inline-size?不写会怎样?」 不写则容器查询无法获取容器的内联尺寸(宽度)。container-type: inline-size 显式声明该元素是一个查询容器,其内部的后代元素可以使用 @container 根据它的宽度查询。目前支持 inline-size、size(高度和宽度)和 normal。

  • 「clamp() 里的 vw 是什么意思?为什么不用 %?」 vw 是 viewport width 的 1%,与视口宽度线性相关。% 相对的是父元素宽度,在嵌套结构中容易受到多层影响。vw 更适合全局流体排版,因为它直接关联最终显示设备的物理尺寸。

  • 「媒体查询和容器查询的浏览器支持如何?」 媒体查询所有现代浏览器完全支持。容器查询自 2022 年起在 Chrome 105+、Firefox 110+、Safari 16+ 全面支持,覆盖率已超过 90%。对于旧浏览器,容器查询不会生效,布局会回退到默认样式(这正是移动优先策略的优势)。

  • 「如何测试不同设备的显示效果?」 Chrome/Edge 开发者工具的「设备模拟」(Ctrl+Shift+M)可以切换常见设备尺寸和 DPR。但真正可靠的测试是在真实设备上访问(可通过局域网 IP + 手机浏览器)。同时检查 min-width、max-width、orientation(横竖屏)等多种条件组合。

错法对照

错法问题正解
为每种手机型号写单独断点断点爆炸,无法覆盖所有设备按内容崩坏点设断点,或用流体排版减少断点
用 px 写固定字号大屏字太小,小屏字太大用 clamp() 实现流体排版
容器查询不写 container-type查询不生效容器必须声明 container-type: inline-size
只写 @media (max-width)桌面优先,小屏加载冗余样式移动优先,基础样式针对小屏,min-width 增强
忽略 prefers-reduced-motion动画对前庭障碍用户造成不适提供 prefers-reduced-motion 媒体查询回退
深色模式只改背景色不改文字色对比度不足,阅读困难使用 CSS 变量系统,深色模式下同时改背景、文字、边框色

卡点急救

  1. 媒体查询不生效:检查是否在 <head> 中写了 <meta name="viewport" content="width=device-width, initial-scale=1.0">。没有这行,移动端浏览器会模拟 980px 宽度,所有基于视口的媒体查询都会失效。

  2. 容器查询不生效:确认容器声明了 container-type: inline-size;确认查询语法正确 @container (min-width: 400px);确认浏览器支持容器查询(Chrome 105+、Safari 16+)。

  3. clamp() 计算出的值不符合预期:在开发者工具中选中元素 → Computed → 找到对应属性,看实际计算值。如果 preferred 值的系数写反了(如 2rem - 1vw),视口越大值越小,可能是逻辑错误。

面试常问

  • 「移动优先和桌面优先有什么区别?为什么推荐移动优先?」 移动优先是先写小屏基础样式,再用 min-width 媒体查询为大屏增强。桌面优先是先写大屏样式,再用 max-width 为小屏降级。推荐移动优先的原因:一、代码更简洁,天然避免为小屏覆盖大量大屏样式;二、性能更好,小屏设备不执行不必要的增强样式;三、符合市场趋势,移动流量占比已超过桌面。

  • 「容器查询与媒体查询的区别?什么时候用容器查询?」 媒体查询基于整个视口的尺寸,适合页面级布局切换(如导航栏显隐、侧边栏折叠)。容器查询基于组件所在容器的尺寸,适合组件级自适应(如卡片在窄容器内垂直排列、在宽容器内水平排列)。当同一个组件可能在页面不同区域以不同宽度呈现时,容器查询更精确。

  • 「如何实现字体大小在不同屏幕上的平滑缩放?」 使用 CSS clamp() 函数,如 font-size: clamp(1rem, 0.5rem + 1vw, 1.25rem)。它定义了最小值、首选值(通常含 vw 单位)和最大值,字体在窄屏不低于最小值、在宽屏不高于最大值,中间按视口比例线性缩放。这比为每个断点写固定值更简洁、更流畅。

自测三问

  1. clamp(1rem, 0.5rem + 2vw, 2rem) 在视口宽度为 0 时、非常大时、以及 0.5rem + 2vw = 1.5rem 时,最终值分别是多少?
  2. 容器查询需要满足哪两个条件才能生效?
  3. 为什么响应式设计中推荐使用 @media (min-width) 而非 @media (max-width)?

小结一句话

响应式设计的现代范式是「流体排版打底、容器查询管组件、媒体查询管页面」;clamp() 让尺寸在边界之间优雅流动,容器查询让组件真正独立于视口,而深色模式适配已成为专业产品的标准配置。

延伸

  • MDN:媒体查询
  • MDN:容器查询
  • MDN:clamp()
  • MDN:prefers-color-scheme
  • 下一课:HTML/CSS 综合实战——从零构建一个课程详情页。
加载本节练习…
← 上一课Grid 布局下一课 →综合练习:静态课程页