【譯】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。 咱們應該同時學習它們,並使用它們
相關文章
相關標籤/搜索