劝你耗子尾汁,弹性盒模型七连鞭

231 阅读5分钟

一、什么是弹性盒模型

弹性盒模型是css3的新的布局模型,也可以叫做 flex 布局模型,是一种当页面需要适应不同的屏幕大小以及设备类型时确保元素拥有恰当的行为的布局方式。

二、弹性盒模型关注是什么

首先,需要明确引入弹性布局模型的目的是什么?

目的是提供一种更加有效的方式来对一个容器中的子元素进行排列、对齐和分配空白空间。

因此为了实现这个目的,在构建弹性盒模型的时候,需要去思考怎么样设置子元素的排列方式,对齐方式,如何进行空间分配。

这里我们需要了解的是:

  • 弹性盒模型是由弹性容器和弹性子元素构成
  • 弹性容器外及弹性子元素内是正常渲染的。弹性盒子只定义了弹性子元素如何在弹性容器内布局

三、实现构建一个弹性盒子

要构建一个弹性盒子,需要理解两个方面的知识:轴和容器

  • 轴 轴是用来决定方向的,主轴代表水平方向,交叉轴代表垂直方向,基于这一点,我们可以决定子元素的是水平排列还是垂直排列
  • 容器 一个容器里面可以有多个子元素,在父容器中我们要决定好子元素的排列方向(水平排列还是垂直排列),排列方式(左对齐、右对齐还是居中对齐等) 在子元素中要决定怎么样分配父容器的空间,按比例分配还是直接占满

下面就来详细梳理一下要实现一个弹性盒子会用到的属性以及相应的值

四、决定子元素的排列方向

flex-direction:row

<html>
  <head>
    <title>弹性盒子</title>
    <meta charset="utf-8"/>
    <style type="text/css">
      .wrapper{
        display: flex;
        flex-direction: row;
        width: 400px;
        height: 300px;
        margin:100px auto;
        background-color: #bccdfa;
      }
      .wrapper>div{
        width: 100px;
        height: 100px;
      }
      .item-1{
        background-color: #36dd38;
      }
      .item-2{
        background-color: #ffc055;
      }
  </style>	
  </head>
  <body>
      <div class="wrapper">
        <div class="item-1">box1</div>
        <div class="item-2">box2</div>
      </div>
  </body>
</html>

flex-direction:row-reverse

flex-direction:column

flex-direction:column-reverse

五、决定子元素的对齐方式

子元素在容器中的对齐方式,可以通过设置父容器来规定子元素的对齐,也可以直接设置子元素本身来规定自身的对齐方式

1、设置父容器

justify-content 决定子元素在水平方向的对齐方式

justify-content:flex-start
<html>
  <head>
    <title>弹性盒子</title>
    <meta charset="utf-8"/>
    <style type="text/css">
      .wrapper{
          display: flex;
          justify-content: flex-start;
          width: 400px;
          height: 300px;
          margin:100px auto;
          background-color: #bccdfa;
      }
      .wrapper>div{
          width: 100px;
          height: 100px;
      }
      .item-1{
          background-color: #36dd38;
      }
      .item-2{
          background-color: #ffc055;
      }
    </style>	
  </head>
  <body>
    <div class="wrapper">
      <div class="item-1">box1</div>
      <div class="item-2">box2</div>
    </div>
  </body>
</html>

justify-content:flex-end

justify-content:center

justify-content:space-between

justify-content:space-arround

align-items 决定子元素在垂直方向的对齐方式

align-items:flex-start
<html>
  <head>
    <title>弹性盒子</title>
    <meta charset="utf-8"/>
    <style type="text/css">
      .wrapper{
        display: flex;
        align-items: flex-start;
        width: 400px;
        height: 300px;
        margin:100px auto;
        background-color: #bccdfa;
      }
      .wrapper>div{
        width: 100px;
        height: 100px;
      }
      .item-1{
        background-color: #36dd38;
      }
      .item-2{
        background-color: #ffc055;
      }
  </style>	
  </head>
  <body>
    <div class="wrapper">
      <div class="item-1">box1</div>
      <div class="item-2">box2</div>
    </div>
  </body>
</html>

align-items:flex-end

align-items:center

align-items:baseline

align-items:stretch

如果子元素未设置高度或者设为 auto,将占满整个容器的高度

 <html>
    <head>
      <title>弹性盒子</title>
      <meta charset="utf-8"/>
      <style type="text/css">
      .wrapper{
        display: flex;
        align-items: stretch;
        width: 400px;
        height: 300px;
        margin:100px auto;
        background-color: #bccdfa;
      }
      .wrapper>div{
          width: 100px;
      }
      .item-1{
        height: auto;
        background-color: #36dd38;
      }
      .item-2{
        height: 100px;
        background-color: #ffc055;
      }
    </style>	
  </head>
  <body>
    <div class="wrapper">
      <div class="item-1">box1</div>
      <div class="item-2">box2</div>
    </div>
  </body>
</html>

2、设置子元素本身

align-self : flex-end
<html>
  <head>
      <title>弹性盒子</title>
      <meta charset="utf-8"/>
      <style type="text/css">
          .wrapper{
              display: flex;
              align-items: center;
              width: 400px;
              height: 300px;
              margin:100px auto;
              background-color: #bccdfa;
          }
          .wrapper>div{
              width: 100px;
              height: 100px;
          }
          .item-1{
              align-self: flex-end;
              background-color: #36dd38;
          }
          .item-2{
              height: 100px;
              background-color: #ffc055;
          }
      </style>	
  </head>
  <body>
      <div class="wrapper">
          <div class="item-1">box1</div>
          <div class="item-2">box2</div>
      </div>
  </body>
</html>

注意:

align-self 的取值和 align-items 的取值一样的,所达到的效果也是类似,这都是垂直方向上的对齐方式

六、决定子元素是否换行

首先看一个例子

<html>
	<head>
		<title>弹性盒子</title>
		<meta charset="utf-8"/>
		<style type="text/css">
			.wrapper{
				display: flex;
				width: 400px;
				height: 300px;
				margin:100px auto;
				background-color: #bccdfa;
			}
			.wrapper>div {
				width: 100px;
			}
			.item-1{
				height: 100px;
				background-color: #36dd38;
			}
			.item-2{
				height: 100px;
				background-color: #ffc055;
			}
		</style>	
	</head>
	<body>
		<div class="wrapper">
			<div class="item-1">box1</div>
			<div class="item-2">box2</div>
			<div class="item-1">box1</div>
			<div class="item-2">box2</div>
			<div class="item-1">box1</div>
			<div class="item-2">box2</div>
		</div>
	</body>
</html>

可以看到不管存在多少个子元素,即使全部子元素的宽度总和已经超出父容器的宽度也是不会换行的

如果想设置子元素是否换行,需要设置换行属性

flex-wrap:wrap

flex-wrap:wrap-reverse

当我们设置了换行属性后,如果仍然想在交叉轴也就是垂直方向的去设置子元素的对齐方式的怎么办,这时就不能使用align-items, 使用的是align-content

比如设置子元素换行后以space-around的方式对齐

<html>
	<head>
		<title>弹性盒子</title>
		<meta charset="utf-8"/>
		<style type="text/css">
			.wrapper{
				display: flex;
				flex-wrap: wrap;
				align-content: space-around;
				width: 400px;
				height: 300px;
				margin:100px auto;
				background-color: #bccdfa;
			}
			.wrapper>div {
				width: 100px;
			}
			.item-1{
				height: 100px;
				background-color: #36dd38;
			}
			.item-2{
				height: 100px;
				background-color: #ffc055;
			}
		</style>	
	</head>
	<body>
		<div class="wrapper">
			<div class="item-1">box1</div>
			<div class="item-2">box2</div>
			<div class="item-1">box3</div>
			<div class="item-2">box4</div>
			<div class="item-1">box5</div>
			<div class="item-2">box6</div>
		</div>
	</body>
</html>

因此,align-content的取值和align-items的取值是一致的,效果也是相同的,但是它们的区别在于什么地方?

align-items的作用对象是所有的子元素

align-content作用对象是成行的子元素

注意:

flex-flow 属性是 flex-direction 和 flex-wrap 属性的复合属性, 设置子元素水平排列,换行时可以这么写:

flex-flow: row wrap;

七、子元素如何分配父容器空间

flex-basis

flex-basis 用于设置子元素的占用空间。如果设置了值,则子项占用的空间为设置的值;如果不设置或者值为auto,那子元素的空间为它设置的width的值

<html>
	<head>
		<title>弹性盒子</title>
		<meta charset="utf-8"/>
		<style type="text/css">
			.wrapper{
				display: flex;
				align-items: center;
				width: 400px;
				height: 300px;
				margin:100px auto;
				background-color: #bccdfa;	
			}
			.item-1{
				width: 100px;
				height: 100px;
				flex-basis: 50px;
				background-color: #36dd38;
			}
			.item-2{
				width: 100px;
				flex-basis: 150px;
				height: 100px;
				background-color: #ffc055;
			}
			.item-3{
				width: 100px;
				flex-basis: auto;
				height: 100px;
				background-color: #36dd38;
			}
		</style>	
	</head>
	<body>
		<div class="wrapper">
			<div class="item-1">box1</div>
			<div class="item-2">box2</div>
			<div class="item-3">box3</div>
		</div>
	</body>
</html>

因此,box1:50px, box2:150px, box3:100px,注意,当所有的基准宽度总和超过父容器的宽度时,某些子元素的基准宽度会收缩,因此有换行需要的还是要换行

flex-grow

用于瓜分父容器的剩余空间

<html>
	<head>
		<title>弹性盒子</title>
		<meta charset="utf-8"/>
		<style type="text/css">
			.wrapper{
				display: flex;
				align-items: center;
				width: 400px;
				height: 300px;
				margin:100px auto;
				background-color: #bccdfa;	
			}
			.item-1{
				width: 100px;
				height: 100px;
				flex-basis: 50px;
				flex-grow: 1;
				background-color: #36dd38;
			}
			.item-2{
				width: 100px;
				flex-basis: 150px;
				height: 100px;
				background-color: #ffc055;
			}
			.item-3{
				width: 100px;
				flex-basis: auto;
				flex-grow: 2;
				height: 100px;
				background-color: #36dd38;
			}
		</style>	
	</head>
	<body>
		<div class="wrapper">
			<div class="item-1">box1</div>
			<div class="item-2">box2</div>
			<div class="item-3">box3</div>
		</div>
	</body>
</html>

父容器宽度为 400px,box1,box2,box3的基准值相加:50+150+100 = 300<400,

剩余宽度:400-300 = 100

box1实际宽度: 50+(100/(1+2))*1=83.33

box2实际宽度: 150(flex-grow不设置默认为0)

box3实际宽度: 100+(100/(1+2))*2=166

flex-shrink

用来“吸收”超出的空间

<html>
	<head>
		<title>弹性盒子</title>
		<meta charset="utf-8"/>
		<style type="text/css">
			.wrapper{
				display: flex;
				align-items: center;
				width: 400px;
				height: 300px;
				margin:100px auto;
				background-color: #bccdfa;	
			}
			.item-1{
				width: 100px;
				height: 100px;
				flex-basis: 150px;
				background-color: #36dd38;
			}
			.item-2{
				width: 100px;
				flex-basis: 200px;
				flex-shrink: 2;
				height: 100px;
				background-color: #ffc055;
			}
			.item-3{
				width: 100px;
				flex-basis: 150px;
				flex-shrink: 1;
				height: 100px;
				background-color: #36dd38;
			}
		</style>	
	</head>
	<body>
		<div class="wrapper">
			<div class="item-1">box1</div>
			<div class="item-2">box2</div>
			<div class="item-3">box3</div>
		</div>
	</body>
</html>

父容器宽度为 400px, box1,box2,box3的基准值相加:150+200+150 = 500>400,

超出宽度:400-500 = -100

box1实际宽度: 150-150 *1/(150 *1+200 *2+150 *1) *100=128.57

box2实际宽度: 200-200 *2/(150 *1+200 *2+150 *1) *100=142.85

box3实际宽度: 150-150 *1/(150 *1+200 *2+150 *1) *100=128.57