上一期我们扒掉了 CSS 的外衣,聊了 HTML 的语义化。今天我们穿上衣服,但这一次,我们要穿得体面,可不能乱穿呢是吧,这可关乎着整体的形象呢,给人的第一感觉。
回想一下,在你刚入行(或者还在石器时代徘徊)的时候,为了把一个 div 垂直居中,你祭献了多少根头发?是用 padding 瞎凑?还是用 position: absolute 配合 transform 各种硬算?亦或是那个让无数人做噩梦的 float: left 加上 .clearfix 补丁?
CSS 的布局进化史,其实就是一部人类摆脱"流体文档"束缚的抗争史:
Table (石器时代) -> Float (青铜时代) -> Position/Inline-block (白铁时代) -> Flex/Grid (现代黄金时代)。
今天,我们把旧时代的"奇技淫巧"统统扔进垃圾桶,只谈现代布局的"绝代双骄" :Flexbox 和 Grid。
一、Flexbox ------ 灵活的一维"弹力绳"
Flexbox(弹性盒子)的出现,主要是为了解决一个千古难题:怎么在一行(或一列)内,优雅地排列元素?
你可以把 Flex 容器想象成一条**"弹力绳"**,里面的子元素就是串在绳子上的珠子。
1. 核心模型:两根轴的博弈
很多朋友 Flex 用得挺溜,但两个属性摆在你面前 justify-content 和 align-items ,又懵了,干脆随便试试了,先试试这个,"诶?不行呀",好,那就那个也试试吧,"耶,成功了!"。虽然是能实现吧,但是开发效率大打折扣呢,几个地方这样测试下还好,但是一个网页下来,哪哪都试试,人家都部署到服务器运营着网站了,你还在那试试哪个行。
其实只要记住两根轴:
- 主轴 (Main Axis):珠子串连的方向(默认是从左到右)。
- 交叉轴 (Cross Axis):和主轴垂直的方向(默认是从上到下)。
2. 那个让后端开发都感动的"万能居中"
在 Flex 出现之前,垂直居中是 CSS 届的玄学。现在,只需要三行代码:
css
.parent {
display: flex; /* 默认主轴是横向,也就是容器里的小容器或小块横向排列 */
justify-content: center; /* 主轴:左右居中,横向局中 */
align-items: center; /* 交叉轴:上下居中,纵向局中 */
}
适用场景:各种按钮文字、弹窗中心、Loading 图标。
说个几个容易混淆的,哈哈,先来个免责声明:如果你没见过这些属性,那就可以跳过了,或者你可以带着好奇心看看,防止以后看到这些也混淆了。
-
justify-contentvsjustify-items:一句话,justify-items主要是给 Grid 用的 ,在 Flex 容器 中,它对 flex items 几乎不起作用 -
align-itemsvsvertical-align:这是个老坑,这是 CSS 面试和实际开发中最容易混淆的一组 。vertical-align它不是 Flex 的,不能随便居中 div,只对 行内元素 / 表格单元格 有效,例如:inline/inline-block;<td>表格内容;图片和文字对齐记住这个:Flex 居中用
align-items; 行内对齐才用vertical-align
3. 避坑指南:flex: 1 到底是个啥?
面试官最爱问的题:"你写了 flex: 1,它代表什么?"
千万别只说"自动填满",而是"参与分配"。它的真身是三个属性的缩写:
css
flex: 1;
/* 等同于 */
flex-grow: 1; /* 有剩余空间时,我贪婪地放大 */
flex-shrink: 1; /* 空间不够时,我委屈地缩小 */
flex-basis: 0%; /* 我的初始大小忽略不计,全靠分配 */
记忆口诀 :Grow (长胖), Shrink (减肥), Basis (基准线)。
那么不写flex : 1的时候到底是啥?
默认情况下,每个 flex item 等价于:
css
flex-grow: 0; /* 我不主动抢剩余空间 */
flex-shrink: 1; /* 空间不够时就大家挤挤吧,我可以压缩一下 */
flex-basis: auto; /* 以自身内容为基准 */
二、Grid ------ 上帝视角的二维"棋盘"
如果说 Flex 是处理线性的(一维),那 Grid(网格)就是处理平面的(二维)。
把 Grid 想象成一个 Excel 表格 或者 棋盘。你具有了上帝视角,先画好格子,然后命令元素:"你,去第二行第三列待着!"
1. 真正的降维打击:grid-template-areas
grid-template-areas(网格区域命名布局)
这是我认为 CSS 里最优雅的代码之一。你不需要写复杂的坐标,而是像画画一样写布局:
css
.container {
display: grid;
/* 定义三行布局,中间那行分为侧边栏和内容,你可以把它当成用字符串画出来的布局图 */
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
/* 定义轨道大小:fr 是"份数",自动瓜分剩余空间 */
/* 定义两列应该怎么分配,第一列是固定 200px,第二列吃掉剩余空间 */
grid-template-columns: 200px 1fr;
/* 第一行头部固定 60px,中间:撑满剩余高度,底部固定 100px */
grid-template-rows: 60px 1fr 100px;
/* 爽点:再也不用手动算 margin 了,老前端高兴地留下了眼泪 */
/* Grid 会自动帮你在行和行之间,列和列之,统一留出 20px 的"安全距离" */
gap: 20px;
}
/* 指定元素去哪里,这一步非常关键,在说:"你属于哪个区域" */
.header { grid-area: header; }
.menu { grid-area: sidebar; }
.main { grid-area: content; }
.footer { grid-area: footer; }
适用场景:整个页面的大框架、复杂的 Dashboard、不对称的艺术排版。
2. 对比说明为何高级
传统思路(老前端 PTSD)
css
.header { height: 60px }
.sidebar { float: left; width: 200px }
.main { margin-left: 220px }
.footer { clear: both }
Grid 思路(现代前端)
css
"这里是头"
"这里是侧边栏 + 内容"
"这里是底部"
你在描述布局,不是在计算布局。
最合适场景
非常明确的几种场景:
- 页面级布局(Header / Sidebar / Main / Footer)
- Dashboard
- 后台管理系统
- 结构清晰、变化不大的页面
回看一下是不是可以说 Grid 的
grid-template-areas是把"页面结构图"直接写进 CSS。
三、深度对决 ------ 我该选谁?
这是初学者甚至一些已过入门阶段使用者最纠结的地方。甚至有人问:"学会了 Grid 还需要 Flex 吗?"
答案是:必须学,它俩是互补的队友,不是竞争的对手。
我们可以通过一个"场景实验室"来对比:
1. 维度之争
- Flex 是"一维"的 :它一次只能处理一行(或一列)。虽然
flex-wrap: wrap可以换行,但换行后的每一行都是独立的,上下行之间没有对齐关系。 - Grid 是"二维"的:它同时管理行和列。元素不仅要对齐左边,还要对齐上面。
2. 控制权之争(核心区别!)
这是最本质的区别,来来来,动笔写下来了:
-
Flex 是【内容驱动 (Content-First)】:
"我有一堆大小不一的标签,请帮我排好,空间不够就挤一挤,或者换行。"
也就是说,布局是未知的,取决于内容多少。
-
Grid 是【布局驱动 (Layout-First)】:
"我已经画好了 3x3 的格子,不管在这个格子里放的是图片还是文字,它都得死死地待在那个框里。"
也就是说,布局是已知的,内容去适应格子。
3. 重叠布局
如果你想让两个元素叠在一起:
- Flex :基本做不到,还得请出
position: absolute。 - Grid :轻轻松松。只需要把两个元素指定到同一个
grid-area,配合z-index即可。
四、双子星合体(实战最佳实践)
在真实的大型项目中,我们通常采用 "Grid 制定战略,Flex 执行战术" 的组合拳。
场景还原: 一个典型的后台管理系统。
宏观架构 (Grid):
使用 Grid 划分出 Header、Sidebar、Main 三大区域。稳如泰山,不动如山。
微观组件 (Flex):
Header里的 Logo 和 用户头像?用 Flex 左右对齐。Sidebar里的菜单列表?用 Flex 垂直排列。Main里的卡片列表?如果卡片大小一致,用 Grid ;如果卡片宽度自适应,用 Flex。
css
/* 宏观:Grid 定乾坤 */
body {
display: grid;
grid-template-areas: "header" "main";
}
/* 微观:Flex 搞细节 */
.header {
display: flex; /* 让 Logo 和 导航 左右排 */
justify-content: space-between;
}
五、总结与思考
"大格局用 Grid 定框架,小细节用 Flex 排内容------Grid 制定战略,Flex 执行战术。"
也就是:
- 页面或组件的 整体布局、二维区域划分 → Grid (Grid 像冰一样,结构严谨,棱角分明)
- 区块内部的 元素排列、一维对齐 → Flex (Flexbox 像水一样,适应容器,流动自如)
掌握这两个武器,你基本上可以把设计稿上的任何布局"按在地上摩擦"。
互动思考题
"瀑布流布局((Masonry Layout))"(卡片高度不一)是如何实现的呢,有些朋友可能对这个布局有点陌生,可能没听过或者略有耳闻,那我提示你一下,解锁你的手机,打开小红书首页就知道了,这里又要澄清一下了,本人可没接小红书广哈哈。
欢迎在评论区留下你的看法,或者你在布局中遇到过的问题,我们下期见!👋