CSS 响应式设计
响应式设计使网页能够适配不同尺寸的设备,从手机到桌面显示器。
响应式设计基础
什么是响应式设计?
响应式设计是一种让网页布局根据设备屏幕尺寸自动调整的方法:
- 移动优先:从小屏幕开始设计
- 流式布局:使用相对单位而非固定像素
- 媒体查询:根据屏幕条件应用不同样式
viewport 视口
<!-- 必须设置! -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
视口属性说明:
| 属性 | 说明 |
|---|---|
| width | 视口宽度,device-width 表示设备宽度 |
| initial-scale | 初始缩放比例 |
| minimum-scale | 最小缩放比例 |
| maximum-scale | 最大缩放比例 |
| user-scalable | 是否允许用户缩放 |
媒体查询 @media
基本语法
/* 屏幕宽度小于768px时生效 */
@media (max-width: 768px) {
body {
font-size: 14px;
}
}
媒体类型
/* screen: 屏幕设备 */
@media screen { }
/* print: 打印机 */
@media print {
.navbar, .sidebar { display: none; }
}
/* all: 所有设备(默认) */
@media all { }
媒体条件
/* 最小宽度 */
@media (min-width: 768px) { }
/* 最大宽度 */
@media (max-width: 768px) { }
/* 宽度范围 */
@media (min-width: 768px) and (max-width: 1024px) { }
/* 屏幕方向 */
@media (orientation: portrait) { } /* 竖屏 */
@media (orientation: landscape) { } /* 横屏 */
/* 设备像素比 */
@media (-webkit-min-device-pixel-ratio: 2) { }
常用断点
/* 移动端 */
@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) { }
响应式布局策略
1. 移动优先 vs 桌面优先
移动优先(推荐)
/* 默认:移动端样式 */
.container { width: 100%; }
/* 平板及以上 */
@media (min-width: 768px) {
.container { width: 750px; }
}
/* 桌面及以上 */
@media (min-width: 992px) {
.container { width: 970px; }
}
/* 大桌面 */
@media (min-width: 1200px) {
.container { width: 1170px; }
}
桌面优先
/* 默认:桌面样式 */
.container { width: 1170px; }
/* 平板及以下 */
@media (max-width: 991px) {
.container { width: 750px; }
}
/* 手机及以下 */
@media (max-width: 767px) {
.container { width: 100%; }
}
2. 流式网格
.container {
width: 100%;
max-width: 1200px;
margin: 0 auto;
padding: 0 15px;
}
.grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
}
/* 响应式:减少列数 */
@media (max-width: 991px) {
.grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 575px) {
.grid { grid-template-columns: 1fr; }
}
3. Flexbox 响应式
.nav {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.nav-links {
display: flex;
gap: 20px;
}
/* 移动端:垂直排列 */
@media (max-width: 767px) {
.nav {
flex-direction: column;
}
.nav-links {
flex-direction: column;
gap: 10px;
}
}
4. 图片响应式
/* 基础 */
img {
max-width: 100%;
height: auto;
}
/* 响应式图片 */
<img src="small.jpg"
srcset="small.jpg 500w, medium.jpg 1000w, large.jpg 1500w"
sizes="(max-width: 600px) 100vw, 50vw"
alt="描述">
/* picture 元素 */
<picture>
<source media="(max-width: 600px)" srcset="mobile.jpg">
<source media="(min-width: 601px)" srcset="desktop.jpg">
<img src="default.jpg" alt="描述">
</picture>
5. 隐藏元素
.desktop-only {
display: none;
}
.mobile-only {
display: block;
}
@media (min-width: 768px) {
.desktop-only { display: block; }
.mobile-only { display: none; }
}
响应式组件
1. 响应式导航栏
/* 默认:移动端(汉堡菜单) */
.navbar {
display: flex;
flex-direction: column;
padding: 10px;
}
.menu-toggle {
display: block;
align-self: flex-end;
}
.nav-links {
display: none;
flex-direction: column;
}
/* 激活菜单 */
.nav-links.active {
display: flex;
}
/* 平板及以上 */
@media (min-width: 768px) {
.navbar {
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.menu-toggle {
display: none;
}
.nav-links {
display: flex;
flex-direction: row;
gap: 20px;
}
}
2. 响应式卡片
.card-container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 20px;
}
.card {
display: flex;
flex-direction: column;
padding: 20px;
}
.card img {
width: 100%;
height: 200px;
object-fit: cover;
}
@media (max-width: 575px) {
.card {
padding: 15px;
}
.card img {
height: 150px;
}
}
3. 响应式表单
.form-row {
display: flex;
gap: 20px;
margin-bottom: 15px;
}
.form-group {
flex: 1;
}
@media (max-width: 575px) {
.form-row {
flex-direction: column;
gap: 0;
}
}
4. 响应式表格
/* 横向滚动 */
.table-container {
overflow-x: auto;
}
/* 卡片式转换 */
@media (max-width: 767px) {
table, thead, tbody, th, td, tr {
display: block;
}
thead { display: none; }
tr {
margin-bottom: 15px;
border: 1px solid #ddd;
}
td {
padding: 10px 10px 10px 40%;
position: relative;
}
td::before {
content: attr(data-label);
position: absolute;
left: 10px;
font-weight: bold;
}
}
<table>
<thead>
<tr>
<th>姓名</th>
<th>年龄</th>
<th>城市</th>
</tr>
</thead>
<tbody>
<tr>
<td data-label="姓名">张三</td>
<td data-label="年龄">25</td>
<td data-label="城市">北京</td>
</tr>
</tbody>
</table>
响应式字体
1. 使用相对单位
html { font-size: 16px; }
body { font-size: 1rem; } /* 16px */
h1 { font-size: 2rem; } /* 32px */
p { font-size: 1rem; } /* 16px */
2. CSS clamp()
/* 响应式字体大小:最小14px,最大24px,优先18px */
h1 {
font-size: clamp(1.75rem, 2.5vw, 3rem);
}
p {
font-size: clamp(0.875rem, 1.5vw, 1.125rem);
}
3. 媒体查询调整
html { font-size: 14px; }
@media (min-width: 768px) {
html { font-size: 16px; }
}
@media (min-width: 1200px) {
html { font-size: 18px; }
}
响应式间距
/* 基础间距 */
.section {
padding: 20px;
}
/* 响应式间距 */
@media (min-width: 768px) {
.section { padding: 40px; }
}
@media (min-width: 1200px) {
.section { padding: 60px 0; }
}
/* 使用 CSS 变量 */
:root {
--spacing-sm: 10px;
--spacing-md: 20px;
--spacing-lg: 40px;
}
@media (min-width: 768px) {
:root {
--spacing-sm: 15px;
--spacing-md: 30px;
--spacing-lg: 60px;
}
}
常用响应式模式
1. 侧边栏布局
.layout {
display: grid;
grid-template-columns: 250px 1fr;
}
@media (max-width: 767px) {
.layout {
grid-template-columns: 1fr;
}
.sidebar { display: none; }
}
2. 卡片网格
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
@media (max-width: 991px) {
.grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 575px) {
.grid { grid-template-columns: 1fr; }
}
3. 堆叠到并排
.content {
display: flex;
flex-direction: column;
}
@media (min-width: 768px) {
.content {
flex-direction: row;
}
.main { flex: 2; }
.sidebar { flex: 1; }
}
测试工具
浏览器开发者工具
- 按 F12 打开开发者工具
- 点击设备模拟图标(手机图标)
- 选择不同设备或自定义尺寸
在线工具
小结
本章学习了:
- 响应式基础:viewport 设置、移动优先理念
- 媒体查询:条件语法、常用断点
- 布局策略:流式网格、Flexbox 响应式、隐藏元素
- 响应式组件:导航、卡片、表单、表格
- 响应式内容:图片、字体、间距
练习
- 为现有页面添加响应式设计
- 创建一套响应式网格系统
- 实现一个响应式导航栏
- 将表格转换为移动端卡片布局
- 使用 clamp() 实现响应式字体