flex 布局用了这么多年,justify-content 和 align-items 还是有人老是记混。不是因为笨,是因为这两个属性的行为会随 flex-direction 变化,记住"横向纵向"没用,下次换了方向又乱了。
这篇文章从主轴和交叉轴的概念出发,讲清楚为什么记混、怎么记对,以及几个常见场景的写法。
先搞清楚一件事:轴的方向不是固定的
很多人背的是"justify-content 控制水平方向,align-items 控制垂直方向"。这句话在默认情况下是对的,但只要 flex-direction 改了,这句话就错了。
准确的描述是:
justify-content:控制主轴方向的对齐align-items:控制交叉轴方向的对齐
主轴是什么?就是 flex-direction 指定的方向:
flex-direction: row; /* 主轴是水平方向(默认) */
flex-direction: row-reverse; /* 主轴是水平方向,但从右往左 */
flex-direction: column; /* 主轴是垂直方向 */
flex-direction: column-reverse; /* 主轴是垂直方向,但从下往上 */
交叉轴永远和主轴垂直。主轴是水平的,交叉轴就是垂直的;主轴是垂直的,交叉轴就是水平的。
所以当你把 flex-direction 改成 column,两个属性的效果就完全反过来了:
/* flex-direction: row(默认) */
.container {
display: flex;
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
}
/* flex-direction: column */
.container {
display: flex;
flex-direction: column;
justify-content: center; /* 垂直居中! */
align-items: center; /* 水平居中! */
}
记这个最简单的方式:justify 跟着主轴走,align 跟着交叉轴走,主轴在哪 justify 就控制哪个方向。
垂直居中,为什么有时候不生效?
这是最常见的问题。写了 align-items: center,元素就是不居中。
原因几乎只有一个:容器没有高度,或者高度不够。
align-items 控制的是元素在交叉轴上的位置,但如果容器本身没有指定高度,它的高度就等于子元素的高度,根本没有多余的空间,居中也就无从谈起。
/* 不生效:容器高度就是内容高度,没有空间居中 */
.container {
display: flex;
align-items: center;
}
/* 生效:给容器一个高度 */
.container {
display: flex;
align-items: center;
height: 300px; /* 或者 min-height,或者 100vh */
}
做全屏垂直居中:
.container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
space-between、space-around、space-evenly 有什么区别?
这三个值都是 justify-content 的选项,都是把剩余空间分配给间距,但分配方式不同。
假设容器里有三个元素,用示意图来看:
space-between: |A B C| 首尾元素贴边,间距在中间平均分
space-around: | A B C | 每个元素两侧各有等量空间(首尾是内部间距的一半)
space-evenly: | A B C | 所有间距完全相等,包括首尾
实际写代码时:
/* 导航栏:logo 在左,链接在右 */
.nav {
display: flex;
justify-content: space-between;
}
/* 卡片列表:卡片之间和两侧都有间距 */
.cards {
display: flex;
justify-content: space-evenly;
}
不过现在更推荐直接用 gap 来控制间距,而不是依赖 justify-content 的 space 系列值,因为 gap 更直观,而且在换行时行为也更符合预期:
.container {
display: flex;
flex-wrap: wrap;
gap: 16px; /* 元素之间的间距,首尾不加 */
}
align-items 和 align-content 的区别
这也是常见的困惑点。
align-items:控制每一行内部,子元素在交叉轴上的对齐方式align-content:控制多行在容器交叉轴上整体的分布方式,只有在flex-wrap: wrap且实际发生了换行时才有效果
/* 只有一行内容时,align-content 没有效果 */
.container {
display: flex;
align-items: center; /* 这行有效:控制行内对齐 */
align-content: center; /* 这行无效:只有一行,没有多行分布可言 */
}
/* 多行时,两个属性同时发挥作用 */
.container {
display: flex;
flex-wrap: wrap;
height: 400px;
align-items: flex-start; /* 每行内部:顶部对齐 */
align-content: space-between; /* 多行之间:两端对齐 */
}
记忆方式:items 管的是行内的事,content 管的是行与行之间的事。
几个常见布局的写法
水平垂直居中(最常用)
.container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
导航栏:左边 logo,右边按钮
.nav {
display: flex;
justify-content: space-between;
align-items: center;
}
把最后一个元素推到最右边
.nav {
display: flex;
align-items: center;
}
.nav .last-item {
margin-left: auto; /* auto margin 会吃掉所有剩余空间 */
}
等高卡片列表
.cards {
display: flex;
flex-wrap: wrap;
gap: 16px;
align-items: stretch; /* 默认值,子元素自动拉伸到等高 */
}
竖向排列,水平居中
.container {
display: flex;
flex-direction: column;
align-items: center; /* 注意:column 时,align-items 控制水平方向 */
}
想直接验证这些布局效果,把 HTML 和 CSS 粘到 HTML 在线编辑器 里实时预览,改一个属性马上看到变化,比在本地建文件测试快多了。



加载中...