Flexbox

2018-05-15 17:26 更新
前提: HTML 基礎 (study Introduction to HTML),和了解CSS如何工作的(study Introduction to CSS.)
目標: 學會如何使用Flexbox布局系統(tǒng)來創(chuàng)建Web布局。

為什么是 Flexbox?

長久以來,唯一可用的且有穩(wěn)定的跨瀏覽器兼容性的能用來構(gòu)建 CSS 布局的工具只有?floats?和?positioning。它們是即可行也不錯,但是在某些方面就有著限制,也難搞。

以下簡單的布局要求是難以或不可能用這樣的工具方便且靈活的實現(xiàn):

  • 垂直居中父內(nèi)容的里一塊內(nèi)容。
  • 使容器的所有子項占用等量的可用寬度/高度,而不管有多少寬度/高度可用。
  • 使多列布局中的所有列采用相同的高度,即使它們包含的內(nèi)容量不同。

正如你將在后面的章節(jié)中看到的一樣,flexbox 使得很多布局任務變得更加容易。讓我們繼續(xù)吧!

一個簡單的例子

在本文中,我們將通過一系列練習來幫助你了解 Flexbox 的工作原理。要開始,您應該拷貝一個文件到本地?— mozila github 倉庫的?flexbox0.html?— 在現(xiàn)代瀏覽器里打開它(比如 Firefox、Chrome),然后打開你的編輯器看一眼它的代碼。你可以看它的線上實例。

你可以看到這個頁面有一個含有頂級標題的 <header> 元素,和一個包含三個 <article> 的?<section> 元素。我們將使用這些來創(chuàng)建一個非常的標準三列布局,如下所示:

324px; margin:0px auto; width:800px;">

指定元素的布局為 flexible

首先,我們需要選擇將哪些元素將設置為 flexible 框。我們要設置那些 flexible 元素的父元素 display 為一個特定值。在本例中,我們想要設置 <article> 元素,因此我們給 <section>(變成了 flex 容器)設置?display:

section {
  display: flex;
}

結(jié)果如下:

348px; margin:0px auto; width:800px;">

所以,就這樣一個簡單的聲明就給了我們所需要的一切—不可思議,對吧? 我們的多列布局具有大小相等的列,并且列的高度都是一樣。 這是因為這樣的 flex 項(flex容器的子項)的默認值是可以解決這些的常見問題的。 后面還有更多內(nèi)容。

注意:假如你想設置行內(nèi)元素為 flexible box,也可以置?display 屬性的值為?inline-flex。

flex 模型說明

當元素表現(xiàn)為 flex 框時,它們沿著兩個軸來布局:

class ="default internal">

  • 主軸(main axis)是沿著 flex 元素放置的方向延伸的軸(比如頁面上的橫向的行、縱向的列)。該軸的開始和結(jié)束被稱為 main start main end。
  • 橫軸(cross axis)是垂直于 flex 元素放置方向的軸。該軸的開始和結(jié)束被稱為 cross start cross end。
  • 設置了?display: flex?的父元素(在本例中是 <section>)被稱之為?flex 容器(flex container)。
  • 在 flex 容器中表現(xiàn)為 flexible 框的元素被稱之為 flex 項(flex item)(本例中是?<article> 元素。

了解這些術語以便你閱讀后續(xù)章節(jié)。 如果您對使用的任何術語感到困惑,您可以隨時返回這里。

列還是行?

Flexbox 提供了 flex-direction 這樣一個屬性,它可以指定主軸的方向(flexbox 子類放置的地方)— 它默認值是?row,這使得它們在按你瀏覽器的默認語言方向排成一排(在英語/中文瀏覽器中是從左到右)。

嘗試將以下聲明添加到 section 元素的 css 規(guī)則里:

flex-direction: column

你會看到,這會將那些元素設置為列布局,就像我們添加這些 CSS 之前。在繼續(xù)之前,請從示例中刪除此規(guī)則。

注意:你還可以使用 row-reverse?column-reverse?值反向排列 flex 項目。用這些值試試看吧!

換行

當你在布局中使用定寬或者定高的時候,可能會有一個問題出來即處于容器中的 flexbox 子元素會溢出,破壞了布局。你可以看一下?flexbox-wrap0.html 示例(你也可以拷貝到本地),如下所示:

>

在這里我們看到,子代確實超出了它們的容器。 解決此問題的一種方法是將以下聲明添加到 section css 規(guī)則中:

flex-wrap: wrap

現(xiàn)在嘗試一下吧;你會看到布局比原來好多了:

現(xiàn)在我們有了多行 flexbox — 任何溢出的元素將被移到下一行。在 article 元素上設置的 flex: 200px 規(guī)則,意味著每個元素的寬度至少是200px;我們將在后面更詳細地討論這個屬性。你可能還注意到,最后一行上的最后幾個項每個都變得更寬,以便把整個行填滿。

但是這里我們可以做得更多。首先,改變?flex-direction 屬性值為?row-reverse — 你會看到仍然有多行布局,但是每一行元素排列的方向和原來是相反的了。

flex-flow 縮寫

到這里,應當注意到存在著 flex-directionflex-wrap — 的縮寫 flex-flow。比如,你可以將

flex-direction: row;
flex-wrap: wrap;

替換為

flex-flow: row wrap;

flex 項的動態(tài)尺寸

現(xiàn)在讓我們回到第一個例子,看看是如何控制 flex 項占用空間的比例的。打開你本地的?flexbox0.html,或者拷貝?flexbox1.html 作為新的開始(查看線上)。

先,將以下規(guī)則添加到 CSS 的底部:

article {
  flex: 1;
}

這是一個無單位的比例值,表示每個 flex 項沿主軸的可用空間大小。本例中,我們設置 <article> 元素的 flex 值為?1,這表示每個元素占用空間都是相等的,占用的空間是在設置 padding 和 margin 之后剩余的空間。因為它是一個比例,這意味著將每個 flex 項的設置為?400000 的效果和 1 的時候是完全一樣的。

現(xiàn)在在上一個規(guī)則下添加:

article:nth-of-type(3) {
  flex: 2;
}

現(xiàn)在當你刷新,你會看到第三個 <article> 元素占用了兩倍的可用寬度和剩下的一樣?— 現(xiàn)在總共有四個比例單位可用。 前兩個 flex 項各有一個,因此它們占用每個可用空間的1/4。 第三個有兩個單位,所以它占用2/4或這說是1/2的可用空間。

您還可以指定?flex 的最小值。 嘗試修改現(xiàn)有的 article 規(guī)則:

article {
  flex: 1 200px;
}

article:nth-of-type(3) {
  flex: 2 200px;
}

這表示"每個flex 項將首先給出200px的可用空間,然后,剩余的可用空間將根據(jù)分配的比例共享"。 嘗試刷新,你會看到分配空間的差別。

324px; margin:0px auto; width:800px;">

Flexbox 的真正價值可以體現(xiàn)在它的靈活性/響應性,如果你調(diào)整瀏覽器窗口的大小,或者增加一個?<article> 元素,這時的布局仍舊是好的。

flex: 縮寫與全寫

flex 是一個可以指定最多三個不同值的縮寫屬性:

  • 第一個就是上面所討論過的無單位比例??梢詥为氈付ㄈ珜?flex-grow 屬性的值。
  • 第二個無單位比例?— flex-shrink — 一般用于溢出容器的 flex 項。這指定了從每個 flex 項中取出多少溢出量,以阻止它們溢出它們的容器。 這是一個相當高級的flexbox功能,我們不會在本文中進一步說明。
  • 第三個是上面討論的最小值??梢詥为氈付ㄈ珜?flex-basis 屬性的值。

我們建議不要使用全寫屬性,除非你真的需要(比如要去覆蓋之前寫的)。使用全寫會多些很多的代碼,它們也可能有點讓人困惑。

水平和垂直對齊

還可以使用 flexbox 的功能讓?flex 項沿主軸或橫軸對齊。讓我們一起看一下新例子?— flex-align0.html(在線瀏覽)— 我們將會有一個整潔,靈活的按鈕/工具欄。 此時,你看到了一個水平菜單欄,其中一些按鈕卡在左上角,就像下面這樣:

>

首先,拷貝一份到本地。

然后,將下面的 CSS 添加到例子的底部:

div {
  display: flex;
  align-items: center;
  justify-content: space-around;
}

刷新一下頁面,你就會看到這些按鈕很好的垂直水平居中了。我們是通過下面所說的兩個新的屬性做到的。

align-items 控制 flex 項在橫軸上的位置。

  • 默認的值是?stretch,其會使所有 flex 項沿著橫軸的方向拉伸以填充父容器。如果父容器在橫軸方向上沒有固定寬度(即高度),則所有 flex 項將變得與最長的 flex 項一樣長(即高度保持一致)。我們的第一個例子在默認情況下得到相等的高度的列的原因。
  • 在上面規(guī)則中我們使用的 center 值會使這些項保持其原有的高度,但是會在橫縱居中。這就是那些按鈕垂直居中的原因。
  • 你也可以設置諸如?flex-start 或?flex-end 這樣使 flex 項在橫軸的開始或結(jié)束處對齊所有的值。查看 align-items 了解更多。

你可以用 align-self 屬性覆蓋 align-items 的行為。比如,你可以這樣:

button:first-child {
  align-self: flex-end;
}

去看看它產(chǎn)生的效果,然后刪除它。

justify-content 控制 flex 項在主軸上的位置。

  • 默認值是?flex-start,這會使所有 flex 項都位于主軸的開始處。
  • 你也可以用?flex-end 來讓 flex 項到結(jié)尾處。
  • center?在?justify-content 里也是可用的,可以讓 flex 項在主軸居中。
  • 而我們上面用到的值?space-around 是很有用的—它會使所有 flex 項沿著主軸均勻地分布,在任意一端都會留有一點空間。
  • 還有一個值是?space-between,它和?space-around 非常相似,只是它不會在兩端留下任何空間。

在繼續(xù)下面之前,多多使用提到過的屬性吧,看看它們的效果。

flex 項排序

Flexbox 也有可以改變 flex 項的布局位置的功能,而不會影響到源順序(即 dom 樹里元素的順序)。這也是傳統(tǒng)布局方式很難做到的一點。

代碼也很簡單,將下面的 CSS 添加到示例代碼下面。

button:first-child {
  order: 1;
}

刷新下,然后你會看到 "Smile" 按鈕移動到了主軸的末尾。下面我們談下它實現(xiàn)的一些細節(jié):

  • 所有 flex 項默認的 order 值是 0。
  • order 值大的 flex 項比 order 值小的在顯示順序中更靠后。
  • 相同 order 值的 flex 項按源順序顯示。所以假如你有四個元素,其 order 值分別是2,1,1和0,那么它們的顯示順序就分別是第四,第二,第三,和第一。
  • 第三個元素顯示在第二個后面是因為它們的 order 值一樣,且第三個元素在源順序中排在第二個后面。

你也可以給 order 設置負值使它們比值為 0 的元素排得更前面。比如,你可以設置?"Blush" 按鈕排在主軸的最前面:

button:last-child {
  order: -1;
}

flex 嵌套

flexbox 也能創(chuàng)建一些頗為復雜的布局。設置 flex 項為 flex 容器也是沒有什么問題的,它的孩子也就表現(xiàn)為 flexible box 了??匆幌?complex-flexbox.html(在線瀏覽)。

0px auto;“>

這個例子的 HTML 是相當簡單的。我們用用一個 <section> 元素包含了三個 <article>。第三個 <article> 元素包含了三個 <div>:

section - article
          article
          article - div - button   
                    div   button
                    div   button
                          button
                          button

現(xiàn)在讓我們看一下布局用到的代碼。

首先,我們設置 <section> 的子代布局為 flexible box。

section {
  display: flex;
}

下面我們給 <article> 元素設置一些 flex 值。特別注意這里的第二條規(guī)則—我們設置第三個?<article> 元素里的子元素同樣表現(xiàn)為 flex 項,但是這次我們使它們放置為列。

article {
  flex: 1 200px;
}

article:nth-of-type(3) {
  flex: 3 200px;
  display: flex;
  flex-flow: column;
}

接下來,我們選擇了第一個 <div>。首先使用?flex: 1 100px;?簡單的給它一個最小的高度 100px,然后設置它的子代(<button> 元素)為 flex 項。在這里我們將它們放在一個包裝行中,使它們居中對齊,就像我們在前面看到的單個按鈕示例中所做的那樣。?

article:nth-of-type(3) div:first-child {
  flex: 1 100px;
  display: flex;
  flex-flow: row wrap;
  align-items: center;
  justify-content: space-around;
}

最后,我們給按鈕設置大小,有意思的是我們給它一個值為1的?flex 屬性。如果你調(diào)整瀏覽器窗口寬度,你會看到這是一個非常有趣的效果。按鈕將占用盡可能多的空間,盡可能多的坐在同一條線上,但是當它們不再適合在同一條線上,他們會到下一行去。

button {
  flex: 1;
  margin: 5px;
  font-size: 18px;
  line-height: 1.5;
}

跨瀏覽器兼容性

大多數(shù)瀏覽器都支持 Flexbox,諸如 Firefox, Chrome, Opera, Microsoft Edge 和 IE 11,較新版本的 Android/iOS 等等。但是你應該要意識到仍舊有被人使用的老瀏覽器不支持 Flexbox(或者支持,但是只是支持非常非常老版本的 Flexbox)。

雖然你只是在學習和實驗,這不太要緊; 然而,如果您正在考慮在真實網(wǎng)站中使用flexbox,則需要進行測試,并確保在盡可能多的瀏覽器中您的用戶體驗仍然可以接受。

Flexbox 相較其他一些 CSS 特性可能更為棘手。 例如,如果瀏覽器缺少 CSS 陰影,則該網(wǎng)站可能仍然可用。 但是假如不支持 flexbox 功能就會完全打破布局,使其不可用。

我們將討論在未來的模塊中克服棘手的跨瀏覽器支持問題的策略。

總結(jié)

到這里,介紹flexbox的基礎知識就結(jié)束了。 我們希望你體會到樂趣,并且玩的開心,能隨著你的學習與你一起向前。 接下來,我們將看到CSS布局的另一個重要方面—網(wǎng)格系統(tǒng)。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號