Skip to content

第十章 css3FLEX 弹性盒模型

A.了解弹性

1.弹性盒模型你真的需要掌握

2.浏览器调试功能的使用

3.弹性布局与传统布局响应对比

Terms:display: flex,flex:1

html
<style>
  * {
  padding: 0;
  margin: 0;
 }
 div.container {
  display: flex;
  height: 100vh;
  justify-content: space-evenly;
 }
 div.container div {
  border: solid 1px #ddd;
 }
 div.container div:nth-of-type(1) {
  min-width: 80px;
  background: #4e9166;
 }
 div.container div:nth-of-type(2) {
  flex: 1;
  background: #ddd;
 }
</style>

<div class="container">
 <div></div>
 <div></div>
</div>

4.传统方式布局微信客户端界面

html
传统布局
<style>
 * {
  padding: 0;
  margin: 0;
 }
 main,
 footer {
  border: solid 1px #ddd;
  box-sizing: border-box;
 }
 main {
  background: #ddd;
  height: 100vh;
  padding-bottom: 55px;
  background-clip: content-box;
 }
 footer {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  height: 50px;
 }
 footer div {
  width: 33%;
  float: left;
  text-align: center;
  line-height: 3em;
  height: 100%;
  background: linear-gradient(to bottom, #f3f3f3, #eee, #f3f3f3);
  cursor: pointer;
 }
 footer div:nth-child(n + 2) {
  border-left: solid 1px #ddd;
 }
</style>

<body>
 <main></main>
 <footer>
  <div>1</div>
  <div>2</div>
  <div>3</div>
 </footer>
</body>

5.使用弹性盒模型布局微信客户端

html
<!-- 弹性布局 -->
<style>
 * {
  padding: 0;
  margin: 0;
 }
 body {
  display: flex;
  flex-direction: column;
  height: 100vh;
 }
 main {
  border: solid 1px #ddd;
  background: #ddd;
  background-clip: content-box;
  margin-bottom: 5px;
  flex: 1;
 }
 footer {
  flex: 0;
  display: flex;
  justify-content: space-evenly;
  border-top: solid 1px #ddd;
  min-height: 50px;
 }
 footer div {
  flex: 1;
  text-align: center;
  line-height: 3em;
  background: linear-gradient(to bottom, #f3f3f3, #eee, #f3f3f3);
  cursor: pointer;
 }
 footer div:nth-child(n + 2) {
  border-left: solid 1px #ddd;
 }
</style>
<body>
 <main></main>
 <footer>
  <div>1</div>
  <div>2</div>
  <div>3</div>
 </footer>
</body>

B.弹性盒子

6.声明弹性盒子的几种方式

Terms:display:flex

  • 容器盒子里面包含着容器元素,使用  display:flex或  display:inline-flex声明为弹性盒子
html
<!-- 声明块级弹性盒子 -->
<style>
 * {
  padding: 0;
  margin: 0;
 }
 article {
  height: 150px;
  margin-left: 100px;
  margin-top: 100px;
  outline: solid 5px silver;
  display: flex;
  padding: 20px;
 }
 article div {
  outline: solid 5px blueviolet;
  text-align: center;
  font-size: 28px;
  line-height: 5em;
  width: 300px;
 }
</style>

<article>
 <div>1</div>
 <div>2</div>
 <div>3</div>
</article>

html
<!-- 声明内联级弹性盒子 -->
<style>
 ...
 article {
   ...
   display: inline-flex;
   ...
 }
 ...
</style>

7.改变弹性元素方向

Terms:flex-direction

  • 用于控制盒子元素排列的方向。
描述
row从左到右水平排列元素(默认值)
row-reverse从右向左排列元素
column从上到下垂直排列元素
column-reverse从下到上垂直排列元素
html
<!-- row-reverse -->
<style>
 * {
  padding: 0;
  margin: 0;
 }
 body {
  margin: 100px;
  font-size: 14px;
  color: #555;
 }
 article {
  width: 500px;
  border: solid 5px silver;
  display: flex;
  box-sizing: border-box;
  padding: 10px;
  flex-direction: row-reverse;
 }
 article * {
  border: solid 5px blueviolet;
  padding: 10px;
  margin: 10px;
 }
</style>

<article>
 <h4>hd</h4>
 <span>hdcms.com</span>
 <p>houdunren.com</p>
</article>

html
<!-- column-reverse -->
<style>
 article {
  flex-direction: column-reverse;
 }
</style>

8.控制弹性元素溢出换行处理

Terms:flex-wrap:wrap

  • flex-wrap 属性规定 flex 容器是单行或者多行,同时横轴的方向决定了新行堆叠的方向。
选项说明
nowrap元素不拆行或不拆列(默认值)
wrap容器元素在必要的时候拆行或拆列。
wrap-reverse容器元素在必要的时候拆行或拆列,但是以相反的顺序

8.1 行元素换行

html
<style>
 * {
  padding: 0;
  margin: 0;
  outline: solid 1px silver;
  padding: 10px;
  margin: 10px;
 }
 head {
  display: block;
 }
 body {
  font-size: 14px;
  color: #555;
 }
 article {
  width: 500px;
  border: solid 5px silver;
  box-sizing: border-box;
  padding: 10px;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
 }
 article div {
  border: solid 5px blueviolet;
  padding: 30px 80px;
  margin: 10px;
  text-align: center;
  font-size: 28px;
 }
</style>

<article>
 <div>1</div>
 <div>2</div>
 <div>3</div>
</article>

8.2 水平排列反向换行

html
<style>
 flex-direction: row;
 flex-wrap: wrap-reverse;
</style>

8.3 垂直元素换行

html
<style>
 flex-direction: column;
 flex-wrap: wrap;
</style>

8.3 垂直元素反向换行

html
<style>
 flex-direction: column;
 flex-wrap: wrap-reverse;
</style>

9.统一设置元素排列方式与换行

Term:flex-flow

html
<style>
 flex-flow: row-reverse wrap-reverse;
</style>

10.主轴与交叉轴详解

  • 根据 row,column,reverse 来确定主轴,交叉轴的方向(x,y 轴,水平轴,垂直轴)

10.1 水平排列

  • flex-flow: row wrap

  • flex-flow: row-reverse wrap-reverse

10.2 垂直排列

  • flex-flow: column wrap

11.主轴元素的多种排列方式

Terms:justify-content

  • 用于控制元素在主轴上的排列方式,再次强调是主轴的排列方式。
选项说明
flex-start元素紧靠主轴起点
flex-end元素紧靠主轴终点
center元素从弹性容器中心开始
space-between第一个元素靠起点,最后一个元素靠终点,余下元素平均分配空间
space-around每个元素两侧的间隔相等。所以,元素之间的间隔比元素与容器的边距的间隔大一倍
space-evenly元素间距离平均分配

11.1 justify-content: flex-end

html
<style>
 * {
  padding: 0;
  margin: 0;
  padding: 10px;
  margin: 10px;
 }
 body {
  font-size: 14px;
  color: #555;
 }
 article {
  border: solid 5px silver;
  box-sizing: border-box;
  display: flex;
  flex-flow: row wrap;
  justify-content: flex-end;
 }
 article div {
  width: 80px;
  border: solid 5px blueviolet;
  text-align: center;
  font-size: 28px;
 }
</style>

<article>
 <div>1</div>
 <div>2</div>
 <div>3</div>
</article>

11.2 space-evenly

html
<style>
 article {
  border: solid 5px silver;
  box-sizing: border-box;
  display: flex;
  flex-flow: row wrap;
  justify-content: space-evenly;
 }
</style>

11.3 垂直排列时对齐到主轴终点

html
<style>
 article {
  height: 400px;
  border: solid 5px silver;
  box-sizing: border-box;
  display: flex;
  flex-flow: column wrap;
  justify-content: flex-end;
 }
</style>

12.交叉轴元素的多种排列方式

Terms:align-items

  • 元素在交叉轴上有行的概念,理解这个概念会对理解 align-items 与 align-content 有更好的帮助。
    • align-item 是控制元素在行上的排列
    • align-content 是控制行在交差轴上的排列

  • align-items

    选项说明
    stretch元素被拉伸以适应容器(默认值)
    center元素位于容器的中心
    flex-start元素位于容器的交叉轴开头
    flex-end元素位于容器的交叉轴结尾

12.1 拉伸适应交叉轴

  • 如果设置了 width | height | min-height | min-width | max-width | max-height ,将影响 stretch 的结果,因为 stretch 优先级你于宽高设置。
html
<style>
 * {
  padding: 0;
  margin: 0;
  padding: 10px;
  margin: 5px;
 }
 head {
  display: block;
 }
 body {
  font-size: 14px;
  color: #555;
 }
 article {
  height: 200px;
  border: solid 5px silver;
  box-sizing: border-box;
  display: flex;
  flex-direction: row;
  align-items: stretch;
 }
 article div {
  width: 80px;
  border: solid 5px blueviolet;
  text-align: center;
  font-size: 28px;
 }
</style>

<article>
 <div>1</div>
 <div>2</div>
 <div>3</div>
</article>

12.2 对齐到交叉轴的顶部

html
<style>
 flex-direction: row;
 align-items: flex-start;
</style>

12.3 对齐到交叉轴底部

html
<style>
 flex-direction: row;
 align-items: flex-end;
</style>

12.4 对齐到交叉轴中心

html
<style>
 flex-direction: row;
 align-items: center;
</style>

12.5 纵向排列时交叉轴排列

html
<style>
 * {
  padding: 0;
  margin: 0;
  padding: 10px;
  margin: 5px;
 }

 article {
  height: 400px;
  border: solid 5px silver;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: center;
 }

 article div {
  height: 50px;
  min-width: 100px;
  border: solid 5px blueviolet;
  text-align: center;
  font-size: 28px;
 }
</style>

<article>
 <div>1</div>
 <div>2</div>
 <div>3</div>
</article>

13.多行元素在交叉轴的排列方式

Terms:align-content

  • 只适用于多行显示的弹性容器,用于控制行(而不是元素)在交叉轴上的排列方式。
选项说明
stretch将空间平均分配给元素
flex-start元素紧靠主轴起点
flex-end元素紧靠主轴终点
center元素从弹性容器中心开始
space-between第一个元素靠起点,最后一个元素靠终点,余下元素平均分配空间
space-around每个元素两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍
space-evenly元素间距离平均分配

13.1 水平排列在交叉轴中居中排列

html
<style>
 * {
  padding: 0;
  margin: 0;
  padding: 10px;
  margin: 5px;
 }
 article {
  height: 500px;
  border: solid 5px silver;
  box-sizing: border-box;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: flex-start;
  align-content: center;
 }
 article div {
  width: 90px;
  border: solid 5px blueviolet;
  text-align: center;
  font-size: 28px;
 }
</style>

<article>
 <div>1</div>
 <div>2</div>
 <div>3</div>
</article>

13.2 垂直排列时交叉轴的排列

html
<style>
 * {
  padding: 0;
  margin: 0;
  padding: 10px;
  margin: 5px;
 }
 article {
  height: 300px;
  border: solid 5px silver;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  align-items: flex-start;
  align-content: center;
 }
 article div {
  min-width: 50px;
  min-height: 80px;
  border: solid 5px blueviolet;
  text-align: center;
  font-size: 28px;
 }
</style>

<article>
 <div>1</div>
 <div>2</div>
 <div>3</div>
</article>

C.弹性元素

14.弹性元素(单个)交叉轴控制

Terms:align-self

  • 放在容器盒子中的元素即为容器元素。

    1. 不能使用 float 与 clear 规则
    2. 弹性元素均为块元素
    3. 绝对定位的弹性元素不参与弹性布局
  • align-self:用于控制单个元素在交叉轴上的排列方式,align-items 用于控制容器中所有元素的排列,而 align-self 用于控制一个弹性元素的交叉轴排列。

选项说明
stretch将空间平均分配给元素
flex-start元素紧靠主轴起点
flex-end元素紧靠主轴终点
center元素从弹性容器中心开始
html
<style>
 * {
  padding: 0;
  margin: 0;
  padding: 10px;
  margin: 5px;
 }
 article {
  height: 400px;
  border: solid 5px silver;
  box-sizing: border-box;
  display: flex;
  flex-direction: row;
  align-items: center;
 }
 article div {
  height: 50px;
  min-width: 50px;
  border: solid 5px blueviolet;
  text-align: center;
  font-size: 28px;
 }
 article div:nth-of-type(1) {
  align-self: flex-start;
 }
 article div:nth-of-type(3) {
  align-self: flex-end;
 }
</style>

<article>
 <div>1</div>
 <div>2</div>
 <div>3</div>
</article>

15.元素可用空间分配

Terms:flex-grow

  • 用于将弹性盒子的可用空间,分配给弹性元素。可以使用整数或小数声明。
    • 下例中为三个 DIV 弹性元素设置了 1、3、6 ,即宽度分成 10 等份,第三个元素所占宽度为(宽度/(1+3+6)) X 6。
html
<style>
 * {
  padding: 0;
  margin: 0;
 }

 body {
  padding-left: 50px;
  padding-top: 15px;
 }

 article {
  border: solid 5px silver;
  width: 550px;
  height: 100px;
  display: flex;
  flex-direction: row;
 }

 article * {
  flex-grow: 1;
  width: 100px;
  height: 100px;
  background: blueviolet;
  background-clip: content-box;
  padding: 10px;
  box-sizing: border-box;
  font-size: 35px;
  color: white;
 }
</style>

<article>
 <div>1</div>
 <div>2</div>
 <div>3</div>
</article>

  • 如果弹性元素设置了宽度,将把(弹性盒子-弹性元素宽度和)后按照  flex-grow进行分配
html
<style>
 * {
  padding: 0;
  margin: 0;
  padding: 10px;
  margin: 5px;
 }
 article {
  width: 600px;
  position: relative;
  height: 200px;
  border: solid 5px silver;
  display: flex;
 }
 article div {
  min-height: 80px;
  border: solid 5px blueviolet;
  text-align: center;
  font-size: 28px;
 }
 article div:nth-of-type(1) {
  width: 100px;
  flex-grow: 1;
 }
 article div:nth-of-type(2) {
  width: 100px;
  flex-grow: 3;
 }
 article div:nth-of-type(3) {
  width: 300px;
  flex-grow: 6;
 }
</style>

16.布局小米移动端页面结构(main 占完中间)

html
<style>
 * {
  padding: 0;
  margin: 0;
 }

 body {
  height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
 }

 header {
  height: 60px;
  background-color: blueviolet;
 }

 main {
  flex-grow: 1;
  background-color: #ccc;
 }

 footer {
  height: 60px;
  background-color: #383881;
 }
</style>

<body>
 <header></header>
 <main></main>
 <footer></footer>
</body>

17.元素动态缩小的处理技巧

Terms:flex-shrink

  • 与 flex-grow 相反 flex-shrink 是在弹性盒子装不下元素时定义的缩小值。
    • 下例在 600 宽的弹性盒子中放了 1000 宽的弹性元素。并为最后两个元素设置了缩放,最后一个元素的缩放比例为 500 -( ( (1000-600) / (100X1+400x3+500X6) ) x 3 ) X 500 = 220.9,计算公式说明如下:
    • 缩小比例 = 不足的空间 / (元素 1 宽度 x 缩小比例) + (元素 2 宽度 x 缩小比例)
    • 最终尺寸 = 元素三宽度 - (缩小比例 x 元素 3 的宽度) X 元素宽度
html
<style>
 * {
  padding: 0;
  margin: 0;
 }
 body {
  padding-left: 50px;
  padding-top: 15px;
 }
 article {
  border: solid 5px silver;
  width: 400px;
  height: 120px;
  display: flex;
  padding: 10px;
  box-sizing: content-box;
 }
 article div:nth-child(1) {
  flex-shrink: 0;
 }
 article div:nth-child(2) {
  flex-shrink: 1;
 }
 article div:nth-child(3) {
  flex-shrink: 3;
 }
 article * {
  width: 200px;
  height: 100px;
  overflow: hidden;
  background: blueviolet;
  background-clip: content-box;
  padding: 10px;
  border: solid 1px blueviolet;
  box-sizing: border-box;
  font-size: 30px;
  color: white;
 }
</style>

<article>
 <div>1</div>
 <div>2</div>
 <div>3</div>
</article>

18.主轴的基准尺寸的定义

Terms:flex-basis

  • flex-basis 属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。

  • 可以是长度单位,也可以是百分比。flex-basis 的优先级高于 width、height 属性。

  • 优先级:flex-basis>max-height,min-height>height,width

html
<style>
 * {
  padding: 0;
  margin: 0;
 }
 article {
  width: 600px;
  position: relative;
  height: 150px;
  margin-left: 100px;
  margin-top: 100px;
  outline: solid 5px silver;
  display: flex;
  padding: 20px;
 }
 article div {
  outline: solid 5px blueviolet;
  text-align: center;
  font-size: 28px;
  line-height: 5em;
 }
 article div:nth-of-type(1) {
  flex-basis: 100px;
  width: 200px;
 }
 article div:nth-of-type(2) {
  flex-basis: 200px;
 }
 article div:nth-of-type(3) {
  flex-basis: 200px;
 }
</style>

<article>
 <div>1</div>
 <div>2</div>
 <div>3</div>
</article>

19.弹性元素组规则和定义

Terms:flex

  • flex 是 flex-grow、flex-shrink 、flex-basis 缩写组合。建议使用 flex 面不要单独使用 flex-grow / flew-shrink / flex-basis 。
html
<!-- 下例定义平均分配剩余空间,并不进行尺寸缩小,基础尺寸为 200px。 -->
<style>
 * {
  padding: 0;
  margin: 0;
 }
 article {
  width: 600px;
  position: relative;
  height: 150px;
  margin-left: 100px;
  margin-top: 100px;
  outline: solid 5px silver;
  display: flex;
  padding: 20px;
 }
 article div {
  outline: solid 5px blueviolet;
  text-align: center;
  font-size: 28px;
  line-height: 5em;
  flex: 1 0 100px;
 }
</style>

20.控制弹性元素的排序

Terms:order

  • 用于控制弹性元素的位置,默认为 order:0 数值越小越在前面,可以负数或整数。
html
<style>
 * {
  margin: 0;
  padding: 0;
 }

 body {
  padding-left: 50px;
  padding-top: 15px;
 }

 article {
  border: 5px solid silver;
  width: 400px;
  display: flex;
  height: 550px;
  padding: 10px;
  flex-direction: column;
  justify-content: space-between;
 }

 article div {
  background-color: blueviolet;
  background-clip: content-box;
  padding: 10px;
  flex: 1;
  color: #fff;
  font-size: 55px;
 }

 article :nth-child(1) {
  order: 1;
 }

 article :nth-child(2) {
  order: -1;
 }

 article :nth-child(3) {
  order: -11;
 }
</style>
<body>
 <article>
  <div>1</div>
  <div>2</div>
  <div>3</div>
 </article>
</body>

21.弹性元素排序实例

  • 下面是通过 J 动态改变 order 属性产生移动效果,因为本章节是讲 CSS 所以 JS 功能没有完善,只是体验一下 order。
html
<style>
 * {
  padding: 0;
  margin: 0;
 }

 body {
  padding-left: 50px;
  padding-top: 15px;
 }

 article {
  border: solid 5px silver;
  width: 400px;
  height: 400px;
  padding: 10px;
  display: flex;
  flex-direction: column;
 }

 article section {
  order: 1;
  flex: 1 0 100px;
  padding: 10px;
  background: blueviolet;
  background-clip: content-box;
  display: flex;
  flex-direction: column;
  text-align: center;
  color: white;
 }

 article section div {
  flex: 1;
 }

 article section div {
  display: flex;
  flex-direction: column;
  justify-content: center;
 }

 article section span {
  flex: 0;
  background: #000;
  padding: 20px;
  cursor: pointer;
 }
</style>

<article>
 <section>
  <div>houdunren.com</div>
  <span onclick="up(this)">up</span>
 </section>
 <section>
  <div>hdcms.com</div>
  <span onclick="up(this)">up</span>
 </section>
</article>

<script>
 function up(el) {
  el.parentElement.style.order = getOrder(el.parentElement) * 1 - 1;
  console.log(getOrder(el.parentElement));
 }

 function getOrder(el) {
  return getComputedStyle(el, null).order;
 }
</script>

D.弹性文本

22.弹性布局操作文本节点

  • 文本节点也在弹性布局操作范围内。
html
<style>
 article {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  height: 100vh;
  align-items: center;
  font-size: 14px;
 }
</style>

<article>
 hd
 <span>houdunren</span>
 hd
</article>

E.绝对定位

23.定位元素在弹性布局中的表现

  • 绝对定位的弹性元素不参与弹性布局
html
<style>
 * {
  padding: 0;
  margin: 0;
  padding: 10px;
  margin: 5px;
 }
 article {
  position: relative;
  height: 400px;
  border: solid 5px silver;
  box-sizing: border-box;
  display: flex;
  justify-content: space-evenly;
  align-items: flex-start;
 }
 article div {
  min-width: 50px;
  min-height: 80px;
  border: solid 5px blueviolet;
  text-align: center;
  font-size: 28px;
 }
 article div:nth-of-type(1) {
  position: absolute;
  top: 0;
 }
</style>

<article>
 <div>1</div>
 <div>2</div>
 <div>3</div>
</article>

F.微信公众号

24.弹性布局移动端通用菜单

25.多级菜单的弹性布局

html
<style>
 * {
  padding: 0;
  margin: 0;
 }

 body {
  display: flex;
  flex-direction: column;
  height: 100vh;
  color: #666;
 }

 main {
  flex: 1;
 }

 footer {
  height: 50px;
  background: blueviolet;
  display: flex;
  justify-content: space-evenly;
 }

 footer section {
  display: flex;
  flex: 1 0;
  flex-direction: column-reverse;
  border-right: solid 1px #555;
  border-top: solid 1px #555;
 }

 footer section:last-child {
  border-right: none;
 }

 footer section h4 {
  flex: 0 0 50px;
  display: flex;
  text-align: center;
  flex-direction: column;
  justify-content: center;
  cursor: pointer;
  color: white;
 }

 footer section ul {
  text-align: center;
  display: flex;
  flex-direction: column;
  border: solid 1px #555;
  margin-bottom: 5px;
  border-radius: 5px;
  margin: 5px;
 }

 footer section ul li {
  flex: 1 0 50px;
  border-bottom: solid 1px #555;
  display: flex;
  flex-direction: column;
  justify-content: center;
  cursor: pointer;
 }

 footer section ul li:last-child {
  border: none;
 }
</style>

<main></main>
<footer>
 <section>
  <h4>教程</h4>
  <ul>
   <li>PHP</li>
   <li>LINUx</li>
  </ul>
 </section>
 <section>
  <h4>直播</h4>
 </section>
</footer>

G.自动空间

26.使用 magin 自动撑满空间技巧 margin-right: auto

  • 在弹性布局中对元素使用margin-right:auto等形式可以自动撑满空间。下例为第一个 ul 设置  margin-right:auto表示右侧空间自动撑满,第二个 ul 靠近父元素右边界。
html
<head>
 <meta charset="UTF-8" />
 <meta name="viewport" content="width=device-width, initial-scale=1.0" />
 <style>
  * {
   padding: 0;
   margin: 0;
  }

  .container {
   width: 1200px;
   margin: 0 auto;
  }

  nav {
   display: flex;
   border: solid 1px green;
   margin-top: 20px;
   align-items: center;
   height: 60px;
   box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
   background: #f3f3f3;
  }

  ul {
   list-style: none;
  }

  ul:nth-child(1) {
   display: flex;
   align-items: center;
   margin-right: auto;
  }

  ul:nth-child(1) > li {
   margin: 0 10px;
  }

  ul:nth-child(2) > li {
   width: 50px;
   height: 50px;
   border-radius: 50%;
   background: #9b59b6;
  }
 </style>
</head>

<body>
 <div class="container">
  <nav>
   <ul>
    <li>houdunren</li>
    <li>视频教程</li>
    <li>每晚直播</li>
    <li>在线文档</li>
   </ul>
   <ul>
    <li></li>
   </ul>
  </nav>
 </div>
</body>