现在大部分浏览器都支持flexbox布局方法。react和react-native中几乎全部采用flex来布局。简单总结下常用属性供参考。
1. flex-direction 属性
先以一个简单的nav为例:
HTML
<nav class="main-nav">
<ul>
<li><a href="#">Work</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
CSS
body {
background: white;
font-family: 'Open Sans', sans-serif;
}
.main-nav li {
width: 100px;
}
.main-nav a {
text-decoration: none;
color: black;
font-size: 21px;
font-weight: 600;
color: #00a9d9;
}
.main-nav a: hover {
text-decoration: underline;
}
效果
现在加上以下属性
.main-nav ul {
list-style: none;
display: flex;
}
变为
flex会让<ul>
这个容器成为一个具有flex功能的block-level容器,并且会影响到它的子元素的布局表现。
如果想让<ul>
成为一个inline元素,可以写成display: inline-flex
,这样它仍然具有flex container的效果,同时也表现为一个inline元素,就像<img>
一样。
当加上display: flex;
后,<li>
元素由垂直排列变成了水平排列。这是因为flex
的flex-direction
属性的默认值为row
,如果我们添加上
.main-nav ul {
list-style: none;
display: flex;
flex-direction: column
}
能看到<li>
元素又变为了垂直排列。
flex-direction
的值除了row,column
还可以是row-reverse
和column-reverse
。
flex-direction
这个属性在用在响应式web design上非常便利,配合media-query
可以根据屏幕大小,将元素从水平排列变成垂直排列。
需要注意的是flexbox属性, 包括 flex-direction, 在有些浏览器上需要加prefixes,所以用之前一定要查查浏览器支持情况, can I use 这个网站就可以。还有个很方便的方法是用auto prefixer post CSS工具可以自动添加前缀,省去很多麻烦。
2. order属性
先添加加上header,main和footer,为了明显用背景色块来区分。
HTML
<body>
<header class="main-header">Header</header>
<nav class="main-nav">
<ul>
<li><a href="#">Work</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
<main class="main-content">Content</main>
<footer class="main-footer">Footer</footer>
</body>
CSS
.main-header {
background: #B61E32;
padding: 10px;
}
.main-content {
background: #F7CE2B;
min-height: 40vh;
padding: 10px;
}
.main-footer {
background: #ABC999;
padding: 10px;
}
效果
然后将整个body都设为flex容器
body {
display: flex;
flex-direction: column;
}
此时,所有的flex元素默认order都是0,所以会按照元素的顺序来渲染,如果将某元素的order改成1:
.main-nav {
order: 1;
}
可以看到main-nav元素跑到了最下面。
当然,还能设为负数,试试改为-1。
3. justify-content属性
html
<body>
<article class="fake-article">
<header>
<h1>Fake Article</h1>
</header>
<p>Vestibulum id ligula porta felis euismod semper. Curabitur blandit tempus porttitor. Nullam quis risus eget urna mollis ornare vel eu leo. Donec ullamcorper nulla non metus auctor fringilla.</p>
</article>
<article class="not-real">
<header>
<h1>Not Real</h1>
</header>
<p>Nullam quis risus eget urna mollis ornare vel eu leo. Etiam porta sem malesuada magna mollis euismod.</p>
</article>
<article class="phoney">
<header>
<h1>Phoney</h1>
</header>
<p>Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Donec id elit non mi porta gravida at eget metus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.</p>
</article>
</body>
css
:root {
height: 100%;
}
body {
font-family: 'Open Sans', sans-serif;
margin: 0;
min-height: 100%;
background: #333;
}
h1 {
font-weight: 600;
margin: 0 0 5px 0;
}
p {
margin: 5px 0;
}
article {
box-sizing: border-box;
background: #FFF;
margin: 5px;
}
body {
display: flex;
flex-direction: column;
}
效果:
justify-content这个属性会影响children沿着flex-direction
方向的排列和空间分配。当前的flex-direction
是column
。所以这个属性会影响子元素在从上到下的竖直方向上,如何分配多余空间,但是并不会改变元素本身的实际大小。
-
flex-start:
justify-content
默认值是flex-start
,意思是所有元素都是从起始点开始向下排列。 - flex-end: 设成flex-end,可以看到子元素们会一起从结束点开始排列。
body {
display: flex;
flex-direction: column;
justify-content: flex-end;
}
效果:
- center: 设成center,他们就会一起挤在中间的位置,还记得刚开始学css的时候总是为如何才能实现真正的vertical-align苦恼,有了flexbox终于能非常简单的实现了。
- space-between: 第一个元素在start位置,最后一个元素在end位置,中间元素均等间隙排列。
- space-around: 会平均分配剩余空间给所有元素间隙,但第一个元素的前面和最后一个元素的后面则是中间的间隙距离一半。
4. align-items 和 align-self
justify-content
是会影响子元素沿着flex-direction
方向的排列,而align-item则会影响子元素与flex-direction
方向垂直的方向上的排列情况。
为了更直观的说明,将flex-direction
改为row
,并将article
的flex
设为1,意思是所有article所占宽度总相等。
body {
display: flex;
flex-direction: row;
}
article {
box-sizing: border-box;
background: #FFF;
margin: 5px;
flex: 1;
}
- 这样改之后会发现,三个ariticle元素虽然内容高度不同,但box都变成了100% height,这是因为align-items的默认值是
stretch
,就是会用掉所有的垂直方向上的多余空间。
- 若将align-items的值设为”flex-start“,如图,就会变成不同高度。
body {
display: flex;
flex-direction: row;
align-items: flex-start;
}
- 相似的还有 flex-end, center。
- 还有一个值是 baseline。就是根据首个元素的baseline来进行对齐。
align-items是用于container的属性,统一设置子元素的排列规则。如果想单独设置某一个子元素的布局规则,可以使用”align-self“。
比如给第二个article元素加上class.not-real
.not-real {
align-self: flex-end ;
}
效果如图,在不影响其他元素的情况下,改变了.not-real。
5. flex-basis,flex-shrink,flex-grow
HTML
<body>
<h1 class="title-1">title1</h1>
<h1 class="title-2">title2</h1>
<h1 class="title-3">title3</h1>
</body>
CSS
body {
margin: 0;
font-family: 'Open Sans', sans-serif;
margin: 0;
color: #eec965;
display: flex;
}
.title-1 {
background: #dd5f40;
}
.title-2 {
background: #3d483a;
}
.title-3 {
background: #468e5d;
}
效果
5.1 flex-basis
flex-basis可以用来定义子元素在flex-direction方向上的最优size。
比如先定义title1的width
.title-1 {
background: #dd5f40;
width: 200px
}
现在title1的宽度变为了200px
但如果加上
.title-1 {
background: #dd5f40;
width: 200px;
flex-basis: 150px;
}
title1的box宽度变成了150px。
flex-basis属性覆盖了width属性(但flex-basis不会让元素超过max-width或者小于min-width)。在flex-basis没有规定值得情况下,默认为auto。那么元素在flex-direction方向上的宽度,在这里就是指的width(因为这里的flex-direction是row),如果width没有规定值,那么就默认为元素的内容宽度,这里就是title1这几个字的宽度。
总之, Flex-basis就是在有足够空间的情况下,flex-direction上的最优宽度。
5.2 flex-grow
先给每个title都设定一个flex-basis:
.title-1 {
background: #dd5f40;
flex-basis: 120px;
}
.title-2 {
background: #3d483a;
flex-basis: 40px;
}
.title-3 {
background: #468e5d;
flex-basis: 100px;
}
现在在row方向上,很明显是有剩余空间的。
此时,flex-grow就决定了如何分配这些空间。没有给值得时候,flex-grow默认为0。
如果:
.title-1 {
background: #dd5f40;
flex-basis: 120px;
flex-grow: 1
}
现在title-1占用了全部的多余空间。
如果把titile2的flex-grow变成2,那么titile-1会占用总的多余空间的1/3,title2占用2/3。
5.3 flex-shrink
flex-shrink会定义当总的flex-basis之和大于能够被分配的空间时,该如何缩减这些子元素。
默认的flex-shrink值是1,意思是每个元素都同等份额的缩减宽度。
比如给title1,title2,title3的flex-basis都设为200px,当总宽度小于600时:
给title1的flex-shrink设为2,那么title1减少的宽度将是其他元素的2倍,但如果设为100,1000,并不会奏效,因为不会让元素的宽度小于元素内容的宽度。
如果不想让元素的宽度因为总宽度的改变而减少,可以给flex-shrink的宽度设为0,若将所有元素的宽度都设为0,那么为导致overflow。
5.4 flex-basis,flex-grow,flex-shrink的缩写规范
注释部分写了该缩写对应的flex-grow,flex-shrink,flex-basis。
.title-1 {
background: #dd5f40;
flex: 1;
/* flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
*/
}
当flex:1时,flex-grow为1,flex-shrink为1(因为是默认值),比较奇怪的是flex-basis此时为0(其默认值应该为auto)。
.title-2 {
background: #3d483a;
flex: 20px;
/* flex-grow: 1;
flex-shrink: 1;
flex-basis: 20px;
*/
}
flex:20px时,很明显只有flex-basis可以规定具体size。flex-grow是1,这也有点奇怪,因为flex-grow默认值是0。
.title-3 {
background: #468e5d;
flex: 0 80px;
/* flex-grow: 0;
flex-shrink: 1;
flex-basis: 80px;
*/
}
当先给一个无单位的值,再给一个有单位的值时,flex-grow得到第一个值,flex-basis得到第二个值。flex-shrink保持默认值。
其实最常用的方法还是,h1 { flex: 1; }
这样的缩写方式。这样会让所有元素同等的获得多余空间,总是保持宽度一致且填满空间。