布局与响应式设计-第11章-11.3-项目属性与实战
学习目标
- 掌握
flex-grow、flex-shrink、flex-basis三个核心项目属性的语法与取值规则 - 能够通过项目属性实现元素的动态空间分配
- 独立完成导航栏、卡片列表、垂直居中三种实战布局
概念讲解
Flex项目属性用于控制单个项目在容器中的空间分配和尺寸调整,是实现灵活布局的核心。与容器属性(控制整体排列)不同,项目属性专注于个体元素的行为,包括:
- 扩展能力:当容器有剩余空间时是否放大(
flex-grow) - 收缩能力:当容器空间不足时是否缩小(
flex-shrink) - 基础尺寸:项目在分配空间前的默认大小(
flex-basis)
三者共同决定了项目在Flex布局中的动态响应特性,使界面能够根据容器尺寸自动调整元素大小,是实现响应式设计的关键。
语法参考
1. 核心属性详解
| 属性名 | 取值范围 | 默认值 | 作用描述 |
|---|---|---|---|
flex-grow |
≥0的数字 | 0 | 定义项目的扩展比例,容器剩余空间按比例分配给项目(0表示不扩展) |
flex-shrink |
≥0的数字 | 1 | 定义项目的收缩比例,容器空间不足时按比例缩小项目(0表示不收缩) |
flex-basis |
auto/长度值 |
auto |
定义项目的基础尺寸,优先级高于width/height,auto表示使用内容尺寸 |
flex |
复合属性 | 0 1 auto | 简写形式:flex: grow shrink basis(推荐使用简写) |
2. 常用flex简写组合
| 简写形式 | 等价展开 | 适用场景 |
|---|---|---|
flex: 1 |
flex: 1 1 0% |
等分剩余空间(常用作自适应内容区) |
flex: auto |
flex: 1 1 auto |
基于内容尺寸伸缩(适合动态文本容器) |
flex: none |
flex: 0 0 auto |
固定尺寸不伸缩(适合固定宽度按钮/图标) |
flex: 2 0 200px |
flex-grow:2; flex-shrink:0; flex-basis:200px |
优先占据2份空间,不收缩,基础尺寸200px |
实战示例
示例1:基础项目属性演示
<div class="flex-container">
<div class="item item-1">1</div>
<div class="item item-2">2</div>
<div class="item item-3">3</div>
</div>
<style>
.flex-container {
display: flex;
width: 600px;
height: 100px;
border: 2px solid #333;
}
.item {
width: 100px; /* 基础宽度(会被flex-basis覆盖) */
height: 80px;
text-align: center;
line-height: 80px;
font-size: 24px;
color: white;
}
.item-1 {
background: #ff6b6b;
flex: 1 1 100px; /* 扩展1份,收缩1份,基础尺寸100px */
}
.item-2 {
background: #4ecdc4;
flex: 2 1 100px; /* 扩展2份,收缩1份,基础尺寸100px */
}
.item-3 {
background: #ffe66d;
flex: 1 1 100px; /* 扩展1份,收缩1份,基础尺寸100px */
}
</style>
效果解析:
- 容器总宽度600px,3个项目基础尺寸各100px,总基础宽度300px,剩余空间300px
item-2的flex-grow:2,占据剩余空间的2/4(150px),最终宽度=100+150=250pxitem-1和item-3各占1/4(75px),最终宽度=100+75=175px
示例2:实战布局案例
案例1:响应式导航栏(固定侧边+自适应内容)
<nav class="main-nav">
<div class="logo">LOGO</div>
<div class="nav-links">
<a href="/">首页</a>
<a href="/">课程</a>
<a href="/">文档</a>
<a href="/">关于</a>
</div>
<div class="user-menu">登录</div>
</nav>
<style>
.main-nav {
display: flex;
height: 60px;
padding: 0 20px;
background: #2c3e50;
color: white;
align-items: center;
}
.logo {
flex: none; /* 固定尺寸不伸缩 */
width: 80px;
font-weight: bold;
font-size: 20px;
}
.nav-links {
flex: 1; /* 自适应剩余空间 */
display: flex;
margin: 0 20px;
gap: 20px;
}
.nav-links a {
color: white;
text-decoration: none;
padding: 5px 10px;
}
.user-menu {
flex: none; /* 固定尺寸不伸缩 */
width: 60px;
text-align: right;
}
</style>
关键技术:
logo和user-menu使用flex: none保持固定宽度nav-links使用flex: 1占据中间所有剩余空间,实现导航栏自适应不同屏幕宽度
案例2:卡片列表(等高布局+底部对齐)
<div class="card-container">
<div class="card">
<img src="https://picsum.photos/300/200" alt="产品图片">
<h3>产品名称</h3>
<p>简短产品描述,可能有多行文本...</p>
<div class="card-footer">
<span>¥99</span>
<button>加入购物车</button>
</div>
</div>
<!-- 重复3-4个卡片 -->
</div>
<style>
.card-container {
display: flex;
gap: 20px;
padding: 20px;
flex-wrap: wrap;
}
.card {
display: flex;
flex-direction: column; /* 垂直排列子元素 */
width: 300px;
border: 1px solid #eee;
border-radius: 8px;
overflow: hidden;
}
.card img {
height: 200px;
object-fit: cover;
}
.card h3 {
padding: 15px 15px 5px;
margin: 0;
}
.card p {
padding: 0 15px 15px;
margin: 0;
flex: 1; /* 内容区自动扩展,使所有卡片等高 */
}
.card-footer {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px;
border-top: 1px solid #eee;
}
</style>
关键技术:
- 卡片内部使用
flex-direction: column垂直排列 - 文本区域
p标签设置flex: 1,自动扩展填充剩余空间,实现所有卡片等高布局 - 底部按钮区
card-footer通过margin-top: auto(等效于margin-top: auto在列布局中)固定在底部
注意事项
1. 兼容性处理
- IE11:支持基本Flexbox,但存在
flex-basis计算bug(需显式设置width作为降级方案) - Safari 9-:需要添加
-webkit-前缀(如-webkit-flex-grow)
2. 性能优化
- 避免同时使用
flex-grow和固定width,可能导致尺寸计算冲突 - 优先使用
flex简写属性(如flex: 1),比单独设置三个属性性能更优
3. 常见误区
- ❌ 错误:认为
flex-grow是“占据百分比”(实际是剩余空间分配比例) - ❌ 错误:设置
flex-basis: 0却期望内容撑开宽度(需使用flex-basis: auto) - ✅ 正确:
flex: 1适合等分空间,flex: auto适合内容优先的自适应
自测题
-
当容器空间不足时,
flex-shrink: 0的项目会如何表现?( )
A. 优先缩小 B. 不缩小 C. 等比例缩小 -
要实现“左侧固定200px,右侧自适应”的两栏布局,右侧项目应设置( )
A.flex: 1B.flex: noneC.flex: 0 0 200px -
代码分析题:以下代码中
.item2的最终宽度是多少?(容器宽度500px).container { display: flex; } .item1 { flex: 1 1 100px; } .item2 { flex: 2 1 200px; }A. 200px B. 250px C. 300px
(答案见附录C)
发表回复