Flexbox 布局
Flexbox(弹性盒子布局)是 CSS3 中的一种一维布局模型,它提供了一种更加高效的方式来布置、对齐和分配容器中项目之间的空间,即使它们的大小是未知或动态的。
什么是 Flexbox?
Flexbox 是 Flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。任何一个容器都可以指定为 Flex 布局。
基本概念
Flex 容器(Flex Container)
通过设置 display: flex 或 display: inline-flex 创建的容器:
css
.flex-container {
display: flex; /* 或 inline-flex */
}Flex 项目(Flex Items)
Flex 容器的直接子元素称为 Flex 项目:
html
<div class="flex-container">
<div class="flex-item">项目1</div>
<div class="flex-item">项目2</div>
<div class="flex-item">项目3</div>
</div>主轴和交叉轴
- 主轴(Main Axis):Flex 项目沿其排列的轴线
- 交叉轴(Cross Axis):垂直于主轴的轴线
Flex 容器属性
flex-direction
决定主轴的方向(项目的排列方向):
css
.flex-container {
display: flex;
flex-direction: row; /* 默认值:水平排列 */
}
.flex-container-column {
display: flex;
flex-direction: column; /* 垂直排列 */
}
.flex-container-row-reverse {
display: flex;
flex-direction: row-reverse; /* 水平反向排列 */
}
.flex-container-column-reverse {
display: flex;
flex-direction: column-reverse; /* 垂直反向排列 */
}flex-wrap
决定项目是否换行:
css
.flex-container-nowrap {
display: flex;
flex-wrap: nowrap; /* 默认值:不换行 */
}
.flex-container-wrap {
display: flex;
flex-wrap: wrap; /* 换行 */
}
.flex-container-wrap-reverse {
display: flex;
flex-wrap: wrap-reverse; /* 反向换行 */
}flex-flow
flex-direction 和 flex-wrap 的简写:
css
.flex-container {
display: flex;
flex-flow: row wrap; /* 等同于 flex-direction: row; flex-wrap: wrap; */
}justify-content
定义项目在主轴上的对齐方式:
css
.flex-container-flex-start {
display: flex;
justify-content: flex-start; /* 默认值:左对齐 */
}
.flex-container-flex-end {
display: flex;
justify-content: flex-end; /* 右对齐 */
}
.flex-container-center {
display: flex;
justify-content: center; /* 居中 */
}
.flex-container-space-between {
display: flex;
justify-content: space-between; /* 两端对齐,项目之间间隔相等 */
}
.flex-container-space-around {
display: flex;
justify-content: space-around; /* 每个项目两侧间隔相等 */
}
.flex-container-space-evenly {
display: flex;
justify-content: space-evenly; /* 每个项目周围间隔相等 */
}align-items
定义项目在交叉轴上的对齐方式:
css
.flex-container-stretch {
display: flex;
align-items: stretch; /* 默认值:拉伸 */
}
.flex-container-flex-start {
display: flex;
align-items: flex-start; /* 起点对齐 */
}
.flex-container-flex-end {
display: flex;
align-items: flex-end; /* 终点对齐 */
}
.flex-container-center {
display: flex;
align-items: center; /* 居中对齐 */
}
.flex-container-baseline {
display: flex;
align-items: baseline; /* 基线对齐 */
}align-content
定义多行项目在交叉轴上的对齐方式(仅在换行时有效):
css
.flex-container-flex-start {
display: flex;
flex-wrap: wrap;
align-content: flex-start;
}
.flex-container-flex-end {
display: flex;
flex-wrap: wrap;
align-content: flex-end;
}
.flex-container-center {
display: flex;
flex-wrap: wrap;
align-content: center;
}
.flex-container-space-between {
display: flex;
flex-wrap: wrap;
align-content: space-between;
}
.flex-container-space-around {
display: flex;
flex-wrap: wrap;
align-content: space-around;
}
.flex-container-stretch {
display: flex;
flex-wrap: wrap;
align-content: stretch;
}Flex 项目属性
order
定义项目的排列顺序,数值越小排列越靠前,默认为 0:
css
.flex-item {
order: 1; /* 数值可以是负数 */
}
.flex-item-first {
order: -1;
}flex-grow
定义项目的放大比例,默认为 0,即如果存在剩余空间也不放大:
css
.flex-item {
flex-grow: 1; /* 等分剩余空间 */
}
.flex-item-double {
flex-grow: 2; /* 占据两倍的剩余空间 */
}flex-shrink
定义项目的缩小比例,默认为 1,即如果空间不足该项目将缩小:
css
.flex-item {
flex-shrink: 1; /* 空间不足时缩小 */
}
.flex-item-no-shrink {
flex-shrink: 0; /* 空间不足时不缩小 */
}flex-basis
定义在分配多余空间之前,项目占据的主轴空间(main size):
css
.flex-item {
flex-basis: auto; /* 默认值,项目本来的大小 */
}
.flex-item-fixed {
flex-basis: 200px; /* 固定大小 */
}
.flex-item-percent {
flex-basis: 30%; /* 百分比 */
}flex
flex-grow, flex-shrink 和 flex-basis 的简写,默认值为 0 1 auto:
css
.flex-item {
flex: 1; /* 等同于 flex: 1 1 0% */
}
.flex-item-auto {
flex: auto; /* 等同于 flex: 1 1 auto */
}
.flex-item-none {
flex: none; /* 等同于 flex: 0 0 auto */
}
.flex-item-custom {
flex: 2 2 200px; /* flex-grow: 2; flex-shrink: 2; flex-basis: 200px; */
}align-self
允许单个项目有与其他项目不一样的对齐方式,可覆盖 align-items 属性:
css
.flex-item {
align-self: auto; /* 默认值,继承父元素的 align-items */
}
.flex-item-flex-start {
align-self: flex-start;
}
.flex-item-flex-end {
align-self: flex-end;
}
.flex-item-center {
align-self: center;
}
.flex-item-baseline {
align-self: baseline;
}
.flex-item-stretch {
align-self: stretch;
}基本示例
简单的 Flex 布局
html
<!DOCTYPE html>
<html>
<head>
<style>
.flex-container {
display: flex;
background-color: #f0f0f0;
padding: 10px;
border-radius: 5px;
}
.flex-item {
background-color: #3498db;
color: white;
padding: 20px;
margin: 10px;
border-radius: 5px;
text-align: center;
}
</style>
</head>
<body>
<div class="flex-container">
<div class="flex-item">项目1</div>
<div class="flex-item">项目2</div>
<div class="flex-item">项目3</div>
</div>
</body>
</html>水平垂直居中
html
<!DOCTYPE html>
<html>
<head>
<style>
.center-container {
display: flex;
justify-content: center;
align-items: center;
height: 300px;
background-color: #f0f0f0;
border-radius: 5px;
}
.centered-item {
background-color: #3498db;
color: white;
padding: 30px;
border-radius: 5px;
}
</style>
</head>
<body>
<div class="center-container">
<div class="centered-item">居中的内容</div>
</div>
</body>
</html>创建导航栏
html
<!DOCTYPE html>
<html>
<head>
<style>
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #333;
padding: 0 20px;
height: 60px;
}
.logo {
color: white;
font-size: 1.5em;
font-weight: bold;
}
.nav-links {
display: flex;
list-style: none;
}
.nav-links li {
margin: 0 15px;
}
.nav-links a {
color: white;
text-decoration: none;
padding: 10px 15px;
border-radius: 4px;
transition: background-color 0.3s;
}
.nav-links a:hover {
background-color: #555;
}
.nav-button {
background-color: #3498db;
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
}
</style>
</head>
<body>
<nav class="navbar">
<div class="logo">我的网站</div>
<ul class="nav-links">
<li><a href="#home">首页</a></li>
<li><a href="#about">关于</a></li>
<li><a href="#services">服务</a></li>
<li><a href="#contact">联系</a></li>
</ul>
<button class="nav-button">登录</button>
</nav>
</body>
</html>实际应用示例
卡片布局
html
<!DOCTYPE html>
<html>
<head>
<style>
.card-container {
display: flex;
flex-wrap: wrap;
gap: 20px;
padding: 20px;
}
.card {
flex: 1 1 300px; /* 允许伸缩,基础宽度300px */
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
overflow: hidden;
}
.card-image {
width: 100%;
height: 200px;
background-color: #3498db;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 1.5em;
}
.card-content {
padding: 20px;
}
.card-title {
margin-top: 0;
color: #333;
}
.card-text {
color: #666;
line-height: 1.6;
}
</style>
</head>
<body>
<div class="card-container">
<div class="card">
<div class="card-image">图片</div>
<div class="card-content">
<h3 class="card-title">卡片标题1</h3>
<p class="card-text">这是卡片的内容描述,可以包含文本、图像等元素。Flexbox 使卡片布局变得非常简单和灵活。</p>
</div>
</div>
<div class="card">
<div class="card-image">图片</div>
<div class="card-content">
<h3 class="card-title">卡片标题2</h3>
<p class="card-text">通过设置 flex 属性,我们可以轻松控制卡片的大小和排列方式,适应不同的屏幕尺寸。</p>
</div>
</div>
<div class="card">
<div class="card-image">图片</div>
<div class="card-content">
<h3 class="card-title">卡片标题3</h3>
<p class="card-text">使用 gap 属性可以轻松设置卡片之间的间距,而不需要使用 margin。</p>
</div>
</div>
</div>
</body>
</html>媒体对象布局
html
<!DOCTYPE html>
<html>
<head>
<style>
.media {
display: flex;
align-items: flex-start;
padding: 20px;
border: 1px solid #ddd;
border-radius: 5px;
margin-bottom: 20px;
}
.media-figure {
margin-right: 20px;
}
.media-figure img {
width: 100px;
height: 100px;
background-color: #3498db;
border-radius: 5px;
}
.media-body {
flex: 1;
}
.media-title {
margin-top: 0;
margin-bottom: 10px;
color: #333;
}
.media-text {
margin: 0 0 10px 0;
color: #666;
line-height: 1.6;
}
.media-actions {
display: flex;
gap: 10px;
}
.media-button {
padding: 5px 10px;
background-color: #f0f0f0;
border: none;
border-radius: 3px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="media">
<div class="media-figure">
<img src="#" alt="头像">
</div>
<div class="media-body">
<h4 class="media-title">用户名称</h4>
<p class="media-text">这是用户发布的评论内容。Flexbox 的 align-items: flex-start 属性确保头像和文本顶部对齐,创建经典的媒体对象布局。</p>
<div class="media-actions">
<button class="media-button">点赞</button>
<button class="media-button">回复</button>
</div>
</div>
</div>
<div class="media">
<div class="media-figure">
<img src="#" alt="头像">
</div>
<div class="media-body">
<h4 class="media-title">另一个用户</h4>
<p class="media-text">Flexbox 使得创建这种响应式布局变得非常简单。在小屏幕上,内容会自动调整以适应可用空间。</p>
<div class="media-actions">
<button class="media-button">点赞</button>
<button class="media-button">回复</button>
</div>
</div>
</div>
</body>
</html>响应式 Flexbox
响应式导航栏
html
<!DOCTYPE html>
<html>
<head>
<style>
.responsive-nav {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
background-color: #333;
padding: 10px 20px;
}
.nav-logo {
color: white;
font-size: 1.5em;
font-weight: bold;
}
.nav-menu {
display: flex;
list-style: none;
margin: 0;
padding: 0;
}
.nav-menu li {
margin: 0 10px;
}
.nav-menu a {
color: white;
text-decoration: none;
padding: 10px;
border-radius: 4px;
}
.nav-menu a:hover {
background-color: #555;
}
.nav-toggle {
display: none;
background: none;
border: none;
color: white;
font-size: 1.5em;
cursor: pointer;
}
@media (max-width: 768px) {
.nav-menu {
flex-direction: column;
width: 100%;
display: none;
}
.nav-menu.active {
display: flex;
}
.nav-toggle {
display: block;
}
.nav-menu li {
margin: 5px 0;
width: 100%;
text-align: center;
}
}
</style>
</head>
<body>
<nav class="responsive-nav">
<div class="nav-logo">我的网站</div>
<button class="nav-toggle">☰</button>
<ul class="nav-menu" id="navMenu">
<li><a href="#home">首页</a></li>
<li><a href="#about">关于</a></li>
<li><a href="#services">服务</a></li>
<li><a href="#portfolio">作品</a></li>
<li><a href="#contact">联系</a></li>
</ul>
</nav>
<script>
document.querySelector('.nav-toggle').addEventListener('click', function() {
document.getElementById('navMenu').classList.toggle('active');
});
</script>
</body>
</html>Flexbox 与 Grid 的比较
Flexbox 适用场景
html
<!DOCTYPE html>
<html>
<head>
<style>
.comparison {
font-family: Arial, sans-serif;
margin: 20px;
}
.section-title {
text-align: center;
margin: 30px 0;
color: #333;
}
/* Flexbox 示例 - 一维布局 */
.flex-example {
display: flex;
gap: 20px;
padding: 20px;
background-color: #f8f9fa;
border-radius: 5px;
}
.flex-item {
flex: 1;
padding: 20px;
background-color: #3498db;
color: white;
text-align: center;
border-radius: 5px;
}
/* Grid 示例 - 二维布局 */
.grid-example {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
padding: 20px;
background-color: #f8f9fa;
border-radius: 5px;
}
.grid-item {
padding: 20px;
background-color: #e74c3c;
color: white;
text-align: center;
border-radius: 5px;
}
</style>
</head>
<body>
<div class="comparison">
<h2 class="section-title">Flexbox 一维布局</h2>
<div class="flex-example">
<div class="flex-item">项目1</div>
<div class="flex-item">项目2</div>
<div class="flex-item">项目3</div>
</div>
<h2 class="section-title">Grid 二维布局</h2>
<div class="grid-example">
<div class="grid-item">项目1</div>
<div class="grid-item">项目2</div>
<div class="grid-item">项目3</div>
<div class="grid-item">项目4</div>
<div class="grid-item">项目5</div>
<div class="grid-item">项目6</div>
</div>
</div>
</body>
</html>最佳实践
- 选择合适的布局方式:一维布局用 Flexbox,二维布局用 Grid
- 合理使用 flex 属性:理解 flex-grow、flex-shrink 和 flex-basis 的作用
- 注意浏览器兼容性:现代浏览器都支持 Flexbox
- 避免过度嵌套:复杂的布局可能需要结合多种技术
- 考虑响应式设计:使用媒体查询调整 Flexbox 行为
浏览器兼容性
Flexbox 在现代浏览器中有很好的支持:
- Chrome 29+
- Firefox 28+
- Safari 9+
- Edge
- Internet Explorer 11+(部分支持)
总结
Flexbox 是现代 CSS 布局的重要工具,特别适合创建一维布局。它的主要优势包括:
- 简化了居中对齐的实现
- 提供了灵活的空间分配机制
- 支持响应式设计
- 减少了对浮动和定位的依赖
掌握 Flexbox 对于现代 Web 开发至关重要。在下一章节中,我们将学习更强大的 Grid 布局 技术。