Flexbox完整指南- A Complete Guide to Flexbox


背景

Flexbox 布局 (FLexible Box)模塊(現在處於W3C的最終征求意見稿(Last Call Working Draft)階段)意在提供一個更為有效的方式來進行布局、對齊和分配一個容器內元素之間的空間,即使他們的大小是未知的或者動態的(這也是flex(彈性的)這個單詞的由來)。

flex布局的主要思想是,讓容器能夠改變它的子元素的寬度/高度(甚至順序),從而更好地填充可用的空間(主要是為了適應所有種類的設備和屏幕大小)。一個 flex 容器可以擴展它的子元素從而填充可用的空間,或者使他們收縮從而避免溢出。

最重要的,flexbox 布局是可以改變方向的。與之相對的是傳統布局(block是垂直方向的從上到下,inline是水平方向的從左到右)。雖然他們在頁面上表現良好,但是他們缺乏彈性(字面意義上的缺乏彈性)來適應大型的或者復雜的應用(尤其是遇到方向的改變、調整大小、伸展、收縮等等這些情況時)。

注意:Flexbox 布局最適合應用的組件、小規模的布局,而 Grid 布局更適於大規模布局。

基本術語

因為 flexbox 是一整個模塊而不是單一的屬性,所以他涉及很多東西,包括一組屬性。他們中一些要設置在容器上(父容器,被稱作 flex容器),還有一些要設置在子元素上(被稱作 flex子元素)。

如果說傳統的布局是基於塊級或行級文檔流方向的,那么flex布局是基於 “flex流方向(flex-flow directions)”的。請看下面來自標准的圖片,它解釋了關於flex布局的主要思想。

flexbox

基本上,子元素要么根據主軸(main axis,從主軸開始到主軸結束 )排列或者交叉軸(從交叉軸開始到交叉軸結束)排列。

  • 主軸 - flex容器的主軸是flex子元素的首要排列方向。要注意的時,主軸並不一定是水平的;實際方向要根據flex-direction屬性確定(后面詳細說明)。
  • 主軸起點|主軸終點 - flex子元素在flex容器內從 主軸起點 到 主軸終點 排列。
  • 主軸尺寸 - 一個元素的主要尺寸要么是它的寬度(width)要么是它的高度(height)。這要取決於哪一個屬性對着主軸方向。
  • 交叉軸 - 垂直於主軸方向的軸稱之為交叉軸。它的方向取決於主軸方向。
  • 交叉軸起點|交叉軸終點 - Flex行被flex子元素填充,從交叉軸起點到交叉軸終點。
  • 交叉軸尺寸 - 一個元素的交叉軸尺寸要么是它的寬度(width)要么是它的高度(height)。這要取決於哪一個屬性對着交叉軸方向。

譯者注:交叉軸(cross-axis)也被翻譯做側軸、旁軸

flex容器的屬性(flex container)

譯者注:不同於常規布局,flex布局依賴於flex容器和flex子元素共同配合完成。所以要在flex容器上設定一些屬性。

flex-container

display

這個屬性定義了一個flex容器;可以設定為 inline(內聯) 元素 或者 block(塊級)元素。它給它的所有直接子元素提供了一個 flex 上下文(環境)。

//CSS
.container{
	display:flex; /* 或者 inline-flex */
}
  • 注意 CSS 列(columns)在 flex容器 上不起作用。
  • float、clear和vertical-align在伸縮項目上沒有效果。

flex-direction

flex-direction

這個確立了主軸,也就是定義了flex子元素在flex容器中排列的方向。Flexbox(不考慮換行)是一個單方向的布局概念。可以認為flex子元素要么在水平行上要么在垂直列上進行排列。

//CSS
.container{
	flex-direction:row | row-reverse | column | column-reverse;
}
  • row (默認):在ltr排版方式下從左到右;在rtl排版方式下從右到左
  • row-reverse :在ltr排版方式下從右到左;在ltr排版方式下從左到右
  • column:和 row 類似,但是從上到下排列
  • column-reverse:和 row-reverse 一樣但是從下到上排列

flex-wrap

flex-wrap

默認情況下,flex子元素會嘗試填充一行。你可以通過設置這一屬性允許元素換行來改變這一點。在這里方向屬性(flex-direction)同樣發揮作用,它可以改變新的行堆積的方向。

//CSS
.container{
	flex-wrap: nowrap | wrap | wrap-reverse;
}
  • nowrap(默認值):單行(不換行)。ltr下從左到右排列,rtl下從右到左排列。
  • wrap:多行(換行)。ltr下從左到右排列排列;rtl下從右到左排列。
  • wrap-reverse:多行(換行)。ltr下從右到左排列;rtl下從左到右排列。

flex-flow

這是對於 flex-directionflex-wrap 屬性的簡潔表示(就像font之於 font-size、font-family、font-weight一樣),同時定義了 flex容器 的主軸和交叉軸。 默認值是 row nowrap

//CSS
flex-flow:<'flex-direction'> || <'flex-wrap'>

justify-content

justify-content

這個屬性定義了沿着主軸方向元素的對齊方式。
它會幫助分配容器內多余的空間,無論flex子元素是非彈性的,還是彈性的但是達到了最大尺寸。對於溢出一行的元素它同樣會發揮作用。

//CSS
.container{
	justify-content:flex-start | flex-end | center | space-between | space-around;
}
  • flex-start (default):子元素向一行的起始處堆積。(想象text-align:left)
  • flex-end:子元素向一行結尾處堆積。
  • center:子元素在一行的中間排列。(想象text-align:center)
  • space-between:子元素平均分布在一行中;第一個子元素緊貼行首,最后一個元素緊貼行末。
  • space-around:子元素平均分布在一行中,周圍有着相同的空間。注意視覺上這些空間並不是相等的,因為所有的元素在兩側都有相等的空間。第一個元素與容器邊緣中間僅有以單位的空間,而它和下一個元素之間會有兩個單位的空間,因為下一個元素本身周圍有着自己的空間。

aligh-items

align-items

這個屬性定義 flex子元素 在當前行沿着交叉軸如何排布。可以認為它是 justify-content 的交叉軸版本。

//CSS
.container{
	align-items:flex-start | flex-end | center | baseline | stretch ;
}
  • flex-start:元素在交叉軸開始處的margin邊緣將緊貼交叉軸的開始處。
  • flex-end:元素在交叉軸結束處的margin邊緣將緊貼交叉軸的結束處。
  • center:元素在交叉軸上居中。
  • baseline:元素根據他們的baseline對齊。
  • stretch(默認值):伸展子元素以填充容器(max-width/min-width仍會起作用)。

align-content

align-content

在容器的交叉軸方向上有多余空間時,這個屬性會對齊容器的,類似於 justify-content 在主軸上對齊單獨的子元素。

注意:當flex容器內部僅有一行 flex子元素 的時候,這個屬性不起作用。

//CSS
.container{
	align-content:flex-start | flex-end | center | space-between | space-around | stretch;
}
  • flex-start:所有行朝着容器的開始處堆積。
  • flex-end:所有行朝着容器的結束處堆積。
  • center:所有行在容器中間分布。
  • space-between:所有行平均分布。第一行在容器的起始處,最后一行在元素的結束處。
  • space-around:所有行平均分布,周圍有着相等的空間。
  • stretch(默認值):所有行伸展以填充剩余的空間。

flex子元素的屬性(flex items)

flex-items

order

order
默認情況下,flex子元素以源代碼中的順序分布。但是, order 屬性可以控制他們他們在 flex容器 中的表現。

//CSS
.item{
	order:<integer>; //默認是0;
}

flex-grow

flex-grow

這個屬性定義了元素可以根據需要擴展(grow)的能力。它接受一個無單位的值用以作為比例。它表明了一個子元素在 flex容器中 應該占有多大比例的空間。

如果所有的子元素都設置 flex-grow 值為1,那么所有的子元素都會獲得相等的空間。如果給其中一個子元素的值為2,那么它將占用其他元素兩倍的空間。

//CSS
.item {
	flex-grow: <number>; /* 默認0 */
}

負值無效。

flex-shrink

這個屬性給了元素在需要的情況下收縮的能力。

//CSS
.item {
	flex-shrink: <number>; /*默認值 1*/
}

負值無效。

flex-basis

這個屬性定義了在多余的空間被分配之前,一個元素的默認大小。根據 flex-direction 定義的不同,main-size 的值會對應 height 或者 width

//CSS
.item {
	flex-basis: <length> | auto; /* 默認值 auto */
}

如果設置為0,那么內容周圍的空間將不被考慮。如果設置為 auto ,那么多雨的空間會根據它的 flex-grow 屬性值來分配。

詳見

flex

該值是 flex-grow, flex-shrink, flex-basis的縮寫。第二個和第三個參數(flex-shrinkflex-basis)是可選的。默認值是 0 1 auto

//CSS
.item {
	flex:none | [<'flex-grow'> <'flex-shrink'> || <'flex-basis'> ];
}

建議用屬性縮寫代替單獨的屬性。這個縮寫會聰明地設置其他值。

align-self

align-self

該屬性允許元素覆蓋默認的對齊方式(或者 align-items 定義的對齊方式)。

參見 align-items 的解釋來理解本屬性可選的值。

//CSS
.item {
	align-self:auto | flex-start |flex-end | center | baseline | stretch;
}

注意 floatclearvertical-align對於 flex子元素 沒有效果。

樣例

我們先看一個簡單的例子,它解決了一個幾乎每天都要遇到的問題:完美的居中。沒有比用 flexbox 更簡單的方法了。

//CSS
.parent {
	display:flex;
	height:300px; /* 或者其他的值 */
}

.child {
	width: 100px; /* 任意值 */
	height: 100px; /* 任意值 */
	margin: auto; /* 神奇所在! */
}

這個方法基於一個很簡單的事實:margin屬性 設置為 ’auto‘ 的 flex子元素 會占用多余的空間。 所以設置垂直方向上的 margin 為 auto 會使得元素在兩個坐標軸上完美地居中。

現在讓我們用一些其他的屬性。
考慮一個有6個元素的列表,所有元素都有一個很漂亮的尺寸,但是可以自動調整大小。我們想要他們優雅地平均分布在主軸上,這樣當我們縮放瀏覽器的時候,一切依然顯示很完美。 (不用媒體查詢 media query).

//CSS
.flex-container{
	/* 我們先創建一個 flex布局 上下文 */
	display:flex;
	
	/* 之后我們定義主軸方向和是否允許自動換行 */
	
	//等同於
	// flex-direction:row;
	// flex-warp:wrap;
	flex-flow: row wrap;
	
	/* 最后我們定義如何分配剩余的空間 */
	justify-content:space-around;
}

完成。其他的一切都是其他樣式定義要考慮的。下面是在codepen上展示的一個例子。到codepen上查看,並試着調整你瀏覽器窗口去看發生什么事?

See the Pen Demo Flexbox 3 by Hugo Giraudel ( @HugoGiraudel) on CodePen.

讓我們試一下其他的一些東西。想象一下我們在頁面頂部有一個右對齊的導航欄,但是我們想要它在中等大小的屏幕上居中,在小屏幕上單行顯示。很簡單。

//CSS

/* 大屏幕 */
.navigation {
	display:flex;
	flex-flow:row wrap;
	
	/* 子元素右對齊 */
	justify-content:flex-end;
}

/* 中型屏幕 */
@media all and (max-width:800px) {
	/* 中型屏幕上,平均分布空白空間用以居中 */
	justify-content:space-around;
}

/* 小型屏幕 */
@media all and (max-width:500px) {
	.navigation {
		/* 在小型屏幕上,用列方向而不是行方向 */
		flex-direction: column;
	}
}
See the Pen Demo Flexbox 2 by Hugo Giraudel ( @HugoGiraudel) on CodePen.

讓我們感受一下 flex子元素 的彈性,嘗試一些更好的東西。比如移動優先的3欄布局,header和footer都占用全部寬度,並且實際順序與源代碼順序相獨立。

//CSS

.wrapper {
	display: flex;
	flex-flow:row wrap;
}

/* 設置所有的子元素100%寬度 */
.header, .main, .nav, .aside, .footer {
	flex:1 100%;
}

/* 源代碼中順序如下:
 * 1. header
 * 2. nav
 * 3. main
 * 4. aside
 * 5. footer
 */
 
 /* 中等屏幕 */
 @media all and (min-width: 600px) {
 	/* 設定兩個側邊欄共用一行 */
 	.aside { flex: 1 auto;}
 }
 
 @media all and (min-width:800px) {
 	.main {flex: 2 0;}
 	
 	.aside-1{ order:1; }
	.main   { order:2; }
	.aside-2{ order:3; }
	.footer { order:4; } 
 }

See the Pen Demo Flexbox 3 by Hugo Giraudel (@HugoGiraudel) on CodePen.

Flexbox 前綴(prefix)

Flexbox需要添加一些前綴用以盡可能支持多的瀏覽器。但是它不是簡單地添加前綴就好(類似於-webkit-、-moz-、-ms-),它有着完全不同的屬性和值。因為Flexbox的標准經過了很多次修改。造成了 "old"、“tweener”、“new”三個版本。

解決這個問題最好的辦法可能是寫的時候用最新的語法來寫,並且用 Autoprefixer 這個工具來處理降級。

當然,可以用 Sass的@mixin 方法來幫助解決這個問題,下面有一個例子展示了應該做哪些處理。

	@mixin flexbox() {
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
}

@mixin flex($values) {
  -webkit-box-flex: $values;
  -moz-box-flex:  $values;
  -webkit-flex:  $values;
  -ms-flex:  $values;
  flex:  $values;
}

@mixin order($val) {
  -webkit-box-ordinal-group: $val;  
  -moz-box-ordinal-group: $val;     
  -ms-flex-order: $val;     
  -webkit-order: $val;  
  order: $val;
}

.wrapper {
  @include flexbox();
}

.item {
  @include flex(1 200px);
  @include order(2);
}

相關屬性

其他資源

Flexbox in the CSS specifications

Flexbox at MDN

Flexbox at Opera

Diving into Flexbox by Bocoup

Mixing syntaxes for best browser support on CSS-Tricks

Flexbox by Raphael Goetter (FR)

Flexplorer by Bennett Feely

Bugs

Flexbox當然存在bug。我見過的關於這些bug的最好的集合是 Philip Walton 和 Greg Whitworth 的Flexbugs。這是一個開源的地方來對這些進行記錄,我給出這個鏈接就好。

瀏覽器支持

flex的版本划分如下:

  • (new)表示最近的標准的語法(例如:display:flex;
  • (tweener)表示2011年版本的語法(例如:display:flexbox;
  • (old)表示最早的2009年的語法(例如:display:box;

|chrome |Safari |Firefox |Opera |IE |Android |iOS |
|---|
|21+(new) |3.1+(old) |2-21(old) |12.1+(new) |10(tweener)|2.1+(old)|3.2+(old)|
|20-(old) |6.1+(new) |22+(new) | |11+(new) |4.4+(new)|7.1+(new)|

有關如何混合多種語法達到最好的瀏覽器兼容效果,請參閱這兩篇文章 CSS-tricksthis article (DevOpera)

翻譯完成之后才發現網上已經有了翻譯了。 W3plus-一個完整的Flexbox指南

英文原文:http://css-tricks.com/snippets/css/a-guide-to-flexbox

中文譯文:http://www.w3cplus.com/css3/a-guide-to-flexbox.html

其他翻譯:http://www.w3cplus.com/css3/a-guide-to-flexbox.html

有意見請留言。

如需轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM