响应式适配实践
场景
同一套代码需要在 PC、平板、手机上都有良好体验,如何设计和实施响应式方案?
方案设计
1. 断点策略
responsive-breakpoints.css
/* 移动优先(推荐) */
/* 基础样式 → 手机端 */
.container { padding: 16px; }
/* 平板 */
@media (min-width: 768px) {
.container { padding: 24px; max-width: 720px; margin: 0 auto; }
}
/* PC */
@media (min-width: 1024px) {
.container { padding: 32px; max-width: 960px; }
}
/* 大屏 */
@media (min-width: 1280px) {
.container { max-width: 1200px; }
}
2. 容器查询
container-query.css
.card-wrapper {
container-type: inline-size;
}
/* 根据容器宽度而非视口宽度响应 */
@container (min-width: 400px) {
.card { display: flex; gap: 16px; }
}
@container (max-width: 399px) {
.card { display: block; }
}
3. Fluid Typography(流体字号)
fluid-text.css
/* clamp(最小值, 首选值, 最大值) */
h1 {
font-size: clamp(1.5rem, 4vw, 3rem);
}
body {
font-size: clamp(14px, 1vw + 12px, 18px);
}
4. 响应式图片
responsive-image.html
<picture>
<source
media="(min-width: 1024px)"
srcset="/img/hero-desktop.webp"
type="image/webp"
/>
<source
media="(min-width: 768px)"
srcset="/img/hero-tablet.webp"
type="image/webp"
/>
<img
src="/img/hero-mobile.jpg"
srcset="/img/hero-mobile.webp"
alt="Hero"
loading="lazy"
/>
</picture>
5. JS 响应式 Hook
useBreakpoint.ts
import { useState, useEffect } from 'react';
type Breakpoint = 'mobile' | 'tablet' | 'desktop';
function useBreakpoint(): Breakpoint {
const [bp, setBp] = useState<Breakpoint>('mobile');
useEffect(() => {
const queries = {
desktop: window.matchMedia('(min-width: 1024px)'),
tablet: window.matchMedia('(min-width: 768px)'),
};
function update() {
if (queries.desktop.matches) setBp('desktop');
else if (queries.tablet.matches) setBp('tablet');
else setBp('mobile');
}
update();
Object.values(queries).forEach((mq) => mq.addEventListener('change', update));
return () =>
Object.values(queries).forEach((mq) => mq.removeEventListener('change', update));
}, []);
return bp;
}
方案对比
| 方案 | 适用场景 | 优缺点 |
|---|---|---|
| 媒体查询 | 通用 | 成熟稳定、基于视口 |
| 容器查询 | 组件库 | 更精准、兼容性较新 |
| clamp() | 字号/间距 | 平滑过渡、无断点跳变 |
| rem 适配 | 移动端为主 | 需设 root font-size |
| CSS Grid auto-fit | 网格布局 | 自适应列数 |
常见面试问题
Q1: 移动优先(Mobile First)和桌面优先的区别?
答案:
- 移动优先:基础样式写手机端,用
min-width逐步增强到大屏。推荐,因为移动代码更简单,大屏渐进增强 - 桌面优先:基础样式写 PC 端,用
max-width逐步适配小屏。适合已有 PC 项目后补移动端
Q2: rem、vw、px 各在什么场景下使用?
答案:
| 单位 | 适用场景 | 说明 |
|---|---|---|
px | 边框、小图标 | 固定像素,不需缩放 |
rem | 字号、间距 | 相对根字号,整体缩放 |
vw/vh | 全屏布局、流体字号 | 相对视口,配合 clamp 使用 |
em | 组件内部间距 | 相对父级字号 |
% | 容器宽度 | 相对父级尺寸 |