翻譯:瘋狂的技術宅 原文:https://medium.com/swlh/css-flexbox-fundamentals-visual-guide-1c467f480dac
介紹
Flexbox是 Flexible Box Module
(彈性盒模型)的縮寫。 是一種可以輕鬆控制html元素之間的空間分佈和對齊的佈局模型。
Flexbox同一時間只能控制行或列中的一個維度。對於二維控制需要 CSS 網格佈局。
首先給出如下模板:
<body>
<div class="container">
<div class="box box-1">1</div>
<div class="box box-2">2</div>
<div class="box box-3">3</div>
<div class="box box-4">4</div>
<div class="box box-5">5</div>
<div class="box box-6">6</div>
<div class="box box-7">7</div>
<div class="box box-8">8</div>
<div class="box box-9">9</div>
<div class="box box-10">10</div>
</div>
</body>複製程式碼
以上 div 的預設行為遵循普通的html文件流,將會從上到下、從左到右呈現,並採用整個 body 的寬度,因為其 display
屬性預設為block
。
彈性專案
當 display: flex
應用於 .container
div 時,所有直接子div都變為 flex-items
,並獲得新的行為
- 它們將顯示在同一行中,因為
flex-direction
預設為row
- 它們將會從左到右顯示
- 其中的專案不會自動伸展來適應整個寬度(主軸),為了做到這一點,它們會縮小。
- 專案會被拉伸以適合交叉軸(在此示例中為高度)。 如果這些專案的高度不一致,它們將會伸展到最高的那個高度
flex-basis
預設為auto
(專案寬度將由其內容決定)flex-wrap
預設為nowrap
(如果容器的寬度不足以適合這些專案,它們不會換行,而是會溢位)
出於視覺化的目的,讓我們拉伸容器使其佔據整個高度。
彈性容器
display:flex
使容器擴充套件至整個可用寬度。 這點與 display:inline-flex
相反,它使容器縮小到內容的寬度。
彈性方向
一旦被宣告為 flex 容器,就可以認為該元素具有兩個軸:主軸與交叉軸。 主軸由flex-direction
屬性定義。 交叉軸垂直於前者。
flex-direction
屬性有四個值:row
,row-reverse
,column
和 column-reverse
。
其預設值為row
,它從左到右水平設定主軸,交叉軸從上到下垂直擷取。 類似地, column
值從頂部到底部垂直設定主軸,從左到右設定交叉軸。 這兩個選項的相反屬性使主軸反轉180°。 交叉軸保持不變。
可以通過下圖觀察這些值的 flex-items 行為:
Flex Wrap
當容器中的空間不足以容納其中的彈性專案時,可以用 flex-wrap
來處理。
在預設情況下,flex-wrap
被設定為 nowrap
,這意味著如果容器不能適應在其內的行中原始寬度的專案,則這些專案將會縮小來進行適應。 如果它們因為某種原因無法收縮,則會溢位容器。
把專案寬度設定為300px,nowrap
選項會輸出以下結果:
其中,每個專案都會縮小到大約 70px 來適合容器。
當屬性被更新為wrap
時,現在專案的寬度實際上是原始值300px。 當第一行不足以容納300px時,則該專案將換行到新的一行,而不是溢位容器。 應該把其中的每一行都視為單獨的彈性容器。 一個容器中的空間分佈不會影響到與其相鄰的其他容器。
但是為什麼彈性專案會佔據整個螢幕高度呢? 在第一部分中,容器高度設定為 100vh
,因此可用空間被平均分為四行,來適合 300px
專案的需要。 如果我們沒有設定 100vh
,容器的高度則會遵循專案內容的高度,如下圖所示:
另一個選項是wrap-reverse
,它會反轉交叉軸。 通過 flex-direction
屬性從上到下設定,wrap-reverse
將其轉換為從下到上。
通過使用 flex-direction:column
反轉主軸,不適應的元素會被換到另一列,剩餘空間被均勻分割。
wrap-reverse
選項會沿著列方向將交叉軸從右向左反轉,產生以下輸出:
由於flexbox是單維度佈局,所以在進行反轉時,專案從下到上進行排列(對於行方向),但保持左右結構,只改變了交叉軸。
彈性流
flex-direction
和 flex-wrap
可以在一個屬性當中宣告:flex-flow:[direction][wrap]
。
.flex-container {
flex-flow : column wrap;
}複製程式碼
專案之間的縫隙
讓我們回到row/wrap。 可以通過設定專案的 width:33.3333%
來填充整個容器:
但是如果你希望在子div 之間有一個間隙,它們就不會按照你想的那樣換行:
這個小麻煩這可以通過 CSS 函式 calc()
來解決:
.flex-item {
width: calc(33.33333% - 40px);
margin: 20px;
}複製程式碼
為了消除容器邊緣的空間,可以在容器上使用負邊距:
.flex-container {
margin: -20px;
}複製程式碼
排序
order
屬性允許更改出現的可視排序專案。排序被分配給組。 預設情況下所有的彈性專案都設定為 order: 0
,這意味著所有專案都屬於同一組,並且它們將按照原始順序定位。 在兩個或多個組的情況下,組會相對於它們的整數值進行排序。
在下面的例子中,有三個 ordinal groups
:-1
, 0
和 1
,按此順序進行排列。
.box-3 { order: 1; }
.box-7 { order: 1; }
.box-8 { order: -1; }複製程式碼
此屬性可視地重新分配專案,但在互動時保持其原始源位置,例如使用Tab鍵遍歷它們。 如果物品訂購對可訪問性有影響,則可以考慮這一點。 flex-direction
也是如此。
對齊
(此圖反覆上傳總是出錯,請大家移步原文檢視)
在Flexbox中,沿著軸的專案對齊和空間分佈可以受到四個屬性的控制:
justify-content
: 對齊主軸中的所有專案align-items
: 對齊交叉軸中的所有專案align-self
: 對齊交叉軸中的單個專案align-content
: 控制交叉軸上柔性線之間的空間
justify-content
適用於容器,justify-content
處理專案在主軸上的對齊方式。六個最常用的選項包括: flex-start
、 flex-end
、center
、 space-around
、 space-between
和 space-evenly
,flex-start
是預設值。.
align-items
也適用於容器, align-items
屬性處理交叉軸方向上的對齊。它的預設值是 stretch
其它的選項是 flex-start
、flex-end
、 center
和 baseline
。
stretch
選項使所有專案伸展到容器高度(如果設定)或最高專案的高度[5]。 第一張圖片顯示容器高度設定為 100vh
,未設定第二個高度。
align-content
這是作用在 flex 容器的四個屬性中的最後一個,align-content
在交叉軸中的彈性線之間分配空格。 作為後者,它的初始值是 stretch
和 justify-content
,它接受以下選項: flex-start
, flex-end
, center
, space-around
, space-between
, space-evenly
。
align-self
align-items 屬性實際上通過在容器內的所有 flex 專案上設定 align-self 來實現。 通過單獨設定 align-self
,可以覆蓋全域性值。 它接受與align-items
和'auto'相同的值[5]。
auto
選項通過 align-items
將 align-self
重置為容器全域性定義的值。
調整 Flexbox 的大小
專案的尺寸和伸展性可以通過三種屬性來控制: flex-grow
、 flex-shrink
和 flex-basis
。 這三個都作用於主軸。
flex-grow
:如果有額外的空間,每個專案應該如何放大flex-shrink
:如果沒有足夠的空間,應該如何縮小每個專案flex-basis
:在設定上述兩個屬性之前,該專案的大小應該是多少
flex-grow
由此屬性設定的 flex grow factor
(彈性增長因子)用來處理專案大小相對於彼此的比率。
預設值為 0
,這意味著如果還有可用空間,就把它放在最後一個專案之後。
在上面的例子中,direction
被設定為 row
,每個彈性專案的 width
被設定為 60px
。 由於容器寬是 980px
,所以剩餘的可用空間為 680px
。 這個空間被稱為positive free space
(正自由空間)。
如果將 flex-grow
設定為1
,正可用空間量會在彈性專案之間平均分配。 每個專案的寬度將會增加 136px
,總寬度為196px
。
通過將 flex-grow: 2
應用到第三個專案,它會得到比其它專案多出兩倍的可用正自由空間,即286px
,其他專案仍為173px
。
下圖顯示了把專案的 flex-grow
屬性值設定為其內容對應的數字時的情形。
flex-shrink
當沒有足夠的可用空間來容納所有容器時,用 flex-shrink
處理專案大小。 它通過縮小這些專案來劃分它們之間的 negative free space
(負自由空間)。
下圖顯示的是寬度為 980px
的容器,它容納了5個寬度為 300px
的物品。 由於沒有空間容納所需的總寬度 1500px
,所以預設的flex shrink factor
(彈性收縮係數)的值為1
,這樣會使每個專案的寬度均勻縮小到196px
。
通過將第三項的比率設定為2
,它縮小為其餘專案大小的二分之一。
本節的最後一張圖顯示了將每個專案的內容值對應的數字設定為 flex-shrink
的值時的情形。
flex-basis
flex-basis
是在實際設定可用空間之前,檢查每個專案本來應具有的大小的屬性。 預設值為 auto
,項寬度由 width
屬性顯式設定,或者取其內容寬度。 它也接受畫素值。
下面的動圖顯示了一個800px
寬的容器和五個設定為 flex-basis:160px
的彈性專案。 這告訴瀏覽器:如果在理想狀態下,有足夠的空間來放置所有的專案,就遵循它們的160px
寬度,並且沒有正/負可用空間;如果沒有足夠的空間的話,那麼 flex-shrink
預設為1
,所有專案均勻收縮; 如果有額外的空間,flex-grow
預設為0
,並且剩餘的空間放在最後一個專案之後。
下一個動圖展示了把專案1設定為flex-shrink:10
,專案4設定為flex-grow:10
。對於負自由空間,專案1的寬度減少10倍。 對於正空閒空間,第4項的寬度是其他空間的10倍。
flex-basis
也接受值 content
,此時無論其寬度是否被設定,計算自由空間時所考慮的寬度依據是專案中的內容。
flex
flex
屬性是按順序排列的 flex-grow
、 flex-shrink
和 flex-basis
的簡寫,它接受以下預定義值:
initial
:重置為 flexbox 的預設值,等同於flex: 0 1 auto
auto
:flex-items能夠根據需要增長/縮小,等同於flex: 1 1 auto
none
:固定專案,等同於flex: 0 0 auto
flex: 1
:flex-items 具有伸縮的能力,flex-basis
設定為零,等同於flex: 1 1 0
Autoprefixer
對於跨瀏覽器的相容性問題,設定具有具有必要字首的屬性是非常重要的,以確保能夠支援所有瀏覽器。
手動自動為每個屬性新增字首可能是一項非常繁瑣的任務,也使樣式很難維護。使用 Gulp 能夠替你自動執行這些任務。
為了能夠使用Gulp,我們必須將它作為依賴新增到專案當中。 這項工作是在 package.json
檔案中完成的,它負責跟蹤專案依賴及其版本。 在終端中輸入下列命令來建立檔案:
nmp init複製程式碼
系統將提示你輸入專案資訊,可以一直按Enter鍵直到完成。 輸出的檔案內容將是這樣的:
{
"name": "project-name",
"version": "1.0.0",
"description": "Project description",
"main": "index.js",
"scripts": { "test": "echo \"Error: no test specified\" && exit 1" },
"author": "Author Name",
"license": "ISC"
}複製程式碼
全域性安裝gulp:
npm install gulp -g複製程式碼
安裝 gulp 和 gulp-autoprefixer 作為專案依賴項:
npm install gulp --save-dev
npm install gulp-autoprefixer --save-dev複製程式碼
它們將會出現在 package.json
檔案中的 devDependencies
下。
建立一個gulpfile.js檔案:
touch gulpfile.js複製程式碼
新增以下內容:
// gulpfile.js
var gulp = require('gulp');
var autoprefixer = require('gulp-autoprefixer');
var options = { browsers: ['last 2 versions'], cascade: false };
gulp.task('styles', function() {
return gulp.src('./styles.css')
.pipe(autoprefixer(options))
.pipe(gulp.dest('build'));
});複製程式碼
gulp
會從 styles.css
中提取內容並通過 gulp-autoprefixer
傳遞它。 處理結果會儲存在build
資料夾下。
參考
- What the Flexbox Course
- Basic concepts of flexbox — 25/03/2018
- Mastering Wrapping of Flex Items — 26/03/2018
- Ordering Flex Items — 26/03/2018
- Aligning Items in a Flex Container — 26/03/2018
- StackOverflow — 27/03/2018
- Controlling Ratios of Flex Items Along the Main Axis — 28/03/2018
- Gulp
- Gulp Autoprefixer