zoukankan      html  css  js  c++  java
  • 震惊!很多人都不知道 CSS Grid 框架早就有了!

    前言

    写作本文起源于知乎的一个问题:【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 属性的特殊性也决定了不可能也不应该只是单纯的叠加组合类名。

  • 相关阅读:
    【leetcode】1630. Arithmetic Subarrays
    【leetcode】1629. Slowest Key
    【leetcode】1624. Largest Substring Between Two Equal Characters
    【leetcode】1620. Coordinate With Maximum Network Quality
    【leetcode】1619. Mean of Array After Removing Some Elements
    【leetcode】1609. Even Odd Tree
    【leetcode】1608. Special Array With X Elements Greater Than or Equal X
    【leetcode】1603. Design Parking System
    【leetcode】1598. Crawler Log Folder
    Java基础加强总结(三)——代理(Proxy)Java实现Ip代理池
  • 原文地址:https://www.cnblogs.com/nzbin/p/13753147.html
Copyright © 2011-2022 走看看