CSS 响应式设计
响应式设计是一种让网页能够自适应不同屏幕尺寸的设计方法。从手机到平板到桌面显示器,用户可能通过各种设备访问你的网站。响应式设计确保网站在任何设备上都能提供良好的用户体验,而不需要为每种设备单独开发版本。
视口设置
响应式设计的第一步是正确设置视口。在 HTML 文档的 <head> 中添加:
<meta name="viewport" content="width=device-width, initial-scale=1.0">
这个元标签告诉移动浏览器:
width=device-width:视口宽度等于设备宽度initial-scale=1.0:初始缩放比例为 100%
没有这个设置,移动浏览器可能会以桌面版宽度(如 980px)渲染页面,然后缩放显示,导致文字太小、需要手动放大才能阅读。
禁止用户缩放(不推荐):
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
这会阻止用户缩放页面,对视力不好的用户不友好,应该避免使用。
媒体查询
媒体查询是响应式设计的核心技术,它允许根据设备特性(如屏幕宽度)应用不同的 CSS 规则。
基本语法
@media (条件) {
/* 当条件满足时应用的样式 */
}
宽度查询
最常见的媒体查询是基于视口宽度:
/* 视口宽度大于等于 768px */
@media (min-width: 768px) {
.container {
max-width: 750px;
}
}
/* 视口宽度小于等于 576px */
@media (max-width: 576px) {
.container {
padding: 10px;
}
}
/* 宽度范围 */
@media (min-width: 768px) and (max-width: 1024px) {
.container {
max-width: 960px;
}
}
断点选择
断点是媒体查询中的宽度阈值。常用的断点参考:
/* 手机(纵向) */
@media (max-width: 575px) { }
/* 手机(横向)和小平板 */
@media (min-width: 576px) and (max-width: 767px) { }
/* 平板 */
@media (min-width: 768px) and (max-width: 991px) { }
/* 小桌面 */
@media (min-width: 992px) and (max-width: 1199px) { }
/* 大桌面 */
@media (min-width: 1200px) { }
断点应该基于内容需求而非特定设备,因为设备尺寸多种多样。
移动优先 vs 桌面优先
移动优先:先编写移动端样式,再用媒体查询扩展到大屏:
/* 默认样式:移动端 */
.container {
padding: 15px;
}
/* 平板及以上 */
@media (min-width: 768px) {
.container {
padding: 30px;
max-width: 750px;
}
}
/* 桌面 */
@media (min-width: 1024px) {
.container {
max-width: 960px;
}
}
桌面优先:先编写桌面端样式,再用媒体查询适配小屏:
/* 默认样式:桌面 */
.container {
padding: 30px;
max-width: 1200px;
}
/* 平板 */
@media (max-width: 1023px) {
.container {
max-width: 960px;
}
}
/* 手机 */
@media (max-width: 767px) {
.container {
padding: 15px;
max-width: none;
}
}
推荐使用移动优先策略,因为:
- 代码更简洁,大屏样式覆盖小屏样式
- 更好地关注核心内容
- 性能更好,移动设备下载的 CSS 更少
其他媒体特性
/* 屏幕方向 */
@media (orientation: portrait) { } /* 纵向 */
@media (orientation: landscape) { } /* 横向 */
/* 分辨率 */
@media (min-resolution: 2dppx) { } /* 高清屏(Retina) */
/* 屏幕类型 */
@media screen { } /* 屏幕 */
@media print { } /* 打印 */
@media speech { } /* 语音合成 */
/* 悬停能力 */
@media (hover: hover) { } /* 支持悬停(鼠标) */
@media (hover: none) { } /* 不支持悬停(触摸) */
/* 指针精度 */
@media (pointer: fine) { } /* 精确指针(鼠标) */
@media (pointer: coarse) { } /* 粗糙指针(手指) */
/* 组合条件 */
@media screen and (min-width: 768px) and (orientation: landscape) { }
@media (min-width: 768px), (orientation: landscape) { } /* 或 */
在 CSS 文件中引入
/* 方式一:直接写在样式表中 */
.element { /* 默认样式 */ }
@media (min-width: 768px) {
.element { /* 大屏样式 */ }
}
/* 方式二:使用 @import */
@import url('mobile.css') screen and (max-width: 767px);
@import url('desktop.css') screen and (min-width: 768px);
在 HTML 中引入
<link rel="stylesheet" href="mobile.css" media="(max-width: 767px)">
<link rel="stylesheet" href="desktop.css" media="(min-width: 768px)">
响应式布局技术
相对单位
使用相对单位让元素尺寸随视口变化:
/* 相对于根元素字体大小 */
html { font-size: 16px; }
h1 { font-size: 2rem; } /* 32px */
/* 视口单位 */
.hero { height: 100vh; } /* 视口高度 */
.width { width: 80vw; } /* 视口宽度 */
.responsive { font-size: clamp(1rem, 2.5vw, 2rem); }
/* 百分比 */
.container { width: 90%; max-width: 1200px; }
.sidebar { width: 25%; }
clamp() 函数设置值的下限、首选值和上限:
.title {
font-size: clamp(1.5rem, 4vw, 3rem);
/* 最小 1.5rem,首选 4vw,最大 3rem */
}
.width {
width: clamp(300px, 80%, 800px);
}
弹性布局
Flexbox 和 Grid 天然支持响应式:
/* Flexbox 换行 */
.flex-container {
display: flex;
flex-wrap: wrap;
}
.flex-item {
flex: 1 1 300px; /* 最小 300px,自动换行 */
}
/* Grid 自动填充 */
.grid-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 20px;
}
响应式布局模式
从堆叠到并排:
/* 默认:手机堆叠 */
.layout {
display: flex;
flex-direction: column;
}
/* 平板及以上:并排 */
@media (min-width: 768px) {
.layout {
flex-direction: row;
}
}
Grid 响应式:
.grid {
display: grid;
gap: 20px;
grid-template-columns: 1fr;
}
@media (min-width: 576px) {
.grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (min-width: 992px) {
.grid {
grid-template-columns: repeat(4, 1fr);
}
}
隐藏/显示元素:
.mobile-only {
display: block;
}
@media (min-width: 768px) {
.mobile-only {
display: none;
}
}
.desktop-only {
display: none;
}
@media (min-width: 768px) {
.desktop-only {
display: block;
}
}
响应式图片
max-width 图片
最简单的响应式图片:
img {
max-width: 100%;
height: auto;
}
图片不会超过容器宽度,高度自动调整保持比例。
srcset 和 sizes
srcset 提供不同分辨率的图片,让浏览器选择最合适的:
<img
src="small.jpg"
srcset="small.jpg 480w, medium.jpg 800w, large.jpg 1200w"
sizes="(max-width: 600px) 480px, (max-width: 1000px) 800px, 1200px"
alt="响应式图片"
>
sizes 告诉浏览器图片在不同断点下的显示宽度,浏览器根据这些信息和设备像素比选择合适的图片。
picture 元素
<picture> 提供更精细的图片控制:
<picture>
<!-- 根据媒体查询选择 -->
<source media="(min-width: 800px)" srcset="large.webp">
<source media="(min-width: 400px)" srcset="medium.webp">
<source srcset="small.webp">
<!-- 根据格式选择 -->
<source srcset="image.avif" type="image/avif">
<source srcset="image.webp" type="image/webp">
<!-- 默认图片 -->
<img src="fallback.jpg" alt="描述">
</picture>
art direction
在不同屏幕尺寸下使用不同裁剪的图片:
<picture>
<source media="(min-width: 800px)" srcset="wide-crop.jpg">
<source media="(min-width: 400px)" srcset="medium-crop.jpg">
<img src="mobile-crop.jpg" alt="移动端裁剪版本">
</picture>
背景图片响应式
.hero {
background-image: url('small.jpg');
background-size: cover;
background-position: center;
}
@media (min-width: 768px) {
.hero {
background-image: url('medium.jpg');
}
}
@media (min-width: 1200px) {
.hero {
background-image: url('large.jpg');
}
}
使用 image-set() 函数:
.hero {
background-image: image-set(
'small.jpg' 1x,
'medium.jpg' 2x,
'large.jpg' 3x
);
}
响应式排版
相对字体大小
html {
font-size: 100%; /* 浏览器默认,通常 16px */
}
body {
font-size: 1rem;
}
h1 {
font-size: clamp(1.75rem, 4vw, 3rem);
}
行高和间距
body {
line-height: 1.5;
}
@media (min-width: 768px) {
body {
line-height: 1.6;
}
}
.container {
padding: 5%;
}
@media (min-width: 768px) {
.container {
padding: 3rem;
}
}
响应式导航
汉堡菜单模式
<nav class="nav">
<button class="nav-toggle" aria-label="菜单">
<span></span>
</button>
<ul class="nav-menu">
<li><a href="#">首页</a></li>
<li><a href="#">产品</a></li>
<li><a href="#">关于</a></li>
</ul>
</nav>
.nav-menu {
display: none;
}
.nav-menu.active {
display: flex;
flex-direction: column;
}
@media (min-width: 768px) {
.nav-toggle {
display: none;
}
.nav-menu {
display: flex;
flex-direction: row;
}
}
测试响应式设计
浏览器开发者工具
Chrome、Firefox 等浏览器都提供设备模拟功能:
- 打开开发者工具(F12)
- 点击设备工具栏图标
- 选择预设设备或自定义尺寸
测试要点
- 在各种尺寸下检查布局是否正常
- 文字是否清晰可读
- 触摸目标是否足够大(至少 44x44 像素)
- 图片是否正确加载和显示
- 导航是否可用
小结
这一章我们学习了:
- 视口设置的重要性
- 媒体查询的语法和使用
- 移动优先的设计策略
- 响应式布局技术
- 响应式图片的处理方法
- 响应式排版
响应式设计是现代 Web 开发的必备技能。记住几个关键点:
- 始终设置 viewport 元标签
- 使用移动优先策略
- 使用相对单位和弹性布局
- 选择合适的断点
- 测试各种设备和尺寸
下一章我们将学习 CSS 动画与过渡,为网页添加动态效果。