CSS Handbook · 布局

第六章 / 6.6 响应式布局实战

第六章 · 6.6 节

响应式布局实战


本节把前面四节的知识——盒模型、Flexbox、Grid、媒体查询——组合成一个真实可用的页面骨架:从流式字号、自适应卡片网格,到小屏下的导航折叠,逐步搭建一个能在手机到桌面显示器之间平滑过渡的页面。

流式字号:clamp() 三值函数

clamp(最小值, 首选值, 最大值) 让字号、间距可以随视口宽度连续变化,替代"在断点处生硬跳变"的做法。首选值通常写成 vw 单位,使其随视口线性缩放,同时用最小/最大值兜底,避免在极端尺寸下失控。

h1 {
  font-size: clamp(1.75rem, 1.2rem + 2.5vw, 3rem);
}
.container {
  padding-inline: clamp(16px, 5vw, 64px);
}
为什么优于媒体查询媒体查询下字号在断点处会有肉眼可见的"跳变";clamp() 让变化连续平滑,且只需一行代码替代原本三四条媒体查询规则。

页面骨架:Grid 搭架子

先用 Grid 定义整站通用的页面级骨架——侧边栏、头部、主内容、页脚,移动端再用媒体查询把侧边栏"折叠"进主列:

.page {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-areas:
    "sidebar header"
    "sidebar main";
  min-height: 100vh;
}

@media (max-width: 768px) {
  .page {
    grid-template-columns: 1fr;
    grid-template-areas:
      "header"
      "main";
  }
  .sidebar { display: none; } /* 交由折叠菜单代替 */
}

卡片列表:auto-fit 自适应

回顾 4.3 节的 auto-fit + minmax() 组合——它本身就是响应式的,甚至不需要额外写媒体查询就能应对绝大多数宽度变化:

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: clamp(12px, 2vw, 24px);
}
效果预览:缩小浏览器窗口观察列数变化(此演示区域较窄,已呈现单列/双列状态)
卡片 A
卡片 B
卡片 C

桌面端用 Flexbox 横向平铺导航项,移动端切换为纵向折叠菜单——排布方式的切换只需要修改 flex-direction 一个属性:

.nav-list {
  display: flex;
  gap: 24px;
}

@media (max-width: 640px) {
  .nav-list {
    flex-direction: column;
    gap: 0;
    display: none; /* 默认收起,由汉堡按钮控制展开 */
  }
  .nav-list.open { display: flex; }
}

完整示例整合

把以上几段代码组合起来,就是一个具备基本响应能力的页面骨架雏形:流式字号负责文字层面的连续缩放,Grid 负责页面级骨架的断点重排,auto-fit 网格负责内容区卡片的自适应列数,Flexbox 负责导航栏这类一维组件在断点前后的方向切换。四者分工明确,各自解决自己最擅长的那一层问题,这正是现代响应式设计的核心思路——不是"一个大而全的方案",而是"在合适的层级选用合适的工具"。

上线前自查清单

  • 是否在 <head> 中声明了 <meta name="viewport" content="width=device-width, initial-scale=1">?缺少它,移动端媒体查询将完全失效。
  • 断点是否由内容决定,而非照搬某个设备型号的分辨率?
  • 触屏设备上的可点击区域是否足够大(建议不小于 44×44px)?
  • 是否用 prefers-reduced-motion 尊重了用户的动效偏好(见 3.2 节)?
  • 深色模式下的对比度、图片是否也经过检查(见 3.2 节)?
  • 横向滚动条是否只出现在刻意设计的容器(如代码块、表格)内,而不是意外出现在整个页面?

Chapter 6 · Section 6.6

Responsive Layout in Practice


This section combines the knowledge from the previous four sections — the box model, Flexbox, Grid, and media queries — into a real, usable page skeleton: from fluid type and an adaptive card grid to a collapsing navigation on small screens, gradually building a page that transitions smoothly from phones to desktop monitors.

Fluid Type: The clamp() Three-Value Function

clamp(minimum, preferred, maximum) lets font sizes and spacing change continuously with the viewport width, replacing the practice of hard jumps at breakpoints. The preferred value is usually written in vw units so it scales linearly with the viewport, while the minimum and maximum values act as guardrails so it never gets out of hand at extreme sizes.

h1 {
  font-size: clamp(1.75rem, 1.2rem + 2.5vw, 3rem);
}
.container {
  padding-inline: clamp(16px, 5vw, 64px);
}
Why better than media queriesWith media queries, font sizes visibly "jump" at breakpoints; clamp() makes the change continuous and smooth, and a single line of code replaces what would otherwise be three or four media query rules.

Page Skeleton: Grid as the Framework

First use Grid to define a site-wide page-level skeleton — sidebar, header, main content, footer — then on mobile use a media query to "collapse" the sidebar into the main column:

.page {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-areas:
    "sidebar header"
    "sidebar main";
  min-height: 100vh;
}

@media (max-width: 768px) {
  .page {
    grid-template-columns: 1fr;
    grid-template-areas:
      "header"
      "main";
  }
  .sidebar { display: none; } /* replaced by the collapsible menu */
}

Card Lists: auto-fit Adaptive Columns

Recall the auto-fit + minmax() combination from Section 4.3 — it is inherently responsive and handles most width changes without even needing extra media queries:

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: clamp(12px, 2vw, 24px);
}
Preview: shrink the browser window to watch the column count change (this demo area is narrow and already shows a one/two-column state)
Card A
Card B
Card C

Collapsing Navigation: Flexbox + Media Queries

On desktop, Flexbox lays out the navigation items horizontally in a row; on mobile, it switches to a vertical collapsed menu — changing the layout requires modifying only one property, flex-direction:

.nav-list {
  display: flex;
  gap: 24px;
}

@media (max-width: 640px) {
  .nav-list {
    flex-direction: column;
    gap: 0;
    display: none; /* hidden by default, toggled open by the hamburger button */
  }
  .nav-list.open { display: flex; }
}

Putting It All Together

Combining the snippets above yields a page skeleton with basic responsive capability: fluid type handles the continuous scaling of text, Grid handles the breakpoint re-layout of the page-level skeleton, the auto-fit grid handles the adaptive column count of the cards in the content area, and Flexbox handles the direction switch of one-dimensional components such as navigation bars before and after breakpoints. Each of the four has a clear role, solving the layer of the problem it is best at — this is the core idea of modern responsive design: not "one big all-encompassing solution", but "choosing the right tool at the right level".

Pre-launch Checklist

  • Did you declare <meta name="viewport" content="width=device-width, initial-scale=1"> in the <head>? Without it, media queries on mobile will not work at all.
  • Are the breakpoints determined by the content, rather than copied from a specific device model's resolution?
  • Are the clickable areas on touch devices large enough (recommended at least 44×44px)?
  • Did you use prefers-reduced-motion to respect the user's motion preferences (see Section 3.2)?
  • Has contrast and images in dark mode been checked too (see Section 3.2)?
  • Do horizontal scrollbars appear only inside deliberately designed containers (such as code blocks or tables), rather than unexpectedly on the whole page?