- 原文地址: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、前端、后端、区块链、产品、设计、人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划、官方微博、知乎专栏。