基于 Flex 布局的响应式自适应卡片布局
七崽爱吃小饼干2026/02/28阅读 1
基于 Flex 布局的响应式自适应卡片布局:在父容器不同宽度区间内,一行显示的卡片数量自动变化,同时卡片间距固定、宽度自适应填充剩余空间。这是前端开发中非常常见的需求(比如商品列表、宫格布局)。
一、核心实现思路
要实现这个效果,需要结合 Flex 布局 + CSS 媒体查询(Media Query) + calc() 计算宽度,核心逻辑:
- 用 Flex 容器实现卡片横向排列,
flex-wrap: wrap让卡片自动换行; - 用媒体查询划分父容器宽度区间,不同区间设置一行显示的卡片数量;
- 用
calc()计算每张卡片的宽度(总宽度 - 所有间距)/ 卡片数量,保证间距固定、宽度自适应; - 用
gap或margin控制卡片间距(推荐gap,更简洁)。
二、完整可运行代码
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Flex 响应式卡片布局</title>
<style>
/* 父容器:核心 Flex 配置 */
.card-container {
width: 90%; /* 父容器宽度(可根据需求调整,比如100%) */
margin: 0 auto; /* 居中 */
display: flex;
flex-wrap: wrap; /* 自动换行 */
gap: 16px; /* 固定间距(水平+垂直),替代margin更方便 */
padding: 20px 0;
border: 1px solid #eee;
}
/* 卡片基础样式 */
.card {
/* 初始宽度(会被媒体查询覆盖,仅作兜底) */
width: calc((100% - 16px * 1) / 2); /* 默认一行2个 */
height: 150px;
background: #f5f5f5;
border-radius: 8px;
display: flex;
justify-content: center;
align-items: center;
font-size: 18px;
}
/* 媒体查询:按父容器宽度划分区间,调整一行卡片数量 */
/* 区间1:父容器宽度 ≥ 1200px → 一行4个 */
@media (min-width: 1200px) {
.card {
width: calc((100% - 16px * 3) / 4);
/* 计算逻辑:总宽度 - (间距 * (卡片数-1)) / 卡片数 */
}
}
/* 区间2:父容器宽度 ≥ 768px 且 < 1200px → 一行3个 */
@media (min-width: 768px) and (max-width: 1199px) {
.card {
width: calc((100% - 16px * 2) / 3);
}
}
/* 区间3:父容器宽度 ≥ 480px 且 < 768px → 一行2个 */
@media (min-width: 480px) and (max-width: 767px) {
.card {
width: calc((100% - 16px * 1) / 2);
}
}
/* 区间4:父容器宽度 < 480px → 一行1个 */
@media (max-width: 479px) {
.card {
width: 100%; /* 无间距,宽度100% */
}
}
</style>
</head>
<body>
<div class="card-container">
<div class="card">卡片1</div>
<div class="card">卡片2</div>
<div class="card">卡片3</div>
<div class="card">卡片4</div>
<div class="card">卡片5</div>
<div class="card">卡片6</div>
</div>
</body>
</html>
三、关键代码解释
1. 父容器核心配置
css
.card-container {
display: flex; /* 开启Flex布局 */
flex-wrap: wrap; /* 卡片超出容器宽度时自动换行 */
gap: 16px; /* 固定间距:水平和垂直方向都是16px,无需手动处理margin */
}
gap是 Flex/Grid 布局的专属属性,直接控制项目之间的间距,比用margin更简洁(无需处理最后一个元素的多余 margin);- 如果需要兼容老旧浏览器(如 IE),可以替换为
margin实现:css.card { margin: 0 8px 16px 8px; } /* 水平间距8px*2=16px,垂直间距16px */ .card-container { margin: 0 -8px; } /* 抵消容器内边距 */
2. 卡片宽度计算(核心)
宽度计算公式:
css
width: calc((100% - 间距 * (一行卡片数 - 1)) / 一行卡片数);
- 示例:一行4个卡片、间距16px →
calc((100% - 16px*3)/4); - 逻辑:总宽度减去「所有卡片之间的间距总和」,再平分给每个卡片,保证间距固定、卡片宽度自适应。
3. 媒体查询区间划分
按常见的设备宽度划分区间(可根据需求自定义):
- ≥1200px(大屏PC):一行4个;
- 768px~1199px(平板/小屏PC):一行3个;
- 480px~767px(大屏手机):一行2个;
- <480px(小屏手机):一行1个。
四、优化与拓展
1. 动态卡片数量适配
如果卡片数量不固定,Flex 的 flex-wrap: wrap 会自动换行,无需额外处理,比如6个卡片在一行4个的区间里,会显示2行(4个+2个),且每行的卡片宽度一致。
2. 兼容移动端
在 <head> 里添加视口设置,保证移动端适配:
html
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
3. 卡片最小宽度限制
如果不想让卡片缩得太窄,可以添加 min-width 限制,结合 flex 实现更灵活的适配:
css
.card {
flex: 1 1 calc((100% - 16px * 3) / 4); /* 伸缩+基准宽度 */
min-width: 200px; /* 最小宽度,小于该值时自动换行 */
}
这种方式无需媒体查询,也能实现“宽度足够时显示更多卡片,不足时自动换行”,适合不想固定区间的场景。
总结
- 核心方案:Flex(
flex-wrap: wrap)+ 媒体查询 +calc()计算宽度,实现不同区间一行显示不同卡片数,间距固定; - 间距控制:优先用
gap实现固定间距,兼容老旧浏览器则用margin; - 灵活拓展:可通过
min-width+flex替代媒体查询,实现无区间的自适应换行。