【CSS-布局】终极方案:Flexbox 与 Grid 的“降维打击”

上一期我们扒掉了 CSS 的外衣,聊了 HTML 的语义化。今天我们穿上衣服,但这一次,我们要穿得体面,可不能乱穿呢是吧,这可关乎着整体的形象呢,给人的第一感觉。

回想一下,在你刚入行(或者还在石器时代徘徊)的时候,为了把一个 div 垂直居中,你祭献了多少根头发?是用 padding 瞎凑?还是用 position: absolute 配合 transform 各种硬算?亦或是那个让无数人做噩梦的 float: left 加上 .clearfix 补丁?

CSS 的布局进化史,其实就是一部人类摆脱"流体文档"束缚的抗争史:

Table (石器时代) -> Float (青铜时代) -> Position/Inline-block (白铁时代) -> Flex/Grid (现代黄金时代)

今天,我们把旧时代的"奇技淫巧"统统扔进垃圾桶,只谈现代布局的"绝代双骄"FlexboxGrid


一、Flexbox ------ 灵活的一维"弹力绳"

Flexbox(弹性盒子)的出现,主要是为了解决一个千古难题:怎么在一行(或一列)内,优雅地排列元素?

你可以把 Flex 容器想象成一条**"弹力绳"**,里面的子元素就是串在绳子上的珠子。

1. 核心模型:两根轴的博弈

很多朋友 Flex 用得挺溜,但两个属性摆在你面前 justify-contentalign-items ,又懵了,干脆随便试试了,先试试这个,"诶?不行呀",好,那就那个也试试吧,"耶,成功了!"。虽然是能实现吧,但是开发效率大打折扣呢,几个地方这样测试下还好,但是一个网页下来,哪哪都试试,人家都部署到服务器运营着网站了,你还在那试试哪个行。

其实只要记住两根轴:

  • 主轴 (Main Axis):珠子串连的方向(默认是从左到右)。
  • 交叉轴 (Cross Axis):和主轴垂直的方向(默认是从上到下)。

2. 那个让后端开发都感动的"万能居中"

在 Flex 出现之前,垂直居中是 CSS 届的玄学。现在,只需要三行代码:

css 复制代码
.parent {
  display: flex; /* 默认主轴是横向,也就是容器里的小容器或小块横向排列 */
  justify-content: center; /* 主轴:左右居中,横向局中 */
  align-items: center;     /* 交叉轴:上下居中,纵向局中 */
}

适用场景:各种按钮文字、弹窗中心、Loading 图标。

说个几个容易混淆的,哈哈,先来个免责声明:如果你没见过这些属性,那就可以跳过了,或者你可以带着好奇心看看,防止以后看到这些也混淆了。

  • justify-content vs justify-items:一句话,justify-items 主要是给 Grid 用的 ,在 Flex 容器 中,它对 flex items 几乎不起作用

  • align-items vs vertical-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 执行战术。"

也就是:

  • 页面或组件的 整体布局、二维区域划分GridGrid 像冰一样,结构严谨,棱角分明)
  • 区块内部的 元素排列、一维对齐FlexFlexbox 像水一样,适应容器,流动自如)

掌握这两个武器,你基本上可以把设计稿上的任何布局"按在地上摩擦"。

互动思考题

"瀑布流布局((Masonry Layout))"(卡片高度不一)是如何实现的呢,有些朋友可能对这个布局有点陌生,可能没听过或者略有耳闻,那我提示你一下,解锁你的手机,打开小红书首页就知道了,这里又要澄清一下了,本人可没接小红书广哈哈。

欢迎在评论区留下你的看法,或者你在布局中遇到过的问题,我们下期见!👋

相关推荐
请叫我聪明鸭2 小时前
基于 marked.js 的扩展机制,创建一个自定义的块级容器扩展,让内容渲染为<div>标签而非默认的<p>标签
开发语言·前端·javascript·vue.js·ecmascript·marked·marked.js插件
悟能不能悟2 小时前
Gson bean getxxx,怎么才能返回给前端
java·前端
2501_944711432 小时前
前端向架构突围系列 - 工程化(五):企业级脚手架的设计与落地
前端·架构
Apex Predator2 小时前
本地库导入到nexus
java·服务器·前端
趁着年轻吃点苦2 小时前
宝塔面板部署指南
前端
0思必得02 小时前
[Web自动化] Selenium中Select元素操作方法
前端·python·selenium·自动化·html
一叶星殇2 小时前
C# .NET 如何解决跨域(CORS)
开发语言·前端·c#·.net
运筹vivo@2 小时前
攻防世界: catcat-new
前端·web安全·php
阿雄不会写代码3 小时前
Let‘s Encrypt HTTPS 证书配置指南
前端·chrome