- 原文地址:Everything You Need To Know About Alignment In Flexbox
- 原文做者:Rachel Andrew
- 譯文出自:掘金翻譯計劃
- 本文永久連接:github.com/xitu/gold-m…
- 譯者:CodeMing
- 校對者:Augustwuli、Ivocin
簡論: 在這篇文章中,咱們將會在探討一些基本規則的同時談一談 Flexbox 的排列屬性以幫助咱們知道橫軸和豎軸上(元素的)對齊是如何實現的。css
在這個系列的第一篇文章中,我解釋了當你把一個元素設置爲 display: flex
時發生了什麼。此次咱們將會討論下排列屬性,同時也會討論(這些屬性)如何和 Flexbox 一塊兒工做。若是你曾經對什麼時候使用 align 屬性和 justify 屬性感到疑惑的話,我但願這篇文章將會讓(排列的)問題變得清晰! 若是你曾經對什麼時候使用 align 屬性和 justify 屬性感到疑惑的話前端
在整個 CSS 佈局的歷史中,如何能恰當地在橫豎兩軸正確排列元素估計是 Web 設計中最難的問題了。因此當瀏覽器中開始出現可以在兩軸恰當地排列元素和元素組的 Flexbox 排列方式時,像你我同樣的廣大web開發者都爲之激動不已。排列方式變得簡單到只須要兩行 CSS 代碼:android
HTML:ios
<div class="container">
<div class="item">Item</div>
</div>複製代碼
CSS:git
body {
padding: 20px;
font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}
* {box-sizing: border-box;}
p {
margin: 0 0 1em 0;
}
.container {
border: 5px solid rgb(111,41,97);
border-radius: .5em;
padding: 10px;
display: flex;
height: 300px;
width: 300px;
justify-content: center;
align-items: center;
}
.item {
padding: 10px;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
}複製代碼
能夠看由 Rachel Andrew (@rachelandrew) 建立的在 CodePen 上的展現:Smashing Flexbox Series 2: center an item 。github
你所瞭解的 flexbox 排列屬性目前都已經完整地被收錄到 盒子元素排列規範中了。這個規範文檔詳細地說明了在各類佈局狀況下的元素排列如何工做。這意味着咱們在使用 Flexbox 排列方式或者未來在不一樣佈局狀況下均可以在 CSS Grid 中使用相同的排列屬性。所以,任何新的排列都會在新的盒子元素排列規範中指出,而不是新的 Flexbox 版本。(譯者注:此處是新的特性是以新的排列屬性/方法來建立的,而不是更新 Flexbox 版本)web
許多人告訴我他們在使用 flexbox 的時候很難區別是應該使用以 align-
仍是 justify-
開頭的屬性。因此你須要知道:後端
justify-
實現主軸上的排列方式。即排列與你的 flex-direction
相同的方向。align-
實現交叉軸上的排列方式。即排列與你的 flex-direction
相垂直的方向。在下文中,根據主軸和交叉軸而不是水平和垂直的方向來思考會更容易理解。(主軸和交叉軸)和物理方位一點關係都沒有。設計模式
咱們將會從主軸排列來開始討論。在主軸上,咱們經過 justify-content
屬性來實現排列。這個屬性的做用對象是咱們的全部 flexbox 子元素所組成的組。同時也控制着組內全部元素的間距。瀏覽器
默認的 justify-content
值是 flex-start
。這也就是爲何你聲明 display: flex
以後你的全部 flexbox 子元素朝着你的 flex 盒子的開始排成一行。若是你有一個值爲 row
的 flex-direction
屬性同時頁面是從左到右讀的語言(例如英語)的話,這些字元素將會從左邊開始排列。
子元素從盒子的開始排列(放大預覽)
記住 justify-content
只會在 盒子有剩餘空間能夠分配時 發揮做用。因此若是你的子元素佔滿了主軸的空間的話,justify-content
將不會產生任何做用。
盒子沒有任何剩餘空間能夠分配(放大預覽)
若是將 justify-content
設置爲 flex-end
的話,全部的元素將會移動到 flex 盒子的結束排成一行。空閒空間將會被移到 flex 盒子的開始之處。
子元素從盒子的結束排列(放大預覽)
咱們能夠對這些剩餘的區域作其餘事情。咱們能夠經過 justify-content: space-between
來讓它分佈在 flex 盒子的兩個子元素之間。在這種狀況下,最前和最後的兩個子元素會貼着容器,同時全部的空間將會被平均分配在每個子元素之間。
剩餘空間分配在子元素之間(放大預覽)
咱們也能夠經過使用 justify-content: space-around
將這些空間環繞着 flex 盒子的子元素。在這種狀況下,子元素將會均勻地分佈在容器中,同時可用空間也會被這些元素分享。
子元素的兩側都有空間([放大預覽(cloud.netlifyusercontent.com/assets/344d…))
在盒子排列規範中能夠找到一個 justify-content
的更新的值,它沒有出如今 Flexbox 的規範中。它的值是space-evenly
。在這種狀況下,子元素會均勻分佈在容器內,同時額外的空間將會被子元素的兩側所分享。
元素均勻地分佈在容器內(放大預覽)
你能夠在 demo 中嘗試一下:
HTML:
<div class="controls">
<select id="justifyMe">
<option value="flex-start">flex-start</option>
<option value="flex-end">flex-end</option>
<option value="center">center</option>
<option value="space-around">space-around</option>
<option value="space-between">space-between</option>
<option value="space-evenly">space-evenly</option>
</select>
</div>
<div class="container" id="container">
<div class="item">One</div>
<div class="item">Two Two</div>
<div class="item">Three Three Three</div>
</div>複製代碼
CSS:
body {
padding: 20px;
font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}
* {box-sizing: border-box;}
p {
margin: 0 0 1em 0;
}
.container {
border: 5px solid rgb(111,41,97);
border-radius: .5em;
padding: 10px;
display: flex;
}
.item {
padding: 10px;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
}
.controls {
background-color: rgba(0,0,0,.1);
padding: 10px;
border-radius: .5em;
border: 1px solid rgba(0,0,0,.2);
margin: 0 0 2em 0
}
.controls select {
font-size: .9em;
}複製代碼
JavaScript:
var justify = document.getElementById("justifyMe");
justifyMe.addEventListener("change", function (evt) {
document.getElementById("container").style.justifyContent = evt.target.value;
});複製代碼
能夠看由 Rachel Andrew (@rachelandrew) 建立的在 CodePen 上的展現:Smashing Flexbox Series 2: justify-content with flex-direction: row
這些值一樣會在你的 flex-direction
爲 column
時生效。你可能沒有額外的空間來分配一個列,但你能夠經過添加 height 屬性或者是改變 flex 容器的大小來解決這個問題。就像下面這個 demo 同樣。
HTML:
<div class="controls">
<select id="justifyMe">
<option value="flex-start">flex-start</option>
<option value="flex-end">flex-end</option>
<option value="center">center</option>
<option value="space-around">space-around</option>
<option value="space-between">space-between</option>
<option value="space-evenly">space-evenly</option>
</select>
</div>
<div class="container" id="container">
<div class="item">One</div>
<div class="item">Two Two</div>
<div class="item">Three Three Three</div>
</div>複製代碼
CSS:
body {
padding: 20px;
font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}
* {box-sizing: border-box;}
p {
margin: 0 0 1em 0;
}
.container {
border: 5px solid rgb(111,41,97);
border-radius: .5em;
padding: 10px;
display: flex;
flex-direction: column;
height: 60vh;
}
.item {
padding: 10px;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
}
.controls {
background-color: rgba(0,0,0,.1);
padding: 10px;
border-radius: .5em;
border: 1px solid rgba(0,0,0,.2);
margin: 0 0 2em 0
}
.controls select {
font-size: .9em;
}複製代碼
JavaScript:
var justify = document.getElementById("justifyMe");
justifyMe.addEventListener("change", function (evt) {
document.getElementById("container").style.justifyContent = evt.target.value;
});複製代碼
能夠看由 Rachel Andrew (@rachelandrew) 建立的在 CodePen 上的展現:Smashing Flexbox Series 2: justify-content with flex-direction: column
若是你給你的 flex 容器添加了 flex-wrap: wrap
同時也有好幾條 flex 排列行,那你能夠用 align-content
屬性來在交叉軸上排列你的 flex 排列行。不過,這將會須要交叉軸上有額外的空間。在下面這個 demo 中,個人交叉軸做爲豎直的列在運行,同時我設置了這個 flex 容器的高度爲 60vh
。因爲這個高度比我展現 flex 子元素所需的高度大,因此個人容器有了交叉軸方向上的空餘空間。
我可使用下面全部的 align-content
屬性值:
HTML:
<div class="controls">
<select id="alignMe">
<option value="stretch">stretch</option>
<option value="flex-start">flex-start</option>
<option value="flex-end">flex-end</option>
<option value="center">center</option>
<option value="space-around">space-around</option>
<option value="space-between">space-between</option>
<option value="space-evenly">space-evenly</option>
</select>
</div>
<div class="container" id="container">
<div class="item">One</div>
<div class="item">Two Two</div>
<div class="item">Three Three Three</div>
<div class="item">Four Four Four Four</div>
</div>複製代碼
CSS:
body {
padding: 20px;
font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}
* {box-sizing: border-box;}
p {
margin: 0 0 1em 0;
}
.container {
border: 5px solid rgb(111,41,97);
border-radius: .5em;
padding: 10px;
max-width: 400px;
height: 60vh;
display: flex;
flex-wrap: wrap;
}
.item {
padding: 10px;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
}
.controls {
background-color: rgba(0,0,0,.1);
padding: 10px;
border-radius: .5em;
border: 1px solid rgba(0,0,0,.2);
margin: 0 0 2em 0
}
.controls select {
font-size: .9em;
}複製代碼
JavaScript:
var align = document.getElementById("alignMe");
alignMe.addEventListener("change", function (evt) {
document.getElementById("container").style.alignContent = evt.target.value;
});複製代碼
能夠看由 Rachel Andrew (@rachelandrew) 建立的在 CodePen 上的展現:Smashing Flexbox Series 2: align-content with flex-direction: row
若是個人 flex-direction
值爲 column
的話,那 align-content
屬性將像下面這個例子同樣運行:
HTML:
<div class="controls">
<select id="alignMe">
<option value="stretch">stretch</option>
<option value="flex-start">flex-start</option>
<option value="flex-end">flex-end</option>
<option value="center">center</option>
<option value="space-around">space-around</option>
<option value="space-between">space-between</option>
<option value="space-evenly">space-evenly</option>
</select>
</div>
<div class="container" id="container">
<div class="item">One</div>
<div class="item">Two Two</div>
<div class="item">Three Three Three</div>
<div class="item">Four Four Four Four</div>
</div>複製代碼
CSS:
body {
padding: 20px;
font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}
* {box-sizing: border-box;}
p {
margin: 0 0 1em 0;
}
.container {
border: 5px solid rgb(111,41,97);
border-radius: .5em;
padding: 10px;
max-width: 400px;
height: 60vh;
display: flex;
flex-wrap: wrap;
flex-direction: column;
}
.item {
height: 20vh;
padding: 10px;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
}
.controls {
background-color: rgba(0,0,0,.1);
padding: 10px;
border-radius: .5em;
border: 1px solid rgba(0,0,0,.2);
margin: 0 0 2em 0
}
.controls select {
font-size: .9em;
}複製代碼
JacaScript:
var align = document.getElementById("alignMe");
alignMe.addEventListener("change", function (evt) {
document.getElementById("container").style.alignContent = evt.target.value;
});複製代碼
能夠看由 Rachel Andrew (@rachelandrew) 建立的在 CodePen 上的展現:Smashing Flexbox Series 2: align-content with flex-direction: column
正如 justify-content
屬性同樣,咱們的設置做用在(子元素所組成的)子元素組中,同時空餘空間被分割。
在盒子元素排列規範中,咱們發現了一個簡寫方法 place-content
。使用這個屬性意味着你能夠一次性設置 justify-content
和 align-content
。它的第一個值是 align-content
,第二個值是 align-content
。若是你僅僅設置了一個值 A,那麼這兩個值都將設置成 A,所以:
.container {
place-content: space-between stretch;
}
複製代碼
和下面同樣:
.container {
align-content: space-between;
justify-content: stretch;
}
複製代碼
若是咱們使用:
.container {
place-content: space-between;
}
複製代碼
那將和下面同樣:
.container {
align-content: space-between;
justify-content: space-between;
}
複製代碼
咱們如今知道,咱們能夠對(全部 flex 子元素所組成的)子元素組進行關於 flex 元素和 flex 排列行的操做。不過,咱們但願有其它方式即經過聲明元素與元素之間在數軸上的關係來操做咱們的元素。你的 flex 容器有一個高度,這個高度多是由容器內最高的子元素所決定的,就以下圖同樣。
容器的高度被第三個子元素所定義(放大預覽)
flex 容器的高度能夠經過給 flex 容器添加一個 height 屬性所代替:
容器的高度經過該容器的大小屬性所定義(放大預覽)
flex 子元素看起來都被拉伸到最高的子元素的高度的緣由是 align-items
的初始值是 stretch
。子元素們在交叉軸上被拉伸成 flex 容器在那個方向上的尺寸了。
請記住哪裏出現 align-items
會致使困惑:若是你有一個具備多個 flex 排列行的 flex 容器,那麼每個 flex 排列行都會像一個新的 flex 容器同樣,(該行的)最高的 flex 子元素將會決定哪一行的全部 flex 子元素高度。
除了設置拉伸的初始值以外,你也能夠給 align-items
屬性設置一個值 flex-start
,在這種狀況下 flex 子元素將會在容器的開始之處排列同時也不會拉伸。
flex 子元素排列在交叉軸的開始之處(放大預覽)
設置值 flex-end
將會把它們(flex 子元素)移到交叉軸的結束之處。
flex 子元素排列在交叉軸的結束之處(放大預覽)
若是你使用值 center
,那 flex 子元素將會排列在交叉軸中央:
flex 子元素排列在交叉軸中央(放大預覽)
咱們也能夠設置依據文字基準線排列。這將會確保(flex 子元素)以文字的基準線排列,而不是盒子的邊框。
根據文字基準線排列(放大預覽)
你能夠嘗試使用這個 demo 中的值:
HTML:
<div class="controls">
<select id="alignMe">
<option value="stretch">stretch</option>
<option value="flex-start">flex-start</option>
<option value="flex-end">flex-end</option>
<option value="center">center</option>
<option value="baseline">baseline</option>
</select>
</div>
<div class="container" id="container">
<div class="item">One</div>
<div class="item">Two Two</div>
<div class="item large">Three Three Three</div>
</div>複製代碼
CSS:
body {
padding: 20px;
font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}
* {box-sizing: border-box;}
p {
margin: 0 0 1em 0;
}
.container {
border: 5px solid rgb(111,41,97);
border-radius: .5em;
padding: 10px;
display: flex;
height: 40vh;
}
.item {
padding: 10px;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
}
.large {
font-size: 150%;
}
.controls {
background-color: rgba(0,0,0,.1);
padding: 10px;
border-radius: .5em;
border: 1px solid rgba(0,0,0,.2);
margin: 0 0 2em 0
}
.controls select {
font-size: .9em;
}複製代碼
JacaScript:
var align = document.getElementById("alignMe");
alignMe.addEventListener("change", function (evt) {
document.getElementById("container").style.alignItems = evt.target.value;
});複製代碼
能夠看由 Rachel Andrew (@rachelandrew) 建立的在 CodePen 上的展現:Smashing Flexbox Series 2: align-items
align-items
意味着你能夠一次設置全部的 flex 子元素。這個操做的真正原理是對全部的 flex 子元素一一設置其 align-self
值。固然你也能夠任意單一的 flex 子元素設置 align-self
值來使其與同一個 flex 容器的其它 flex 子元素不同。
在下面的例子中,我使用了 align-items
屬性來設置 flex 子元素組的排列方式是 center
,可是同時也給第一個和最後一個設置了 align-self
屬性來改變他們的排列方式。
HTML:
<div class="container" id="container">
<div class="item">One</div>
<div class="item">Two Two</div>
<div class="item">Three Three Three</div>
</div>複製代碼
CSS:
body {
padding: 20px;
font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}
* {box-sizing: border-box;}
p {
margin: 0 0 1em 0;
}
.container {
border: 5px solid rgb(111,41,97);
border-radius: .5em;
padding: 10px;
display: flex;
height: 40vh;
align-items: center;
}
.item {
padding: 10px;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
}
.item:first-child {
align-self: flex-end;
}
.item:last-child {
align-self: stretch;
}複製代碼
能夠看由 Rachel Andrew (@rachelandrew) 建立的在 CodePen 上的展現: Smashing Flexbox Series 2: align-self
一個很常見的問題是爲何不能在主軸上排列單個元素或元素組? 爲何在主軸上沒有 -self
排列屬性?若是你認爲 justify-content
和 align-content
的做用是關於空餘空間分佈的,那麼它們沒有單獨的排列方法的理由就顯而易見了。咱們將flex 子元素做爲一整個組進行處理,並以某種方式分配可用空間——在組的開頭及結尾或 flex 子元素之間。
想一想 justify-content
和 align-content
在 CSS Gird 佈局中如何起做用也是頗有幫助的。這兩個屬性用於描述在 gird 容器和 gird 塊之間的空餘空間如何分配。再次地,咱們將 gird 塊看成一個組,而後這些屬性決定他們之間的全部額外空間。正如咱們在 Gird 和 Flexbox 中展現的做用那樣,咱們不能指定某一個元素去作一些不同的事情。不過,有一個方法能夠實現你想要的在主軸上相似 self
屬性的佈局,那就是使用自動外邊距。
若是你曾經在 CSS 中將一個塊級元素居中(就像將頁面主元素的容器經過將它的左右外邊距設置爲 auto
),那麼你就已經有了如何設置自動外邊距的經驗了。當一個外邊距的值設置爲 auto 時,它(外邊距)會盡量地嘗試在其所指的方向上變大。在使用外邊距將一個塊級元素居中時,咱們將其左右的外邊距都設置爲了 auto;它們(左右外邊距)都會盡量地佔據空間因而就將塊級元素擠到了中間。
在 Flexbox 中使用自動外邊距來排列主軸上的單個元素或者一組元素的效果很是好。在下面的例子中,咱們實現了一個共同的設計模式。我有一個使用 Flexbox 的導航欄,其子元素以行的形式排列同時使用了默認值 justify-content: start
。我想讓最後的那個子元素和其它子元素分開並展現在 flex 排列行的最後面——假設該行有足夠的空間。
我定位到了那個元素而且把它的 margin-left 屬性設置成了 auto。這意味着它的外邊距將會盡量地佔用它左邊的空間,這意味着那個子元素被推到了最右邊。
HTML:
<div class="container" id="container">
<div class="item">One</div>
<div class="item">Two Two</div>
<div class="item push">Three Three Three</div>
</div>複製代碼
CSS:
body {
padding: 20px;
font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}
* {box-sizing: border-box;}
p {
margin: 0 0 1em 0;
}
.container {
border: 5px solid rgb(111,41,97);
border-radius: .5em;
padding: 10px;
display: flex;
}
.item {
padding: 10px;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
}
.push {
margin-left: auto;
}複製代碼
能夠看由 Rachel Andrew (@rachelandrew) 建立的在 CodePen 上的展現: Smashing Flexbox Series 2: alignment with auto margins
若是你在主軸上使用了自動外邊距,那 justify-content
將不會有任何做用,由於自動外邊距將會佔據全部以前用在 justify-content
上的空間。
每個排列方法詳細來講都會有一個回退排列,它會說明在你請求的排列方式沒法實現時會發生什麼。舉個例子,若是在你的 flex 容器中只有一個子元素但你聲明瞭 justify-content: space-between
,會發生什麼?答案是(該屬性的)回退排列 flex-start
會讓你惟一的那個子元素排列在 flex 容器的開始之處。對於 justify-content: space-around
,回退排列 center
將會被使用。
在如今的規範中你不能改變回退排列的值,因此若是你但願 space-between
的回退值是 center
而不是 flex-start
的話,並無方法能實現。這是 一份規範筆記,它描述了將來版本可能會支持這種方式。
最新的一個添加到盒子元素排列規範的是使用
和
關鍵詞的關於安全和非安全的排列的概念。
看下面的代碼,最後一個元素相較於容器太寬了同時是 unsafe 排列而且 flex 容器是在頁面左邊的,當子元素溢出界面以外時,其被裁減了。
.container {
display: flex;
flex-direction: column;
width: 100px;
align-items: unsafe center;
}
.item:last-child {
width: 200px;
}
複製代碼
不安全的排列將會按照你定義的排列但可能致使界面數據丟失(放大預覽)
安全的排列將會保護界面數據免於丟失,方式是經過從新移動溢出區間到其餘地方:
.container {
display: flex;
flex-direction: column;
width: 100px;
align-items: safe center;
}
.item:last-child {
width: 200px;
}
複製代碼
安全的排列會嘗試避免數據丟失(放大預覽)
這些關鍵詞如今還不多有瀏覽器支持(譯者注:自測 Chrome 69 已支持),不過,它展現了在盒子元素排列規範中帶給了 Flexbox 額外的控制方式。
HTML:
<div class="container" id="container">
<div class="item">One</div>
<div class="item">Two Two</div>
<div class="item">Three Three Three</div>
</div>複製代碼
CSS:
body {
padding: 20px;
font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}
* {box-sizing: border-box;}
p {
margin: 0 0 1em 0;
}
.container {
border: 5px solid rgb(111,41,97);
border-radius: .5em;
padding: 10px;
display: flex;
flex-direction: column;
width: 100px;
align-items: safe center;
}
.item {
padding: 10px;
background-color: rgba(111,41,97,.3);
border: 2px solid rgba(111,41,97,.5);
}
.item:last-child {
width: 200px;
}複製代碼
能夠看由 Rachel Andrew (@rachelandrew) 建立的在 CodePen 上的展現: Smashing Flexbox Series 2: safe or unsafe alignment
Flexbox 的排列屬性最初以列表的方式出現,可是如今它們有了本身的規範同時也適用於其它的佈局環境。這裏是一些小知識可能幫助你如何在 Flexbox 中使用它們:
justify-
適用於主軸,align-
適用於交叉軸;align-content
和 justify-content
時你須要空餘空間;align-content
和 justify-content
屬性面向的是子元素組、做用是分享空間。所以,你不能指定一個特定的子元素同時它們也沒有對應 -self
排列屬性;align-items
屬性設置了整個子元素組的全部 align-self
值。能夠經過設置 align-self
屬性來設置一個特定的子元素。若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。