CSS Grid VS Flexbox:实例对比


不久以前,所有 HTML 页面的布局还都是通过 tables、floats 以及其他的 CSS 属性来完成的。面对复杂页面的布局,却没有很好的办法。

然而 Flexbox 的出现,便轻松的解决了复杂的 Web 布局。它是一种专注于创建稳定的响应式页面的布局模式,并可以轻松地正确对齐元素及其内容。如今已是大多数 Web 开发人员首选的 CSS 布局方式。

现在,又出现了一个构建 HTML 最佳布局体系的新竞争者。(冠军头衔正在争夺中…)它就是强大的 CSS Grid 布局。直到本月月底,它也将在 Firefox 52 Chrome 57 上得到原生支持,相信不久也会得到其他浏览器兼容性的支持。

基本布局测试

要了解这两个体系构建布局的方式,我们将通过相同的 HTML 页面,利用不同的布局方式 (即 Flexbox 与 CSS Grid)为大家区分。

同时,你也可以通过文章顶部附近的下载按钮,下载演示项目进行对比,或者通过在线演示来察看它们:

简版静态页面布局

该页面的设计相对比较简单 – 它是由一个居中的容器组成,在其内部则包含了标头、主要内容部分、侧边栏和页脚。接下来,我们要完成同时保持 CSS 和 HTML 尽可能整洁的挑战事项:

  1. 在布局中将四个主要的部分进行定位。
  2. 将页面变为响应式页面;
  3. 对齐标头:导航朝左对齐,按钮向右对齐。

如你所见,为了便于比较,我们将所有事项从简处理。那么,让我们从第一个挑战事项开始吧!

挑战 1:定位页面部分

Flexbox 解决方案

我们将从 Flexbox 解决方案开始。我们将为容器添加display: flex来指定为 Flex 布局,并指定子元素的垂直方向。

.container {
    display: flex;
    flex-direction: column;
}

现在我们需要使主要内容部分和侧边栏彼此相邻。由于 Flex 容器通常是单向的,所以我们需要添加一个包装器元素。

<header></header>
<div class="main-and-sidebar-wrapper">
    <section class="main"></section>
    <aside class="sidebar"></aside>
</div>
<footer></footer>

然后,我们给包装器在反向添加display: flexflex-direction属性。

.main-and-sidebar-wrapper {
    display: flex;
    flex-direction: row;
}

最后一步,我们将设置主要内容部分与侧边栏的大小。通过 Flex 实现后,主要内容部分会比侧边栏大三倍。

.main {
    flex: 3;
    margin-right: 60px;
}
.sidebar {
   flex: 1;
}

如你所见,Flex 将其很好的实现了出来,但是仍需要相当多的 CSS 属性,并借助了额外的 HTML 元素。那么,让我们看看 CSS Grid 如何实现的。

CSS Grid 解决方案

针对本项目,有几种不同的 CSS Grid 解决方法,但是我们将使用网格模板区域语法来实现,因为它似乎最适合我们要完成的工作。

首先,我们将定义四个网格区域,所有的页面各一个:

<header></header>
<!-- Notice there isn't a wrapper this time -->
<section class="main"></section>
<aside class="sidebar"></aside>
<footer></footer>
header {
    grid-area: header;
}
.main {
    grid-area: main;
}
.sidebar {
    grid-area: sidebar;
}
footer {
    grid-area: footer;
}

然后,我们会设置网格并分配每个区域的位置。初次接触 Grid 布局的朋友,可能感觉以下的代码会有些复杂,但当你了解了网格体系,就很容易掌握了。

.container {
    display: grid;

    /*  Define the size and number of columns in our grid. 
    The fr unit works similar to flex:
    fr columns will share the free space in the row in proportion to their value.
    We will have 2 columns - the first will be 3x the size of the second.  */
    grid-template-columns: 3fr 1fr;

    /*  Assign the grid areas we did earlier to specific places on the grid. 
        First row is all header.
        Second row is shared between main and sidebar.
        Last row is all footer.  */
    grid-template-areas: 
        "header header"
        "main sidebar"
        "footer footer";

    /*  The gutters between each grid cell will be 60 pixels. */
    grid-gap: 60px;
}

就是这样! 我们现在将遵循上述结构进行布局,甚至不需要我们处理任何的 margins 或 paddings 。

挑战 2:将页面变为响应式页面

Flexbox 解决方案

这一步的执行与上一步密切相关。对于 Flexbox 解决方案,我们将更改包装器的flex-direction属性,并调整一些 margins。

@media (max-width: 600px) {
    .main-and-sidebar-wrapper {
        flex-direction: column;
    }

    .main {
        margin-right: 0;
        margin-bottom: 60px;
    }
}

由于网页比较简单,所以我们在媒体查询上不需要太多的重写。但是,如果遇见更为复杂的布局,那么将会重新的定义相当多的内容。

CSS Grid 解决方案

由于我们已经定义了网格区域,所以我们只需要在媒体查询中重新排序它们。 我们可以使用相同的列设置。

@media (max-width: 600px) {
    .container {
    /*  Realign the grid areas for a mobile layout. */
        grid-template-areas: 
            "header header"
            "main main"
            "sidebar sidebar"
            "footer footer";
    }
}

或者,我们可以从头开始重新定义整个布局。

@media (max-width: 600px) {
    .container {
        /*  Redefine the grid into a single column layout. */
        grid-template-columns: 1fr;
        grid-template-areas: 
            "header"
            "main"
            "sidebar"
            "footer";
    }
}

挑战 3:对齐标头组件

Flexbox 解决方案

我们的标头包含了导航和一个按钮的相关链接。我们希望导航朝左对齐,按钮向右对齐。而导航中的链接务必正确对齐,且彼此相邻。

<header>
    <nav>
        <li><a href="#"><h1>Logo</h1></a></li>
        <li><a href="#">Link</a></li>
        <li><a href="#">Link</a></li>
    </nav>
    <button>Button</button>
</header>

我们曾在一篇较早的文章中使用 Flexbox 做了类似的布局:响应式标头最简单的制作方法。这个技术很简单:

header {
    display: flex;
    justify-content: space-between;
}

现在导航列表和按钮已正确对齐。下来我们将使<nav>内的 items 进行水平移动。这里最简单的方法就是使用display:inline-block属性,但目前我们需要使用一个 Flexbox 解决方案:

header nav {
    display: flex;
    align-items: baseline;
}

仅两行代码就搞定了! 还不错吧。接下来让我们看看如何使用 CSS Grid 解决它。

CSS Grid 解决方案

为了拆分导航和按钮,我们要为标头定义display: grid属性,并设置一个 2 列的网格。同时,我们还需要两行额外的 CSS 代码,将它们定位在相应的边界上。

header{
    display: grid;
    grid-template-columns: 1fr 1fr;
}
header nav {
    justify-self: start;
}
header button {
    justify-self: end;
}

至于导航中的内链 - 这是我们使用 CSS grid 最好的布局展示:

虽然链接为内链形式,但它们不能正确的对齐。由于 CSS grid 不具备基线选项(不像 Flexbox 具备的align-items属性),所以我们只能再定义一个子网格。

header nav {
    display: grid;
    grid-template-columns: auto 1fr 1fr;
    align-items: end; 
}

CSS grid 在此步骤中,存在一些明显的布局上的缺陷。但你也不必过于惊讶。因为它的目标是对齐容器,而不是内部的内容。所以,用它来处理收尾工作,或许不是很好的选择哦。

结论

如果你已经浏览完整篇文章,那么结论不会让你感到意外。事实上,并不存在最好的布局方式。Flexbox 和 CSS grid 是两种不同的布局形式,我们应该根据具体的场景将它们搭配使用,而不是相互替代。

对于那些跳过文章只想看结论的朋友(不用担心,我们也这样做),这里是通过实例比较后的总结:

  1. CSS grids 适用于布局大画面。它们使页面的布局变得非常容易,甚至可以处理一些不规则和非对称的设计。
  2. Flexbox 非常适合对齐元素内的内容。你可以使用 Flex 来定位设计上一些较小的细节。
  3. 2D 布局适合使用 CSS grids(行与列)。
  4. Flexbox 适用于单一维度的布局(行或列)。
  5. 共同学习并使用它们。

感谢你的阅读。若你有所收获,欢迎点赞与分享。

注:

  1. 本文版权归原作者所有,仅用于学习与交流。
  2. 如需转载译文,烦请按下方注明出处信息,谢谢!

英文原文:CSS Grid VS Flexbox: A Practical Comparison
作者:Danny Markov
译者:IT程序狮
译文地址:http://www.jianshu.com/p/6262c3e48443

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,737评论 1 92
  • 简介 CSS Grid布局 (又名"网格"),是一个基于二维网格布局的系统,旨在改变我们基于网格设计的用户界面方式...
    咕咚咚bells阅读 2,488评论 0 4
  • 选择qi:是表达式 标签选择器 类选择器 属性选择器 继承属性: color,font,text-align,li...
    wzhiq896阅读 1,733评论 0 2
  • 选择qi:是表达式 标签选择器 类选择器 属性选择器 继承属性: color,font,text-align,li...
    love2013阅读 2,306评论 0 11
  • 三岁的时候,你因为不听妈妈的话,爬上桌子打翻了一个热水瓶。妈妈吓的呆若木鸡,好半天才反应过来抱着你大哭。你看着妈妈...
    小妖的浅时光阅读 374评论 0 1