前言

写作本文起源于知乎的一个问题:【CSS Grid 布局那么好,为什么至今没有人开发出基于 Grid 布局的前端框架呢?

这篇文章拖沓了两个月,是因为真的不知道从哪里说好。这个问题的所有回答几乎都没有切中问题的本质,而且对 CSS Grid 也有很深的误解。另外这个问题的描述可能不太恰当,因为基于 CSS Grid 的框架已经有了。感兴趣的朋友可以了解一下 Flex-Layout,它是一个基于指令布局的神器。大家不要被项目名误导,虽然叫 flex-layout,其实有 flexgrid 两种指令。

我觉得这个问题更恰当的描述应该是【为什么没有基于 Grid 布局的纯 CSS 前端框架呢】,基于 Float 和 Flex 的 CSS 布局框架多如牛毛,但是一直没看到基于 CSS Grid 的实现。我在写 Snack 的时候也曾考虑过在 v3 版本中整合 CSS Grid,但是后来发现有些不现实,下文详述。据说 Bootstrap 也曾打算在 v5 版本整合 CSS Grid,但是目前来看依然沿用了 Flex 布局。我个人觉得基于指令实现的 flex-layout 应该是整合 CSS Grid 的最佳方式。

本文打算从相反的角度聊一聊,假如要实现一个基于 CSS Grid 的布局框架,我们会遇到哪些问题呢?

浏览器兼容性

先说一下兼容性,很多人总觉得 CSS Grid 的兼容性不行。其实不然,下图的统计数据能够看出大部分浏览器对 CSS Grid 的支持还是不错的,要知道 Flex 在 IE10 上面可以使用的属性也非常有限。据统计目前 CSS Grid 使用率和 Flex 已经基本持平了。所以兼容性并不能回答开篇提出的问题。

CSS 布局框架的特点

CSS 布局主要有四种,上古时期用的是 table,这个就不说了,我们只讨论新世纪常用的 Float、Flex、Grid。这三种布局方式就是递进的关系,逐步加强了 CSS 布局的便利性。CSS 布局的最佳实践当属 Bootstrap,其中 Float 和 Flex 布局方案都已经被 Bootstrap 实现,唯独 Grid 方案迟迟不见踪影。

CSS 布局框架的关键在于如何设计栅格,我们先看看在 Bootstrap 中是怎么进行布局的。

<div class="row">
<div class="col-md-1">.col-md-1</div>
<div class="col-md-1">.col-md-1</div>
<div class="col-md-1">.col-md-1</div>
<div class="col-md-1">.col-md-1</div>
<div class="col-md-1">.col-md-1</div>
<div class="col-md-1">.col-md-1</div>
<div class="col-md-1">.col-md-1</div>
<div class="col-md-1">.col-md-1</div>
<div class="col-md-1">.col-md-1</div>
<div class="col-md-1">.col-md-1</div>
<div class="col-md-1">.col-md-1</div>
<div class="col-md-1">.col-md-1</div>
</div>
<div class="row">
<div class="col-md-8">.col-md-8</div>
<div class="col-md-4">.col-md-4</div>
</div>
<div class="row">
<div class="col-md-4">.col-md-4</div>
<div class="col-md-4">.col-md-4</div>
<div class="col-md-4">.col-md-4</div>
</div>
<div class="row">
<div class="col-md-6">.col-md-6</div>
<div class="col-md-6">.col-md-6</div>
</div>

用过 Bootstrap 的人对以上结构一定不陌生。在 Bootstrap v4 中,由于 Flex 布局功能的增强,row 也可以搭配 utility 使用。

<div class="row align-items-start">
<div class="col">One of three columns</div>
<div class="col">One of three columns</div>
<div class="col">One of three columns</div>
</div>
<div class="row align-items-center">
<div class="col">One of three columns</div>
<div class="col">One of three columns</div>
<div class="col">One of three columns</div>
</div>
<div class="row align-items-end">
<div class="col">One of three columns</div>
<div class="col">One of three columns</div>
<div class="col">One of three columns</div>
</div>

rowcol 的组合几乎已经成为栅格布局的共识和标准。接下来我们就用这种设计方式手撕一个 Grid 栅格看看效果。

手撕 CSS 布局栅格

其实手撕一个 CSS 布局栅格并不难,关键是要熟悉预处理器的循环功能。下面我们分别用 Float、Flex 及 Grid 实现一个简化版的栅格布局并对比一下它们之间的差异。

Float

Float 是过去实现流体布局的唯一方式,难点在于处理父元素的塌陷,这算是一个老生常谈的问题了,本文不再赘述。以下是一个简易版的 Float 栅格:

See the Pen float-columns by Zongbin (@nzbin)
on CodePen.

这种栅格简单实用,堪称经典。但是 Float 布局的局限性很大,如果栅格的高度不相同(比如将第一个栅格的高度加高),布局就会出现塌陷。

Flex

Flex 的诞生几乎解决了 Float 栅格的所有痛点,比如上面提到的塌陷问题。以下是一个简易版的 Flex 栅格:

See the Pen flex-columns by Zongbin (@nzbin)
on CodePen.

其实在一维布局中,Flex 已经足够好用,至少在流体布局中没发现需要改进的地方,所以我们是否还有必要引入二维布局方案?

Grid

重点来了!重点来了!重点来了!

Grid 是比 Flex 更高级的布局技术,所以单纯替换 Flex 实现一套栅格布局系统完全没有问题。以下是一个极其简易的 Grid 栅格,几乎和 Flex 栅格的效果没有区别。

See the Pen grid-columns by Zongbin (@nzbin)
on CodePen.

Grid 除了能实现 Flex 的布局之外,还可以在纵向空间对每一行进行调整(比如设置 grid-template-rows: 1fr 2fr)。另外,Grid 设置其它列数的栅格也比较容易,比如设置 10 列栅格,只需要设置 grid-template-columns: repeat(10, 1fr) 即可;如果是 Flex,则需要重新计算栅格的宽度。

上面示例中展示的 CSS Grid 的功能只是冰山一角。作为一个二维布局技术,它的属性写法非常繁杂,比如另外一个强大的功能 grid-template-areas MDN Demos。这种属性定义方式很难使用类名的叠加组合实现对应的功能。

如果只是简单地将 Flex 栅格替换成 Grid 栅格,我个人感觉意义不大,一个基于 CSS Grid 全新的栅格系统应该尽可能的发挥它所有的优势。这或许就是 CSS Grid 栅格系统迟迟没有出现的原因吧。我不知道文章写到这里是否清楚的表达了我的观点,或者说能否解答大家对于开篇问题的疑惑。接下来再看看 flex-layout 中的 Grid。

Flex-Layout 中的 Grid

因为 flex-layout 是基于指令的实现,所以不像类名叠加的方式那样有很大的局限性,几乎可以发挥 CSS Grid 的全部优势。以下就是 grid-template-areas 的定义方法。

<div gdAreas.xs="header | sidebar | content | sidebar2 | footer" gdGap="1em"
gdColumns.xs="none"
gdAreas.sm="header header | sidebar content | sidebar2 sidebar2 | footer footer"
gdColumns.sm="20%!"
gdAreas.gt-sm="header header header | sidebar content sidebar2 | footer footer footer"
gdColumns.gt-sm="120px auto 120px" gdGap.gt-sm="20px" [ngStyle]="{'max-width': 'auto'}"
[ngStyle.gt-sm]="{'max-width': '600px'}">
<div class="blocks one" gdArea="header">Header</div>
<div class="blocks two" gdArea="sidebar">Sidebar</div>
<div class="blocks three" gdArea="sidebar2">Sidebar 2</div>
<div class="blocks four" gdArea="content">Content
<br /> More content than we had before so this column is now quite tall.</div>
<div class="blocks five" gdArea="footer">Footer</div>
</div>

flex-layout 无论是设计思路还是实现方式都让我顶礼膜拜,它与传统的 Bootstrap 形式的栅格有着本质区别。本文的重点不是介绍 flex-layout,如果大家感兴趣,还是看官网介绍吧 Flex-Layout

总结

酝酿了两个月个文章,感觉还是没有把自己的观点表达清楚。回到问题本身,【为什么没有基于 Grid 布局的纯 CSS 前端框架呢】,个人觉得最主要的还是传统写法无法发挥 CSS Grid 的全部优势,至少用以往的类叠加方式是无法做到的。CSS Grid 属性的特殊性也决定了不可能也不应该只是单纯的叠加类名。

震惊!很多人都不知道 CSS Grid 框架早就有了!的更多相关文章

  1. 很多人都在埋怨没有遇到好的团队,但好的团队不可能凭空出现,一流的团队不能仅靠团队成员努力,作为Leader,要有可行的规划,并坚定地执行、时势地调整(转)

    <西游记>中的唐僧团队历经千难万险,终于求得真经,目标明确.分工合理为这支队伍最终走向成功奠定了基础.唐僧从一开始,就为这个团队设定了西天取经的目标,虽然经历各种挫折与磨难,但目标从未动摇 ...

  2. 上传伪技术~很多人都以为判断了后缀,判断了ContentType,判断了头文件就真的安全了。是吗?

    今天群里有人聊图片上传,简单说下自己的经验(大牛勿喷) 0.如果你的方法里面是有指定路径的,记得一定要过滤../,比如你把 aa文件夹设置了权限,一些类似于exe,asp,php之类的文件不能执行,那 ...

  3. [转帖](区块链补习班)ERC20很多人都听过,但ERC是什么你真的了解吗?

    (区块链补习班)ERC20很多人都听过,但ERC是什么你真的了解吗? http://baijiahao.baidu.com/s?id=1600948969290990883&wfr=spide ...

  4. 这个 Spring 循环依赖的坑,90% 以上的人都不知道

    1. 前言 这两天工作遇到了一个挺有意思的Spring循环依赖的问题,但是这个和以往遇到的循环依赖问题都不太一样,隐藏的相当隐蔽,网络上也很少看到有其他人遇到类似的问题.这里权且称他非典型Spring ...

  5. 听说特斯拉花了4个月研发出新ERP,然后很多人都疯了

    欢迎关注微信公众号:sap_gui (ERP咨询顾问之家) 最近这件事儿在SAP圈里炒的挺火的,最主要是因为这几个关键词: 放弃SAP.4个月.自研ERP: 这则新闻一出来,很多人都兴高采烈,都要疯了 ...

  6. 很多人都搞不清楚C语言和C++的关系!今天我们来一探究竟为大家解惑~

    最近,身边有许多小伙伴已经开始学习编程了,但是呢,学习又会碰到许多的问题,其中作为新手小白提到最多的问题就是编程语言的选择. 每次遇到这种问题,看起来很简单,但是又有很多小伙伴搞不清编程语言之间的关系 ...

  7. 一道月薪3W的java面试题 (小明和小强都是张老师的学生,张老师的生日是某月某日,2人都不知道张老师的生日)

    小明和小强都是张老师的学生,张老师的生日是M月N日,2人都知道张老师的生日 是下列10组中的一天,张老师把M值告诉了小明,把N值告诉了小强,张老师问他们知道他的生日是那一天吗? 3月4日 3月5日 3 ...

  8. 7个现在就该学习Python 的理由【80%的人都不知道】

    Python 是一门更注重可读性和效率的语言,尤其是相较于 Java,PHP 以及 C++ 这样的语言,它的这两个优势让其在开发者中大受欢迎. 诚然,它有点老了,但仍是 80 后啊 —— 至少没有 C ...

  9. 原来现在很多人都用SignalR来实现Chat Room

    今天从一个业余开发的群里,看到有人要求这样一个项目需求: 1,)学员可以通过在线课堂找到自己喜欢的老师和课程. 2,)每个人可以建立自己课堂,每个课堂扣分多个子房间,交流群.设置管理员:有录音功能,可 ...

随机推荐

  1. python数据结构之图深度优先和广度优先实例详解

    本文实例讲述了python数据结构之图深度优先和广度优先用法.分享给大家供大家参考.具体如下: 首先有一个概念:回溯 回溯法(探索与回溯法)是一种选优搜索法,按选优条件向前搜索,以达到目标.但当探索到 ...

  2. c++ 中. 和 ->,波浪号 ~ 符号怎么用 ————很重要

    参考:https://www.cnblogs.com/Simulation-Campus/p/8809999.html 1.  用在类中的析构函数之前,表示该函数是析构函数.如类A的析构函数 clas ...

  3. Docker镜像仓库Harbor部署

    一.Harbor组件 组件 功能 harbor-adminserver 配置管理中心 harbor-db Mysql数据库 harbor-jobservice 负责镜像复制 harbor-log 记录 ...

  4. [学习笔记] 数位DP的dfs写法

    跟着洛谷日报走,算法习题全都有! 嗯,没错,这次我也是看了洛谷日报的第84期才学会这种算法的,也感谢Mathison大佬,素不相识,却写了一长篇文章来帮助我学习这个算法. 算法思路: 感觉dfs版的数 ...

  5. shell-变量的数值运算符-计算双括号(())的使用

    1. 变量的数值计算 变量的数值计算常见的如下几个命令: (()).let.expr.bc.$[]  1) (())用法:(此法很常用,且效率高) 执行简单的整数运算,只需将特定的算术表达式用 &qu ...

  6. 网站搭建-云服务器是什么-云服务器ECS是什么

    学习上瘾了,本博客关闭,后期再总结整理.

  7. linux CentOS7 防火墙操作

    1, 查看防火墙状态: firewall-cmd --state systemctl status firewalld.service 2, 开启防火墙: systemctl start firewa ...

  8. turtle库元素语法分析

    一.turtle原理理解: turtle库是Python中一个有趣的图形绘制函数库.原名(海龟),我们想象一只海龟,位于显示器上窗体的正中心,在画布上游走,它游走的轨迹就形成了绘制的图形. 对于小海龟 ...

  9. 多测师讲解 自动化测试理论(1)_高级讲师肖sir

    自动化测试理论什么是自动化测试?广义的:通过工具或程序替代或辅助人工测试的行为叫自动化测试狭义的:通过工具录制或编写脚本模拟手工测试的过程,通过回放或运行脚本执行测试用例,从而代替人工对系统的功能验证 ...

  10. 第一个月多测师讲解__项目讲解以及注意事项(肖sir)

    一.目的讲解流程:(讲述业务时长10-15分钟为宜)1.自我介绍礼貌用语,姓名,籍贯,学校,个人技能,经验,表现,兴趣爱好等 ,1分钟 ,谢谢2.介绍项目的名字 ,项目的背景,(涉及什么架构)3.对项 ...