【譯】Css Grid VS Flexbox: 實踐比較

原文:CSS Grid VS Flexbox: A Practical Comparison
作者:Danny Markov

在不久前,所有 HTML 頁面的布局都是通過tablefloat和其他 CSS 屬性來完成的,但其實這些屬性并不適合設計復雜的網(wǎng)頁。

緊接著,出現(xiàn)了flexbox ——一種專門為創(chuàng)建強大的響應式頁面而設計的布局模式。 使得元素和內(nèi)容的正確對齊變得很容易,現(xiàn)在是大多數(shù)網(wǎng)頁開發(fā)者首選的 CSS 系統(tǒng)。

現(xiàn)在我們有了一個“構(gòu)建 html 布局最佳系統(tǒng)獎杯”的新競爭者——這就是強大的CSS Grid,到本月底,它將在 Firefox 52Chrome 57中發(fā)布,其他瀏覽器(希望如此)也會很快跟進。

基本布局測試

為了了解使用每個系統(tǒng)構(gòu)建布局是什么感覺,我們對同一個 HTML 頁面構(gòu)建了兩次 -- 一次是使用 flexbox,另一次是使用CSS Grid。 您可以從原文文章頂部附近的下載按鈕下載這兩個項目,或者在這個在線演示中查看它們:

這個設計非常簡單——它由一個居中的容器組成,其中包含一個頭部、主要部分、側(cè)邊欄和一個頁腳。 下面是我們必須解決的主要"挑戰(zhàn)",同時盡可能保持 CSS 和 HTML 的干凈:

  1. 布局四個主要部分
  2. 響應式布局(在屏幕較小的情況下側(cè)邊欄位于主要內(nèi)容的下方)
  3. 將標題導航的內(nèi)容對齊到左側(cè),按鈕對齊到右側(cè)

正如你所看到的,為了便于比較,我們把一切都寫的盡可能簡單。 讓我們從第一個問題開始。

挑戰(zhàn)1: 定位頁面部分

Flexbox 方案

我們從 flexbox 方案開始。 我們將 display: flex添加到容器并將其子容器垂直定向。 這會讓所有模塊一個接一個地往下放。

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

現(xiàn)在我們需要讓主要部分和側(cè)邊欄挨著放。 由于 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;
}

最后一步是設置主要部分和邊欄的大小。 我們希望主要內(nèi)容是側(cè)邊欄大小的三倍,這對 flex 或百分比來說并不困難。

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

你可以看到 flexbox 已經(jīng)做得很好了,但我們?nèi)匀恍枰喈敹嗟?CSS 屬性 + 一個額外的 HTML 元素。 讓我們看看 CSS 網(wǎng)格是如何工作的。

CSS Grid 方案

使用 CSS Grid有幾種不同的方法,我們將使用grid-template-areas,對于當下我們要完成的工作來說,它似乎是最適合的。

首先,我們將定義四個grid-area,每個網(wǎng)格區(qū)域一個:

<!-- 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,并分配每個區(qū)域的位置。

下面的代碼一開始可能看起來相當復雜,但是一旦了解了網(wǎng)格系統(tǒng),就很容易理解了。

.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;
}

就是這樣! 布局現(xiàn)在遵循開頭所說的結(jié)構(gòu),現(xiàn)在甚至不需要處理任何邊緣或填充。

挑戰(zhàn)2: 讓頁面響應迅速

Flexbox 方案

此步驟的執(zhí)行與前一個步驟緊密相連。 對于 flexbox 解決方案,我們將不得不改變wrapper的flex-direction ,并調(diào)整一些邊距。

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

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

頁面真的很簡單,所以在媒體查詢中沒有太多需要修改的地方,但是在一個更復雜的布局中,將會有很多很多的東西需要重新定義。

CSS Grid 方案

因為我們已經(jīng)定義了grid-areas ,現(xiàn)在只需要在媒體查詢中對它們進行重新排序。我們可以使用相同的列設置。

@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";
    }
}

挑戰(zhàn)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中,我們已經(jīng)使用flexbox做了一個類似的布局,這個技巧非常簡單:

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

現(xiàn)在導航列表和按鈕正確對齊。 剩下的就是讓<nav> 中的項水平居中。 在這里使用 display: inline-block 是最簡單的,但是既然我們要使用完全 flexbox,那么讓我們應用一個flexbox-only解決方案:

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

只有兩行! 一點也不差。 接下來讓我們看看 CSS Grid是如何處理它的。

CSS Grid 方案

為了分割導航和按鈕,我們必須設置header為display: grid ,并設置一個2列的網(wǎng)格。 另外還需要兩行額外的 CSS 來定位它們在各自的邊界上。

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

至于導航中的內(nèi)聯(lián)鏈接--其實我們使用css grid是無法非常精準實現(xiàn)的。 以下是我們的最佳嘗試:

css-grid-header.png

這些鏈接是內(nèi)聯(lián)的,但是它們不能正確對齊,因為沒有像 flexbox 的 align-items 那樣的baseline選項。 我們還必須定義另一個子網(wǎng)格。

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

很明顯,CSS grid在布局的這一部分遇到了困難,但這并不奇怪——它的重點是調(diào)整容器,而不是容器內(nèi)的內(nèi)容。

總結(jié)

如果你已經(jīng)讀完了整篇文章,這個結(jié)論對你來說并不意外。 事實上是,沒有一個最優(yōu)的解決方案--flexboxCSS Grid擅長的東西不同,決定了使用場景不同,它們應該一起被使用,而不是作為競爭對手。

對于那些直接跳到文章結(jié)論的人(不用擔心,我也經(jīng)常這樣做)),這里有一個全文比較結(jié)論的摘要:

  • CSS grids對于構(gòu)建更大的圖片非常有用。 它們使管理頁面布局變得非常容易,甚至可以處理更多非傳統(tǒng)和不對稱的設計
  • Flexbox 非常擅長對齊元素內(nèi)容,它可以用來定位設計中較小的細節(jié)
  • 使用 CSS grids進行2D 布局(行和列)
  • Flexbox只在一個維度時(行或列)工作得更好
  • 沒有理由只使用CSS grids或只使用 flexbox。 我們應該同時學習它們,并使用它們
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標簽默認的外補...
    _Yfling閱讀 14,199評論 1 92
  • DEMO 地址:【傳送門】 示例下載地址: 【傳送門】 不久以前,所有 HTML 頁面的布局還都是通過 table...
    IT程序獅閱讀 10,652評論 3 47
  • 本文譯自 A Complete Guide to Flexbox這里,針對本文介紹的屬性列個提綱:伸縮容器屬性: ...
    evelynlab閱讀 718評論 0 2
  • 人性的弱點在于自私,于己于他人,想來都有弊端??捎窒胧|蕓眾生如果能摒棄之,現(xiàn)今又哪來如此多的故事?哪來如此多的萬古談資?
    謝飄同學閱讀 273評論 0 0
  • 音樂,圖片承載了我的回憶。 一張圖,能讓我回憶幾年前的某次聚會。一首歌,能讓我想起第一次聽到這首歌時我身在何處,在...
    苦瓜粉第三代閱讀 177評論 0 0

友情鏈接更多精彩內(nèi)容