flex 适合用于一维的布局
flex 容器 和 flex项目
flex 容器
flex 容器指的是 display 为 flex、inline-flex 的元素,元素中的子元素则自动称为 flex 项目。
flex 容器会产生 flex formatting context(伸缩格式化上下文),这类似于 BFC (块级格式化上下文),保证了内部元素不会干扰到外部元素
flex 项目
flex 容器的直接子元素就是 flex 项目,flex 容器内的连续文字也会被视作 flex 项目
.sup {
display: flex;
align-items: center;
width: 200px;
height: 100px;
margin-top: 50px;
margin-left: auto;
border: 1px solid pink;
}
.sup > span {
margin-left: auto;
}
轴线
flexbox 有两根轴线,主轴 和 交叉轴,主轴即为元素的排列方向,其默认值为 row 水平方向
flex-direction
通过 flex-direction 属性,可以定义 flexbox 的主轴方向,其可取值如下:
- row
- row-reverse
- column
- column-reverse
主轴和交叉轴
在flexbox 中,flexbox 的轴线定义了起始线 和 终止线,默认情况下,起始线在水平方向是左侧,在垂直方向是上侧,终止线则与起始线相反
通过上方 flex-direction 的 row-reverse、column-reverse,可以改变主轴的 起始线 和 终止线
.sup1, .sup2, .sup3 {
display: flex;
width: 200px;
height: 100px;
border: 1px solid pink;
}
.sup1 {
flex-direction: row-reverse;
}
.sup2 {
flex-direction: column;
}
.sup3 {
flex-direction: column-reverse;
}
flex-grow
当 flex 容器还有 富余空间 时,通过此属性决定如何分配富余空间,默认值为 0,负值无效
每个 flex 项目所占的富余空间为该 (flex 项目的 flex-grow 值 / 所有 flex 项目的 flex-grow 的和) * 富余空间
上图中,flex 容器的宽度为 200px,每个 flex 项目 50px,则 flex 容器还有 100px 的富余空间,如果给每个 flex 项目都设置 flex-grow: 1,则每个 flex 项目应该分得 (1 / (1+1)) * 100 = 50 的富余空间,如下图:
flex-shrink
当 flex 项目 溢出 容器时,通过此属性决定 flex 项目如何进行收缩,默认值是 1,负值无效
如果 flex 项目的 flex-basis 为 auto,则最小收缩到元素的 min-content
与 flex-grow 的计算方式相似,元素应该收缩的长度为 (flex 项目的 flex-shrink 值 / 所有 flex 项目的 flex-shrink 值的和) * 超出的长度
上图中,容器的宽度为 200px,每个 flex 项目的宽度为 200px,默认情况下,每个元素应该收缩 (1 / (1+1)) * 200 = 100,可以看到图中每个元素确实都收缩了100px,若将 sub2 的 flex-shrink 改为 3,则其收缩为 50px 宽,如下图:
注意:如果 flex-basis 为 auto,则 flex 项目只会收缩到换行后最长的单词的长度,即使本身的 flex-shrink 比较大
.sub1, .sub2 {
width: 200px;
background-color: yellow;
}
.sub2 {
flex-shrink: 3;
background-color: red;
}
flex-basis
该属性指定了 flex 项目在主轴方向上的初始大小,默认值为 auto,即大小由内容撑开
其取值可以为 数值 或者 百分比值(根据主轴的长度计算),不允许设置负值
当值为 auto,并且 flex-shrink 不为 0,此时就是 min-content 的表现,会尽可能的换行,最小 宽/高 就是最长的单词的长度,汉字的话就是每个字都会换行,效果如下图:
当值为 auto,并且 flex-shrink 值为 0 的时候,就是 max-content 的表现,内容由多少,长度就有多少,效果如下图所示:
当为 flex 项目设置了 宽/高 时,其 flex-basis 的默认值就是其 宽/高,如图:
当设置了 min-width/height 时,此时会以 min-width/height 和 width 中较大的值作为 flex-basis 的值
当 flex-basis 设置为 0 的时候,表示在分配空间的时候不考虑该 flex 项目的长度,直到该 flex 项目达到 min-content 状态,所以 flex 项目无论怎么收缩,都只会收缩到 min-content 的状态,不会收缩为 0
.sub {
flex-grow: 1;
flex-basis: 0;
border: 1px solid yellow;
}
.sub2 {
width: 0px;
flex-grow: 1;
flex-shrink: 0;
border: 1px solid red;
}
如上图所示,当两个 flex 项目都是 0 ,并且 flex-grow 相等时,则两个元素均分容器空间
.sub {
flex-grow: 1;
flex-basis: 0;
border: 1px solid yellow;
}
.sub2 {
width: 10px;
flex-grow: 1;
flex-shrink: 0;
border: 1px solid red;
}
如上图所示,当第二个 flex 项目宽设置为 10px,则两个 flex 项目均分剩下的 90px 的空间
.sub {
flex-grow: 1;
flex-basis: 0;
border: 1px solid yellow;
}
.sub2 {
width: 100px;
flex-grow: 1;
border: 1px solid red;
}
如上图所示,当第二个 flex 项目设置很大的 width 的时候,第一个 flex 项目也不会缩小到 0
justify-content
该属性定义了在 主轴 上,如何在 flex 项目之间分配 富余、溢出空间,例如,设置为 center,即使溢出了, flex 项目也会在容器中居中,其取值可以如下:
- flex-start
- flex-end
- space-between
- space-around
- space-enevly
- center
align-items
该属性定义了在 交叉轴 上,flex 项目如何分配 富余、溢出空间,默认值为 stretch,其可取值如下:
- flex-start
- flex-end
- center
- stretch
align-self
定义 flex 项目如何在 交叉轴上显示,会覆盖 align-items,如果 交叉轴 方向 margin 值设置为 auto,则会忽略 align-self,取值与 align-items 相同
align-content
定义 flex 项目在容器内换行后,每行 在 交叉轴 上如何显示,类似于交叉轴上的 justify-content,取值与 justify-content 相同
使用 flex 进行布局
两栏式布局
非 flex 实现
1. 浮动 + 普通流
<div class="wrap">
<div class="left"></div>
<div class="right"></div>
</div>
.left {
float: left;
width: 200px;
height: 100%;
background-color: yellow;
}
.right {
height: 100%;
margin-left: 200px;
background-color: pink;
}
2. 纯浮动
<div class="wrap">
<div class="left"></div>
<div class="right"></div>
</div>
.left {
float: left;
width: 200px;
height: 100%;
background-color: yellow;
}
.right {
float: left;
width: calc(100% - 200px);
height: 100%;
background-color: pink;
}
3. 定位
<div class="wrap">
<div class="left"></div>
<div class="right"></div>
</div>
.left {
position: absolute;
top: 0;
left: 0;
width: 200px;
height: 100%;
background-color: yellow;
}
.right {
position: absolute;
top: 0;
left: 200px;
right: 0;
height: 100%;
background-color: pink;
}
flex 实现
<div class="wrap">
<div class="left"></div>
<div class="right"></div>
</div>
.wrap {
display: flex;
height: 100%;
}
.left {
width: 200px;
height: 100%;
background-color: yellow;
}
.right {
flex-grow: 1;
height: 100%;
background-color: pink;
}
顶部导航栏左右布局效果
非 flex 实现
<div class="wrap">
<div class="left"></div>
<div class="right"></div>
</div>
.wrap {
height: 200px;
border: 1px solid #000;
}
.left {
float: left;
width: 200px;
height: 100%;
background-color: yellow;
}
.right {
float: right;
width: 200px;
height: 100%;
background-color: pink;
}
flex 实现
1. 使用 justify-content
<div class="wrap">
<div class="left"></div>
<div class="right"></div>
</div>
.wrap {
display: flex;
justify-content: space-between;
height: 200px;
border: 1px solid #000;
}
.left {
width: 200px;
background-color: yellow;
}
.right {
width: 200px;
background-color: pink;
}
2. 使用 margin
<div class="wrap">
<div class="left"></div>
<div class="right"></div>
</div>
.wrap {
display: flex;
height: 200px;
border: 1px solid #000;
}
.left {
width: 200px;
background-color: yellow;
}
.right {
width: 200px;
margin-left: auto;
background-color: pink;
}
这种方法是在参考 MDN 写这篇文章的时候,在 MDN 文档上发现的实现方法,建议大家可以多翻阅参考 MDN 文档
实现元素等宽
<div class="wrap">
<div>这里是第一段</div>
<div>这里是第二段,第二段,第二段,第二段</div>
<div>这里是第三段,第三段</div>
<div>这里是第四段</div>
<div>这里是第五段段段段段段段</div>
<div>第六段</div>
</div>
.wrap {
display: flex;
height: 200px;
border: 1px solid #000;
}
.wrap > div {
flex-basis: 0;
flex-grow: 1;
border: 1px solid #000;
}