前提: | HTML 基礎(chǔ) (study Introduction to HTML),和了解CSS如何工作的(study Introduction to CSS.) |
---|---|
目標(biāo): | 學(xué)會(huì)如何使用Flexbox布局系統(tǒng)來(lái)創(chuàng)建Web布局。 |
長(zhǎng)久以來(lái),唯一可用的且有穩(wěn)定的跨瀏覽器兼容性的能用來(lái)構(gòu)建 CSS 布局的工具只有?floats?和?positioning。它們是即可行也不錯(cuò),但是在某些方面就有著限制,也難搞。
以下簡(jiǎn)單的布局要求是難以或不可能用這樣的工具方便且靈活的實(shí)現(xiàn):
正如你將在后面的章節(jié)中看到的一樣,flexbox 使得很多布局任務(wù)變得更加容易。讓我們繼續(xù)吧!
在本文中,我們將通過(guò)一系列練習(xí)來(lái)幫助你了解 Flexbox 的工作原理。要開(kāi)始,您應(yīng)該拷貝一個(gè)文件到本地?— mozila github 倉(cāng)庫(kù)的?flexbox0.html?— 在現(xiàn)代瀏覽器里打開(kāi)它(比如 Firefox、Chrome),然后打開(kāi)你的編輯器看一眼它的代碼。你可以看它的線上實(shí)例。
你可以看到這個(gè)頁(yè)面有一個(gè)含有頂級(jí)標(biāo)題的 <header>
元素,和一個(gè)包含三個(gè) <article>
的?<section>
元素。我們將使用這些來(lái)創(chuàng)建一個(gè)非常的標(biāo)準(zhǔn)三列布局,如下所示:
324px; margin:0px auto; width:800px;">
首先,我們需要選擇將哪些元素將設(shè)置為 flexible 框。我們要設(shè)置那些 flexible 元素的父元素 display
為一個(gè)特定值。在本例中,我們想要設(shè)置 <article>
元素,因此我們給 <section>
(變成了 flex 容器)設(shè)置?display:
section { display: flex; }
結(jié)果如下:
348px; margin:0px auto; width:800px;">
所以,就這樣一個(gè)簡(jiǎn)單的聲明就給了我們所需要的一切—不可思議,對(duì)吧? 我們的多列布局具有大小相等的列,并且列的高度都是一樣。 這是因?yàn)檫@樣的 flex 項(xiàng)(flex容器的子項(xiàng))的默認(rèn)值是可以解決這些的常見(jiàn)問(wèn)題的。 后面還有更多內(nèi)容。
注意:假如你想設(shè)置行內(nèi)元素為 flexible box,也可以置?display
屬性的值為?inline-flex。
當(dāng)元素表現(xiàn)為 flex 框時(shí),它們沿著兩個(gè)軸來(lái)布局:
class ="default internal">
display: flex
?的父元素(在本例中是 <section>
)被稱之為?flex 容器(flex container)。
<article>
元素。了解這些術(shù)語(yǔ)以便你閱讀后續(xù)章節(jié)。 如果您對(duì)使用的任何術(shù)語(yǔ)感到困惑,您可以隨時(shí)返回這里。
Flexbox 提供了 flex-direction
這樣一個(gè)屬性,它可以指定主軸的方向(flexbox 子類放置的地方)— 它默認(rèn)值是?row,
這使得它們?cè)诎茨銥g覽器的默認(rèn)語(yǔ)言方向排成一排(在英語(yǔ)/中文瀏覽器中是從左到右)。
嘗試將以下聲明添加到 section 元素的 css 規(guī)則里:
flex-direction: column
你會(huì)看到,這會(huì)將那些元素設(shè)置為列布局,就像我們添加這些 CSS 之前。在繼續(xù)之前,請(qǐng)從示例中刪除此規(guī)則。
注意:你還可以使用 row-reverse?
和 column-reverse?
值反向排列 flex 項(xiàng)目。用這些值試試看吧!
當(dāng)你在布局中使用定寬或者定高的時(shí)候,可能會(huì)有一個(gè)問(wèn)題出來(lái)即處于容器中的 flexbox 子元素會(huì)溢出,破壞了布局。你可以看一下?flexbox-wrap0.html 示例(你也可以拷貝到本地),如下所示:
>
在這里我們看到,子代確實(shí)超出了它們的容器。 解決此問(wèn)題的一種方法是將以下聲明添加到 section css 規(guī)則中:
flex-wrap: wrap
現(xiàn)在嘗試一下吧;你會(huì)看到布局比原來(lái)好多了:
現(xiàn)在我們有了多行 flexbox — 任何溢出的元素將被移到下一行。在 article 元素上設(shè)置的 flex: 200px 規(guī)則,意味著每個(gè)元素的寬度至少是200px;我們將在后面更詳細(xì)地討論這個(gè)屬性。你可能還注意到,最后一行上的最后幾個(gè)項(xiàng)每個(gè)都變得更寬,以便把整個(gè)行填滿。
但是這里我們可以做得更多。首先,改變?flex-direction
屬性值為?row-reverse
— 你會(huì)看到仍然有多行布局,但是每一行元素排列的方向和原來(lái)是相反的了。
到這里,應(yīng)當(dāng)注意到存在著 flex-direction
和 flex-wrap
— 的縮寫 flex-flow
。比如,你可以將
flex-direction: row; flex-wrap: wrap;
替換為
flex-flow: row wrap;
現(xiàn)在讓我們回到第一個(gè)例子,看看是如何控制 flex 項(xiàng)占用空間的比例的。打開(kāi)你本地的?flexbox0.html,或者拷貝?flexbox1.html 作為新的開(kāi)始(查看線上)。
先,將以下規(guī)則添加到 CSS 的底部:
article { flex: 1; }
這是一個(gè)無(wú)單位的比例值,表示每個(gè) flex 項(xiàng)沿主軸的可用空間大小。本例中,我們?cè)O(shè)置 <article>
元素的 flex 值為?1,這表示每個(gè)元素占用空間都是相等的,占用的空間是在設(shè)置 padding 和 margin 之后剩余的空間。因?yàn)樗且粋€(gè)比例,這意味著將每個(gè) flex 項(xiàng)的設(shè)置為?400000 的效果和 1 的時(shí)候是完全一樣的。
現(xiàn)在在上一個(gè)規(guī)則下添加:
article:nth-of-type(3) { flex: 2; }
現(xiàn)在當(dāng)你刷新,你會(huì)看到第三個(gè) <article>
元素占用了兩倍的可用寬度和剩下的一樣?— 現(xiàn)在總共有四個(gè)比例單位可用。 前兩個(gè) flex 項(xiàng)各有一個(gè),因此它們占用每個(gè)可用空間的1/4。 第三個(gè)有兩個(gè)單位,所以它占用2/4或這說(shuō)是1/2的可用空間。
您還可以指定?flex 的最小值。 嘗試修改現(xiàn)有的 article 規(guī)則:
article { flex: 1 200px; } article:nth-of-type(3) { flex: 2 200px; }
這表示"每個(gè)flex 項(xiàng)將首先給出200px的可用空間,然后,剩余的可用空間將根據(jù)分配的比例共享"。 嘗試刷新,你會(huì)看到分配空間的差別。
324px; margin:0px auto; width:800px;">
Flexbox 的真正價(jià)值可以體現(xiàn)在它的靈活性/響應(yīng)性,如果你調(diào)整瀏覽器窗口的大小,或者增加一個(gè)?<article>
元素,這時(shí)的布局仍舊是好的。
flex
是一個(gè)可以指定最多三個(gè)不同值的縮寫屬性:
flex-grow
屬性的值。flex-shrink
— 一般用于溢出容器的 flex 項(xiàng)。這指定了從每個(gè) flex 項(xiàng)中取出多少溢出量,以阻止它們溢出它們的容器。 這是一個(gè)相當(dāng)高級(jí)的flexbox功能,我們不會(huì)在本文中進(jìn)一步說(shuō)明。flex-basis
屬性的值。我們建議不要使用全寫屬性,除非你真的需要(比如要去覆蓋之前寫的)。使用全寫會(huì)多些很多的代碼,它們也可能有點(diǎn)讓人困惑。
還可以使用 flexbox 的功能讓?flex 項(xiàng)沿主軸或橫軸對(duì)齊。讓我們一起看一下新例子?— flex-align0.html(在線瀏覽)— 我們將會(huì)有一個(gè)整潔,靈活的按鈕/工具欄。 此時(shí),你看到了一個(gè)水平菜單欄,其中一些按鈕卡在左上角,就像下面這樣:
>
首先,拷貝一份到本地。
然后,將下面的 CSS 添加到例子的底部:
div { display: flex; align-items: center; justify-content: space-around; }
刷新一下頁(yè)面,你就會(huì)看到這些按鈕很好的垂直水平居中了。我們是通過(guò)下面所說(shuō)的兩個(gè)新的屬性做到的。
align-items
控制 flex 項(xiàng)在橫軸上的位置。
stretch,其會(huì)使
所有 flex 項(xiàng)沿著橫軸的方向拉伸以填充父容器。如果父容器在橫軸方向上沒(méi)有固定寬度(即高度),則所有 flex 項(xiàng)將變得與最長(zhǎng)的 flex 項(xiàng)一樣長(zhǎng)(即高度保持一致)。我們的第一個(gè)例子在默認(rèn)情況下得到相等的高度的列的原因。在上面規(guī)則中我們使用的 center
值會(huì)使這些項(xiàng)保持其原有的高度,但是會(huì)在橫縱居中。這就是那些按鈕垂直居中的原因。flex-start
或?flex-end 這樣使 flex 項(xiàng)在橫軸的開(kāi)始或結(jié)束處對(duì)齊所有的值。
查看 align-items
了解更多。你可以用 align-self
屬性覆蓋 align-items
的行為。比如,你可以這樣:
button:first-child { align-self: flex-end; }
去看看它產(chǎn)生的效果,然后刪除它。
justify-content
控制 flex 項(xiàng)在主軸上的位置。
默認(rèn)值是?flex-start,
這會(huì)使所有 flex 項(xiàng)都位于主軸的開(kāi)始處。flex-end 來(lái)讓 flex 項(xiàng)到結(jié)尾處。
center
?在?justify-content 里也是可用的,可以讓 flex 項(xiàng)在主軸居中。
space-around 是很有用的
—它會(huì)使所有 flex 項(xiàng)沿著主軸均勻地分布,在任意一端都會(huì)留有一點(diǎn)空間。還有一個(gè)值是?space-between,它和
?space-around 非常相似,只是它不會(huì)在兩端留下任何空間。
在繼續(xù)下面之前,多多使用提到過(guò)的屬性吧,看看它們的效果。
Flexbox 也有可以改變 flex 項(xiàng)的布局位置的功能,而不會(huì)影響到源順序(即 dom 樹(shù)里元素的順序)。這也是傳統(tǒng)布局方式很難做到的一點(diǎn)。
代碼也很簡(jiǎn)單,將下面的 CSS 添加到示例代碼下面。
button:first-child { order: 1; }
刷新下,然后你會(huì)看到 "Smile" 按鈕移動(dòng)到了主軸的末尾。下面我們談下它實(shí)現(xiàn)的一些細(xì)節(jié):
order
值是 0。你也可以給 order 設(shè)置負(fù)值使它們比值為 0 的元素排得更前面。比如,你可以設(shè)置?"Blush" 按鈕排在主軸的最前面:
button:last-child { order: -1; }
flexbox 也能創(chuàng)建一些頗為復(fù)雜的布局。設(shè)置 flex 項(xiàng)為 flex 容器也是沒(méi)有什么問(wèn)題的,它的孩子也就表現(xiàn)為 flexible box 了??匆幌?complex-flexbox.html(在線瀏覽)。
0px auto;“>
這個(gè)例子的 HTML 是相當(dāng)簡(jiǎn)單的。我們用用一個(gè) <section>
元素包含了三個(gè) <article>
。第三個(gè) <article>
元素包含了三個(gè) <div>
:
section - article article article - div - button div button div button button button
現(xiàn)在讓我們看一下布局用到的代碼。
首先,我們?cè)O(shè)置 <section>
的子代布局為 flexible box。
section { display: flex; }
下面我們給 <article>
元素設(shè)置一些 flex 值。特別注意這里的第二條規(guī)則—我們?cè)O(shè)置第三個(gè)?<article>
元素里的子元素同樣表現(xiàn)為 flex 項(xiàng),但是這次我們使它們放置為列。
article { flex: 1 200px; } article:nth-of-type(3) { flex: 3 200px; display: flex; flex-flow: column; }
接下來(lái),我們選擇了第一個(gè) <div>
。首先使用?flex: 1 100px;
?簡(jiǎn)單的給它一個(gè)最小的高度 100px,然后設(shè)置它的子代(<button>
元素)為 flex 項(xiàng)。在這里我們將它們放在一個(gè)包裝行中,使它們居中對(duì)齊,就像我們?cè)谇懊婵吹降膯蝹€(gè)按鈕示例中所做的那樣。?
article:nth-of-type(3) div:first-child { flex: 1 100px; display: flex; flex-flow: row wrap; align-items: center; justify-content: space-around; }
最后,我們給按鈕設(shè)置大小,有意思的是我們給它一個(gè)值為1的?flex 屬性。如果你調(diào)整瀏覽器窗口寬度,你會(huì)看到這是一個(gè)非常有趣的效果。按鈕將占用盡可能多的空間,盡可能多的坐在同一條線上,但是當(dāng)它們不再適合在同一條線上,他們會(huì)到下一行去。
button { flex: 1; margin: 5px; font-size: 18px; line-height: 1.5; }
大多數(shù)瀏覽器都支持 Flexbox,諸如 Firefox, Chrome, Opera, Microsoft Edge 和 IE 11,較新版本的 Android/iOS 等等。但是你應(yīng)該要意識(shí)到仍舊有被人使用的老瀏覽器不支持 Flexbox(或者支持,但是只是支持非常非常老版本的 Flexbox)。
雖然你只是在學(xué)習(xí)和實(shí)驗(yàn),這不太要緊; 然而,如果您正在考慮在真實(shí)網(wǎng)站中使用flexbox,則需要進(jìn)行測(cè)試,并確保在盡可能多的瀏覽器中您的用戶體驗(yàn)仍然可以接受。
Flexbox 相較其他一些 CSS 特性可能更為棘手。 例如,如果瀏覽器缺少 CSS 陰影,則該網(wǎng)站可能仍然可用。 但是假如不支持 flexbox 功能就會(huì)完全打破布局,使其不可用。
我們將討論在未來(lái)的模塊中克服棘手的跨瀏覽器支持問(wèn)題的策略。
到這里,介紹flexbox的基礎(chǔ)知識(shí)就結(jié)束了。 我們希望你體會(huì)到樂(lè)趣,并且玩的開(kāi)心,能隨著你的學(xué)習(xí)與你一起向前。 接下來(lái),我們將看到CSS布局的另一個(gè)重要方面—網(wǎng)格系統(tǒng)。
更多建議: