【译】Css Grid VS Flexbox: 实践比较

原文:CSS Grid VS Flexbox: A Practical Comparison 做者:Danny Markovcss

在不久前,全部 HTML 页面的布局都是经过tablefloat和其余 CSS 属性来完成的,但其实这些属性并不适合设计复杂的网页。html

紧接着,出现了flexbox ——一种专门为建立强大的响应式页面而设计的布局模式。 使得元素和内容的正确对齐变得很容易,如今是大多数网页开发者首选的 CSS 系统。web

如今咱们有了一个“构建 html 布局最佳系统奖杯”的新竞争者——这就是强大的CSS Grid,到本月底,它将在 Firefox 52和  Chrome 57中发布,其余浏览器(但愿如此)也会很快跟进。浏览器

基本布局测试

为了了解使用每一个系统构建布局是什么感受,咱们对同一个 HTML 页面构建了两次 -- 一次是使用 flexbox,另外一次是使用CSS Grid。 您能够从原文文章顶部附近的下载按钮下载这两个项目,或者在这个在线演示中查看它们:bash

剥离式静态页面布局

这个设计很是简单——它由一个居中的容器组成,其中包含一个头部、主要部分、侧边栏和一个页脚。 下面是咱们必须解决的主要"挑战",同时尽量保持 CSS 和 HTML 的干净:app

  1. 布局四个主要部分
  2. 响应式布局(在屏幕较小的状况下侧边栏位于主要内容的下方)
  3. 将标题导航的内容对齐到左侧,按钮对齐到右侧

正如你所看到的,为了便于比较,咱们把一切都写的尽量简单。 让咱们从第一个问题开始。ide

挑战1: 定位页面部分

Flexbox 方案

咱们从 flexbox 方案开始。 咱们将 display: flex添加到容器并将其子容器垂直定向。 这会让全部模块一个接一个地往下放。布局

.container {
    display: flex;
    flex-direction: column;
}
复制代码

如今咱们须要让主要部分和侧边栏挨着放。 因为 flex 容器一般是单向的,所以咱们须要添加一个wrapper元素。学习

<div class="main-and-sidebar-wrapper">
    <section class="main"></section>
    <aside class="sidebar"></aside>
</div>
<footer></footer>
复制代码

而后咱们设置包裹层(wrapper)的display为:flex 而且flex-direction设置为相反的方向。测试

.main-and-sidebar-wrapper {
    display: flex;
    flex-direction: row;
}
复制代码

最后一步是设置主要部分和边栏的大小。 咱们但愿主要内容是侧边栏大小的三倍,这对 flex 或百分比来讲并不困难。

.main {
    flex: 3;
    margin-right: 60px;
}
.sidebar {
   flex: 1;
}
复制代码

你能够看到 flexbox 已经作得很好了,但咱们仍然须要至关多的 CSS 属性 + 一个额外的 HTML 元素。 让咱们看看 CSS 网格是如何工做的。

CSS Grid 方案

使用 CSS Grid有几种不一样的方法,咱们将使用grid-template-areas,对于当下咱们要完成的工做来讲,它彷佛是最适合的。

首先,咱们将定义四个grid-area,每一个网格区域一个:

<!-- 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;
}
复制代码

就是这样! 布局如今遵循开头所说的结构,如今甚至不须要处理任何边缘或填充。

挑战2: 让页面响应迅速

Flexbox 方案

此步骤的执行与前一个步骤紧密相连。 对于 flexbox 解决方案,咱们将不得不改变wrapper的flex-direction ,并调整一些边距。

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

    .main {
        margin-right: 0;
        margin-bottom: 60px;
    }
}
复制代码

页面真的很简单,因此在媒体查询中没有太多须要修改的地方,可是在一个更复杂的布局中,将会有不少不少的东西须要从新定义。

CSS Grid 方案

由于咱们已经定义了grid-areas ,如今只须要在媒体查询中对它们进行从新排序。咱们可使用相同的列设置。

@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>
复制代码

在一篇旧文章The Easiest Way To Make Responsive Headers中,咱们已经使用flexbox作了一个相似的布局,这个技巧很是简单:

header {
    display: flex;
    justify-content: space-between;
}
复制代码

如今导航列表和按钮正确对齐。 剩下的就是让<nav> 中的项水平居中。 在这里使用 display: inline-block 是最简单的,可是既然咱们要使用彻底 flexbox,那么让咱们应用一个flexbox-only解决方案:

header nav {
    display: flex;
    align-items: baseline;
}
复制代码

只有两行! 一点也不差。 接下来让咱们看看 CSS Grid是如何处理它的。

CSS Grid 方案

为了分割导航和按钮,咱们必须设置header为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-header.png

这些连接是内联的,可是它们不能正确对齐,由于没有像 flexbox 的 align-items 那样的baseline选项。 咱们还必须定义另外一个子网格。

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

很明显,CSS grid在布局的这一部分遇到了困难,但这并不奇怪——它的重点是调整容器,而不是容器内的内容。

总结

若是你已经读完了整篇文章,这个结论对你来讲并不意外。 事实上是,没有一个最优的解决方案--flexboxCSS Grid擅长的东西不一样,决定了使用场景不一样,它们应该一块儿被使用,而不是做为竞争对手。

对于那些直接跳到文章结论的人(不用担忧,我也常常这样作)),这里有一个全文比较结论的摘要:

  • CSS grids对于构建更大的图片很是有用。 它们使管理页面布局变得很是容易,甚至能够处理更多非传统和不对称的设计
  • Flexbox 很是擅长对齐元素内容,它能够用来定位设计中较小的细节
  • 使用 CSS grids进行2D 布局(行和列)
  • Flexbox只在一个维度时(行或列)工做得更好
  • 没有理由只使用CSS grids或只使用 flexbox。 咱们应该同时学习它们,并使用它们
相关文章
相关标签/搜索