CSS: 响应式布局实战
掌握了响应式设计的基础知识后,我们来通过实际案例看看如何把理论应用到项目中。
响应式设计速查表
| 属性/技术 | 常用值/语法 | 作用 |
|---|---|---|
@media |
@media (max-width: 768px) { ... } |
媒体查询,在不同屏幕尺寸应用不同样式 |
min-width |
320px |
元素最小宽度(防止缩太小) |
max-width |
1200px |
元素最大宽度(响应式布局常用) |
vw / vh |
50vw, 100vh |
视口相对单位(1vw = 视口宽度的1%) |
rem |
1rem = 16px(默认) |
相对根元素字体大小 |
em |
1em = 父元素字体大小 |
相对父元素字体大小 |
% |
50%, 100% |
相对父容器百分比 |
clamp() |
clamp(16px, 3vw, 32px) |
限制值在范围内(CSS 函数) |
min() / max() |
min(100%, 1200px) |
取最小/最大值(CSS 函数) |
1. 响应式网格系统
我们可以用 CSS Grid 或 Flexbox 构建自己的简易网格系统:
(1) 使用 Grid 实现
▶ 示例
HTML
<style>
/* 基础网格 */
.grid {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: 20px;
}
/* 列类 */
.col-3 { grid-column: span 3; }
.col-4 { grid-column: span 4; }
.col-6 { grid-column: span 6; }
.col-8 { grid-column: span 8; }
.col-12 { grid-column: span 12; }
/* 平板:6列网格 */
@media (max-width: 768px) {
.grid {
grid-template-columns: repeat(6, 1fr);
}
.col-md-3 { grid-column: span 3; }
.col-md-6 { grid-column: span 6; }
}
/* 手机:全部单列 */
@media (max-width: 576px) {
.grid {
grid-template-columns: 1fr;
}
}
.media-demo { padding: 20px; background: #f0f0f0; border-radius: 8px; border: 1px solid #ddd; }
</style>
<div class="media-demo">Media demo</div>
(2) 使用 Flexbox 实现
▶ 示例
HTML
<style>
.row {
display: flex;
flex-wrap: wrap;
}
[class*="col-"] {
padding: 0 10px;
box-sizing: border-box;
}
.col-3 { width: 25%; }
.col-4 { width: 33.33%; }
.col-6 { width: 50%; }
.col-12 { width: 100%; }
@media (max-width: 768px) {
.col-md-6 { width: 50%; }
.col-md-12 { width: 100%; }
}
@media (max-width: 576px) {
.col-sm-12 { width: 100%; }
}
.media-demo { padding: 20px; background: #f0f0f0; border-radius: 8px; border: 1px solid #ddd; }
</style>
<div class="media-demo">Media demo</div>
2. 实战案例:响应式卡片网格
(1) HTML 结构
HTML
<div class="card-grid">
<div class="card">
<img src="image1.jpg" alt="卡片图片">
<div class="card-body">
<h3>卡片标题</h3>
<p>卡片描述文字...</p>
<a href="#" class="btn">Btn</a>
</div>
</div>
<!-- 重复更多卡片... -->
</div>
(2) CSS 实现
▶ 示例
HTML
📖 仅展示
<style>
/* 默认:手机优先 */
.card-grid {
display: grid;
grid-template-columns: 1fr;
gap: 20px;
padding: 20px;
max-width: 1200px;
margin: 0 auto;
}
.card {
border: 1px solid #eee;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.card img {
width: 100%;
height: 200px;
object-fit: cover;
}
.card-body {
padding: 16px;
}
.card h3 {
margin: 0 0 8px;
font-size: 1.2rem;
}
/* 平板:两列 */
@media (min-width: 600px) {
.card-grid {
grid-template-columns: repeat(2, 1fr);
}
}
/* 桌面:三列 */
@media (min-width: 900px) {
.card-grid {
grid-template-columns: repeat(3, 1fr);
}
}
/* 大桌面:四列 */
@media (min-width: 1200px) {
.card-grid {
grid-template-columns: repeat(4, 1fr);
}
}
.media-demo { padding: 20px; background: #f0f0f0; border-radius: 8px; border: 1px solid #ddd; }
</style>
<div class="media-demo">Media demo</div>
3. 实战案例:响应式导航栏
HTML
<nav class="navbar">
<div class="nav-brand">Nav brand</div>
<ul class="nav-menu">
<li><a href="#">首页</a></li>
<li><a href="#">关于</a></li>
<li><a href="#">服务</a></li>
<li><a href="#">联系</a></li>
</ul>
</nav>
▶ 示例
HTML
<style>
/* 移动优先:垂直菜单 */
.navbar {
background: #333;
color: white;
padding: 10px 20px;
}
.nav-menu {
list-style: none;
/* 列表样式 */
padding: 0;
margin: 10px 0 0;
}
.nav-menu li {
margin: 5px 0;
}
.nav-menu a {
color: white;
text-decoration: none;
display: block;
padding: 8px 0;
}
/* 桌面:水平菜单 */
@media (min-width: 768px) {
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
}
.nav-menu {
display: flex;
gap: 20px;
margin: 0;
}
.nav-menu li {
margin: 0;
}
}
.media-demo { padding: 20px; background: #f0f0f0; border-radius: 8px; border: 1px solid #ddd; }
</style>
<div class="media-demo">Media demo</div>
4. 实战案例:响应式布局综合
▶ 示例
HTML
📖 仅展示
<style>
/* ===== 页面整体布局 ===== */
body {
margin: 0;
font-family: sans-serif;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
/* ===== 两栏内容区 ===== */
.content-area {
display: grid;
grid-template-columns: 1fr;
gap: 30px;
}
@media (min-width: 768px) {
.content-area {
grid-template-columns: 1fr 300px; /* 主内容 + 侧栏 */
}
}
/* ===== 图片自适应 ===== */
.responsive-img {
max-width: 100%;
height: auto;
}
/* ===== 表格响应式 ===== */
.table-wrapper {
overflow-x: auto; /* 小屏表格可横向滚动 */
}
/* ===== 隐藏/显示元素 ===== */
.desktop-only {
display: none;
}
.mobile-only {
display: block;
}
@media (min-width: 768px) {
.desktop-only {
display: block;
}
.mobile-only {
display: none;
}
}
.media-demo { padding: 20px; background: #f0f0f0; border-radius: 8px; border: 1px solid #ddd; }
</style>
<div class="media-demo">Media demo</div>
5. 测试响应式布局
- 在浏览器中缩放窗口:最简单的方法,直接拖拽浏览器边框
- Chrome DevTools 的设备模拟:F12 → 切换设备工具栏(Ctrl+Shift+M)
- 真实设备测试:如果可以,最好在真实手机、平板上测试
❓ 常见问题
Q 图片怎么做响应式?
A 基础版:
img { max-width: 100%; height: auto; } 保证图片不溢出容器。进阶版:用 <picture> 和 <source> 在不同的屏幕尺寸加载不同分辨率的图片。大部分场景基础版就够用了。Q 响应式布局一定要做三个版本吗?
A 不需要。先保证手机端体验良好,然后在大屏上逐步增强。很多页面手机版+桌面版两个版本就够了,平板版往往是自然过渡。关键是"内容优先,设备适配",而不是为了响应式而响应式。
Q 怎么测试响应式效果?
A 浏览器 F12 的 DevTools 可以模拟各种设备尺寸,但建议在真实设备上打开看看。触摸操作的真实感受是模拟器给不了的。也可以用
https://www.responsinator.com 这类在线工具快速查看。📖 小节
- 响应式布局的核心是"灵活适应"
- 通过弹性网格(% / fr)、弹性图片(max-width)、媒体查询(@media)三件套,可以构建出在各种屏幕上都有良好表现的页面
- 实际开发中,一般采用"移动优先"的策略:先写好手机版样式,再用
min-width逐步为平板、桌面增加样式
📝 作业
- 创建一个"响应式个人博客"页面,包含头部导航、文章列表、侧栏推荐和底部版权。要求:
- 手机:单列布局
- 平板:两列布局
- 桌面:三列布局 + 固定侧栏
- 使用
min-width断点,将上面案例中的"卡片网格"从 1 列逐步变成 4列,每个断点至少观察效果。 - 创建一个响应式表格页面,在小屏设备上表格可以横向滚动(使用
overflow-x: auto)。