先记住这个答案
align-items: baseline 不看盒子的边缘,看的是文字的基线。浏览器找到每个子项第一行文字的基线,然后把它们对齐到同一水平线上。这样即使各子项的字号、行高或 padding 不同,文字看起来依然整齐。它不会拉伸子项的高度,和 stretch 是完全不同的行为。
- 按第一行文字基线对齐
- 字号不同时文字仍在同一水平线
- 没有文字时用盒子底边当基线
- 和
stretch互斥,不会同时拉伸
字号不同时 baseline 的效果
一个 flex 容器里放一个大标题和几个小按钮。如果用 flex-start,所有盒子的顶边对齐,但文字参差不齐。如果用 center,盒子居中了,文字还是不在同一条线上。只有 baseline 才能让不同字号的文字在视觉上对齐。
.toolbar {
display: flex;
align-items: baseline; /* 文字基线对齐 */
gap: 16px;
}
.title {
font-size: 24px;
padding: 8px 0;
}
.button {
font-size: 14px;
padding: 6px 12px;
}
/* 虽然字号和 padding 都不同,文字在同一条水平线上 */这种对齐在导航栏、工具栏和表单标签旁边放按钮的场景里特别有用。
和 flex-start 以及 center 的区别
flex-start 让盒子顶边对齐,文字的位置取决于各自的 padding-top 和字号,通常参差不齐。center 让盒子在交叉轴上居中,文字的位置依然取决于各自的 padding 比例。baseline 直接对齐文字本身,不管盒子的 padding 怎么设。
选择用哪个取决于你想对齐的是盒子还是文字。如果是卡片列表,盒子边缘整齐更重要,用 flex-start 或 stretch。如果是文字混排(标题旁边放标签),用 baseline 更自然。
没有文字时怎么处理
如果某个子项是一个纯图标或者空盒子,没有文字内容,浏览器无法找到基线。这时会用这个子项 margin box 的底边当作基线。效果类似 flex-end,图标会和其他子项的文字底部大致对齐。
不过这个退化行为有时候不太好看。如果容器里混合了文字和纯图标,可以考虑给图标加一个隐藏的文字让它有基线,或者单独给图标设 align-self: center。
容易答错的地方
- 以为
baseline对齐的是盒子底边 baseline对齐的是文字基线,不是盒子底边。基线是文字底部的那条不可见的线(严格来说是拉丁字母的底边),位置取决于字号和行高。- 以为
baseline和stretch可以同时生效 baseline不拉伸高度。设了baseline后,子项的高度由内容决定,不会填满行高。这和stretch的行为完全相反。
面试官还会怎么问?
多行文字取的是哪一行的基线?
取第一行文字的基线。如果子项里有多行文字,浏览器只看第一行。可以用 align-self: last baseline 来让某个子项按最后一行基线对齐,但浏览器支持还不完全。
vertical-align: baseline 和 align-items: baseline 一样吗?
原理类似,都是按文字基线对齐。但 vertical-align 用在 inline 元素和 table-cell 里,align-items: baseline 用在 flex 容器里。两者的上下文不同,不能互换。
Grid 布局里也能用 baseline 对齐吗?
可以。Grid 的 align-items: baseline 让同一行里的子项按基线对齐。用法和 flex 一样,只是作用在 Grid 的行轨道内。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。