CSS 中的 flex 布局

曹至梧 2018-08-01 01:23 更新
  1. 简介
  2. 容器属性
  3. 条目属性
  4. 条目分布与对齐
  5. column
  6. 常用布局

1. 简介

flex 是 css 中新添加的一种布局特性,它的表现,还是像一维的流式布局。但是,因为加了几个控制属性,所以很多时候可以很直接地使用它来代替浮动,来达到想要的效果,并且,它不像浮动会有“清除浮动”的问题。

它的出现,也使得我们在使用“表格布局”,“浮动布局”之外,又有了一个新选择。

机制上来说,可以把 flex 看成是三个部分:

一个完整的例子是:

<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
<meta charset="utf-8" />
<title>Flex布局</title>
<style type="text/css">
  .wrapper {
    background-color: #ccc;
    height: 100px;
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    flex-flow: row wrap;
    justify-content: center;
    align-items: center;
  }
  .wrapper > div {
    border: 1px solid gray;
    padding: 10px;
    box-sizing: border-box;
    width: 40%;
    flex-basis: auto;
    flex-grow: 1;
    flex-shrink: 0;
    flex: 1 0 auto;
  }
</style>
</head>
<body>
  <div class="wrapper">
    <div>A</div>
    <div>B</div>
    <div>C</div>
  </div>
</body>
</html>

别看属性一列不少,同样的结果,用浮动不一定比它简单,明了的。

上面例子中的 wrapper 就是“容器”,它的三个直接子节点 div 就是“条目”了。

2. 容器属性

先不说对齐,那么容器属性本身还是比较简单的,只有 3 + 1 个:

flex-flowflex-directionflex-wrap 的简写。

display 不用说了。 flex-wrap 表示条目是否换行,默认值是 nowrap ,这种情况下,根据设置宽度要么自动缩小,要么溢出容器。

flex-direction 是定义方向,横,或者竖,再加上是否“逆向”,就是四种情况:

这个设置项,本身是很容易理解的。 row 就从左到右, column 就从上到下,加上 -reverse 就反过来。但是,这个设置项会直接影响后面的“条目属性”,及“对齐属性”的意义。我不太想去思考“主轴”,“交叉轴”这类比较正统的概念,暂且,只从 row 去认识 flex 就好了,然后,再单独看看 column 下又是怎样的表现。

3. 条目属性

这块相对来说,就比较简单了,还是 3 + 1 个:

flexflex-grow flex-shrink flex-basis 的缩写。

这些值定义的行为,主要影响 flex 元素与容器空白的关系。简单来说,如果一个容器宽是 100 ,但是里面所有的元素宽加起来只有 80 ,剩下的 20 如何处理的事。

flex-basis 是“宽度”的意思, auto 会取元素的 width 值,即,如果有值,则是一个定宽,否则,根据里面的内容决定宽度。

flex-growflex-shrink ,有点像“橡皮长度”的感觉,前者是伸长,后者是缩短。各个无素的这个值,表示它们之间程度的相对值,比如 A 的 flex-grow 是 1 ,而 B 的 flex-grow 是 2 ,那么空白的分配中, B 会比 A 占 得更多。

<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
<meta charset="utf-8" />
<title>Flex布局</title>
<style type="text/css">
  .wrapper {
    background-color: #ccc;
    padding: 10px;
    box-sizing: border-box;
    height: 100px;
    width: 300px;
    display: flex;
  }
  .wrapper > div {
    border: 1px solid black;
    background-color: red;
    width: 50px;
    flex: 1 0 auto;
  }
</style>
</head>
<body>
  <div class="wrapper">
    <div>A</div>
    <div>B</div>
    <div>C</div>
  </div>
</body>
</html>

上的例子中,三个子元素会填充满 wrapper ,像是浮动中的 width: 33.33% 的效果一样,而且,高度会自动填充为容器的高。

flex 跟容器的 flex-wrap 一起,会有不一样的作用:

<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
<meta charset="utf-8" />
<title>Flex布局</title>
<style type="text/css">
  .wrapper {
    background-color: #ccc;
    padding: 10px;
    box-sizing: content-box;
    height: 100px;
    width: 300px;
    display: flex;
    flex-wrap: wrap;
  }
  .wrapper > div {
    border: 1px solid black;
    background-color: red;
    width: 150px;
    flex: 1 0 auto;
  }
</style>
</head>
<body>
  <div class="wrapper">
    <div>A</div>
    <div>B</div>
    <div>C</div>
  </div>
</body>
</html>

上面的例子,因为设置了“可换行”,并且子元素“可伸长”,在容器高度一定,一行放不下两个子元素的情况下, A,B,C 三块,会变成从上往下排列了。

如果把子元素的 width: 150px 改成 width: 120 ,结果就是 A,B 在同一行,每个宽 150 , C 独立一行,宽 300 。记住,宽度变成是因为 flex-grow 作用。如果想要简单的 float: left 那样的效果,只需要 flex-grow: 0 就好了。

4. 条目分布与对齐

水平分布,是在容器中使用 justify-content 属性控制,在子元素没有伸缩的情况下,子元素在足够大的容器中如何排列的行为,简单列几个取值是:

垂直对齐方面,是在容器中使用 align-items 来控制,这个属性与子元素的 height 有关系,常见的几个取值:

例子:

<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
<meta charset="utf-8" />
<title>Flex布局</title>
<style type="text/css">
  .wrapper {
    background-color: #ccc;
    padding: 10px;
    box-sizing: content-box;
    height: 100px;
    width: 800px;
    display: flex;
    flex-wrap: nowrap;
    justify-content: space-between;
    align-items: flex-start;
  }
  .wrapper > div {
    border: 1px solid black;
    background-color: red;
    width: 120px;
    height: auto;
    flex: 0 0 auto;
  }
</style>
</head>
<body>
  <div class="wrapper">
    <div>A</div>
    <div><span style="font-size: 50px;">B</span></div>
    <div>C</div>
  </div>
</body>
</html>

5. column

当把容器的 flex-direction 默认值 row 改成 column 之后,很多属性的行为都会不同了。

我们之前说的什么“水平居中”,“左对齐”之类的说法,其实在 column 场景下,是对不上的。

row 的子元素排列,是从左往右排,沿水平轴。 column 的排列,是从上往下排,沿垂直轴。对应地,很多之前介绍的属性的行为,跟子元素排列的轴是一致的,所以 row 的时候我们说的“水平”,在 column 下就变成“垂直”了。。

flex-growflex-start 也是同样的道理, row 下它们控制宽, column 就变成控制高了。

示例:

<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
<meta charset="utf-8" />
<title>Flex布局</title>
<style type="text/css">
  .wrapper {
    background-color: #ccc;
    padding: 10px;
    box-sizing: content-box;
    height: 100px;
    width: 800px;
    display: flex;
    flex-direction: column;
    flex-wrap: wrap;
    justify-content: flex-start;
    align-items: center
  }
  .wrapper > div {
    border: 1px solid black;
    background-color: red;
    width: 120px;
    height: 30px;
    flex: 1 0 auto;
  }
</style>
</head>
<body>
  <div class="wrapper">
    <div>A</div>
    <div style="width: 200px; height: 50px;"><span style="font-size: 50px;">B</span></div>
    <div>C</div>
  </div>
</body>
</html>

columnflex ,有点像排版中的“分栏”,之前, css 应该是直接做不出来的吧。

6. 常用布局

6.1. 左右

<div style="display: flex; height: 300px;">
    <div style="flex: 0 0 200px; background-color: lightblue;"></div>
    <div style="flex: 1 0 auto; background-color: yellow;"></div>
</div>

6.2. 右左

<div style="display: flex; height: 300px;">
    <div style="flex: 0 0 200px; background-color: lightblue;"></div>
    <div style="flex: 1 0 auto; background-color: yellow;"></div>
</div>

6.3. 左中右

<div style="display: flex; height: 300px;">
    <div style="flex: 0 0 200px; background-color: lightblue;"></div>
    <div style="flex: 1 0 auto; background-color: yellow;"></div>
    <div style="flex: 0 0 200px; background-color: lightblue;"></div>
</div>

6.4. 从左到右

<div style="display: flex; height: auto; flex-wrap: wrap;">
    <div style="flex: 0 0 100px; background-color: lightblue; height: 100px; margin: 10px;"></div>
    <div style="flex: 0 0 100px; background-color: lightblue; height: 100px; margin: 10px;"></div>
    <div style="flex: 0 0 100px; background-color: lightblue; height: 100px; margin: 10px;"></div>
    <div style="flex: 0 0 100px; background-color: lightblue; height: 100px; margin: 10px;"></div>
    <div style="flex: 0 0 100px; background-color: lightblue; height: 100px; margin: 10px;"></div>
    <div style="flex: 0 0 100px; background-color: lightblue; height: 100px; margin: 10px;"></div>
    <div style="flex: 0 0 100px; background-color: lightblue; height: 100px; margin: 10px;"></div>
    <div style="flex: 0 0 100px; background-color: lightblue; height: 100px; margin: 10px;"></div>
    <div style="flex: 0 0 100px; background-color: lightblue; height: 100px; margin: 10px;"></div>
</div>

6.5. 均匀分布(不贴边)

<div style="display: flex; height: auto; justify-content: space-around;">
    <div style="flex: 0 0 100px; background-color: lightblue; height: 100px;"></div>
    <div style="flex: 0 0 100px; background-color: lightblue; height: 100px;"></div>
    <div style="flex: 0 0 100px; background-color: lightblue; height: 100px;"></div>
</div>

6.6. 均匀分布(贴边)

<div style="display: flex; height: auto; justify-content: space-around;">
    <div style="flex: 0 0 100px; background-color: lightblue; height: 100px;"></div>
    <div style="flex: 0 0 100px; background-color: lightblue; height: 100px;"></div>
    <div style="flex: 0 0 100px; background-color: lightblue; height: 100px;"></div>
</div>

6.7. 分栏

A
B
C
<div style="display: flex; height: 300px; flex-flow: column wrap">
    <div style="flex: 0 0 100px; background-color: lightblue; width: auto; margin: 10px;">A</div>
    <div style="flex: 0 0 100px; background-color: lightblue; width: auto; margin: 10px;">B</div>
    <div style="flex: 0 0 100px; background-color: lightblue; width: auto; margin: 10px;">C</div>
</div>
评论
©2010-2018 zouyesheng.com All rights reserved. Powered by GitHub , txt2tags , MathJax