CSS Flex

网页布局(layout)是CSS的一个重点,传统的方式是基于盒子模型,依赖displaypositionfloat等属性,对于特殊布局非常不便,比如垂直居中。2009年,W3C提出了Flexbox布局方案,一种简单、完整、响应式的页面布局。

  • Flex弹性盒子布局与方向无关,相对于常规布局(垂直块/水平内联块为基础)不存在浮动元素脱离文档流后需清除浮动的问题。
  • Flex弹性盒子布局适用于应用程序的组件以及小规模布局,网格布局适用于较大规模的布局。
  • Flex弹性布局模块旨在提供一个更加有效地方式来布置,对齐和分布在容器之间的各项内容,即使它们的大小是未知或动态的。
  • Flex弹性布局的主要思想是让容器有能力来改变项目的宽度和高度以填满可用空间,主要是为了容纳所有类型的显示设备和屏幕尺寸的能力。
  • Flex弹性布局Flexible Box)用来为盒状模型提供最大的灵活性,任何容器都可指定为Flex布局。

Flex弹性盒子布局的原理

Flex弹性盒子布局旨在赋予父容器更改子元素宽高或顺序的能力,来更好地填充剩余可用空间,主要使其自适应不同尺寸的显式设备和屏幕。使用Flexbox弹性盒子布局的父容器会拉伸每个子元素来填充剩余空用空间,或压缩来阻止它们超出父容器。

由于Flexbox弹性盒子布局在方向上是不可预知的,这一点和常规布局不同,常规布局中Block块是基于垂直方向排列的,Inline内联则是基于水平方向的。常规布局在页面中虽然显式没有问题,但缺乏灵活性,因此难以支撑大型复杂应用。特别是响应式自适应方向、大小、伸缩、收缩等变化时。

弹性布局

Flexbox弹性盒子是一个整体模块而非单一属性,它涉及到属性集在容器和项目上的不同设置。

弹性盒子

采用弹性布局的元素称为Flex容器(Flex Container),容器的所有子元素自动成为容器成员,称为Flex项目(Flex Item)

要使用Flexbox弹性盒子布局首先必须让父元素变成一个Flex容器,可以在父元素中显式的设置display:flexdisplay:inline-flex,通过显式声明Flex容器后,一个Flexbox格式化上下文就会立即启动。

Flex弹性盒子布局关键

  • Flex容器(Flex Container):父元素显式设置display:flexdisplay:inline-flex
.flex-container{
  display:flex;
}
  • Flex项目(Flex Items):弹性盒子容器内的子元素
.flex-item{

}

弹性盒子通过设置display属性值为flexinline-flex将其定义为弹性容器,弹性盒子只定义了弹性项目如何在弹性容器内布局。弹性项目通常在弹性盒子内一行显示,默认每个容器只有一行。

设置为Flex弹性布局后,子元素floatclearvertical-align属性将失效。

.flex-container{
  display:flex;
}

行内元素也可使用弹性布局

.flex-inline-container{
  display:inline-flex;
}

轴(Axis)

在Flex弹性布局的世界中,水平和垂直并非方向概念,而是采用主轴(Main Axis)和侧轴(Cross Axis)来表示。默认主轴即水平方向从左向右,侧轴即垂直方向从上向下。

主轴和侧轴

主轴和侧轴是Flex容器(Flex Container)默认存在两根轴

  • 横轴:水平的主轴(main axis)
    主轴的开始位置即与边框的交叉点称为main start,结束位置叫做 main end

  • 竖轴:垂直的交叉轴(cross axis)
    交叉轴的开始位置叫做 cross start,结束位置叫做cross end

Flex项目(Flex Item)默认沿着主轴排列,单个项目占据的主轴空间叫做main size, 占据交叉轴空间叫做cross size

Flex容器

弹性项目在主轴方向上的宽度或高度是弹性项目的主轴长度,弹性项目的主轴长度属性是widthheight属性,具体由主轴方向flex-direction属性决定。

弹性项目的主轴

弹性容器(Flex Container)

Flex容器上的属性共有6个:

属性 描述
flex-direction 用于控制Flex项目沿着主轴(Main Axis)的排列方向
flex-wrap 设置Flex弹性项目子元素的换行方式,默认为nowrap。
flex-flow 复合属性,flex-direction和flex-wrap的简写形式。
justify-content 设置弹性项目在横轴上的对齐方式
align-items 设置Flex项目在每个Flex行的交叉轴上默认的对齐方式
align-content 仅适用于多行Flex容器,当Flex容器在交叉轴上存在多余空间时,将子项作为整体进行对齐。

主轴方向(Flex Direction)

flex-direction 决定主轴(main axis)的方向,即弹性项目(flex item)的排列方向,用于设置或检索弹性盒子对象的子元素在父容器中的位置。

属性值 描述
row 默认值,弹性项目水平从左到右以左对齐方式排列。
row-reverse 反转水平横向排列,以右对齐从后向前排列,最后一项位于首位。
column 纵向排列
column-reverse 反转纵向排列,从后向前排列,最后一项位于最上层。

Flex的主轴是flex-direction定义的方向,默认为row,此时交叉轴跟主轴垂直即为column。若定义flex-direction主轴方向为column,则交叉轴为row

flex-direction: row | row-reverse | column | column-reverse;
排列方向
# 默认值,主轴为水平方向,起点为左端。
.flex-container{
  display:flex;
  flex-direction:row;
}
主轴水平方向
# 主轴为垂直方向,起点为上端。
.flex-container{
  display:flex;
  flex-direction:column;
}
主轴垂直方向
# 主轴为水平方向,起点在右端。
.flex-container{
  display:flex;
  flex-direction:row-reverse;
}
主轴水平反向
# 主轴为垂直方向,起点为下端。
.flex-container{
  display:flex;
  flex-direction:column-reverse;
}
主轴垂直反向

例如:自适应导航

.navigation{
  display:flex;
  flex-flow:row wrap; 
  justify-content:flex-end;
}

@media all and (max-width:800px){
  .navigation{
    justify-content:space-around;
  }
}

@media all and (max-width:500px){
  .navigation{
    flex-direction:column;
  }
}
自适应导航

项目换行 (Flex Wrap)

默认情况下弹性项目(flex item)排列在一条轴线上

  • flex-wrap定义了如果在一条轴线上排列不下弹性项目时,如何换行的情况。
  • flex-wrap规定了Flex弹性容器是单行还是多行,同时横轴(主轴)的方向决定了新行的堆叠方向。
flex-wrap: nowrap | wrap | wrap-revers;
flex-wrap 换行方式
属性值 描述
nowrap 默认值,设置弹性项目不拆行或不拆列,即弹性项目溢出弹性容器时不换行。
wrap 设置弹性项目在必要时拆行或拆列,即当弹性项目溢出弹性容器时自动换行。
wrap-reverse 设置弹性项目在必要时拆行或拆列并以反转方式排列

禁止换行

  • nowrapflex-wrap的默认值,此时弹性容器为单行。
.flex-container{
  display:wrap;
  flex-wrap:nowrap;
}
禁止换行

自动换行

  • wrap用于设置弹性容器为多行,此时弹性项目溢出部分会被放置到新行中,弹性项目内部会发生断行。
.flex-container{
  display:flex;
  flex-wrap:wrap;
}
自动换行

反转换行:反转换行排列,即上下项目位置交换。

.flex-container{
  display:flex;
  flex-wrap:wrap-reverse;
}
wrap-reverse 反转换行

方向换行 (Flex Flow)

flex-flow属于复合属性 是flex-direction属性和flex-wrap属性的简写方式

flex-flow: <flex-direction> <flex-wrap>;

flex-flow默认水平排列且不换行row nowrap

.flex-container{
  display:flex;
  flex-flow: row nowrap;
}

轴对齐

轴对齐
位置 水平 垂直
(0, 0) justify-content:flex-start -
(1, 0) justify-content:center -
(2, 0) justify-content:flex-end -
(0, 1) - align-items:center
(1, 1) justify-content:center align-items:center
(2, 1) justify-content:flex-end align-items:center
(0, 2) - align-items:flex-end
(1, 2) justify-content:center align-items:flex-end
(2, 2) justify-content:flex-end align-items:flex-end

横轴对齐(Justify Content)

justify-content 定义弹性项目(flex item)在主轴(main axis)上的对齐方式

当弹性容器中多行弹性项目都无法伸缩,或者已经到达弹性容器最大值时,justify-content属性可协助对剩余可用空间进行分配。当项目项目溢出某行时,justify-content可在对齐方式上进行控制。

justify-content: flex-start | flex-end | center | space-between | space-around;
内容对齐
对齐方式 描述
flex-start 默认左对齐
flex-end 右对齐
center 居中对齐
space-between 两端对齐
space-around 留白包围

左对齐

弹性项目向行首起始位置对齐,行首第一个弹性项目的主起始位置的边界将于该行主起始位置的边界对齐,后续弹性项目与前个项目对齐。

.flex-container{
  display:flex;
  justify-content: flex-start;
}

右对齐

弹性项目向行尾结束位置对齐,行首第一个弹性项目的主结束位置边界将与该行主结束位置边界对齐,后续弹性项目与前一个项目对齐。

.flex-container{
  display:flex;
  justify-content: flex-end;
}

居中对齐

弹性项目向行中央位置对齐,行元素相互对齐并在行中居中对齐,第一个元素与行主起始位置边距等同于最后一个元素与行主结束位置的边距,若剩余空间为负数,则保持两端相等长度的溢出。

.flex-container{
  display:flex;
  justify-content: center;
}

两端对齐

弹性项目平均分布在行中,第一个元素柏边界与行主起始位置的边界对齐,最后一个元素的边界与行主结束位置的边距对齐,剩余的弹性项目平均分布,并确保两两之间空白空间相等。

若最左边剩余空间为负数,或行中仅有一个元素,则等效于flex-start

.flex-container{
  display:flex;
  justify-content: space-between;
}

留白包围

  • 弹性项目平均分布在行内,两端保留的间距是弹性形目之间间距的一半。
  • 若最左边剩余空间为负数或行内只有一个弹性项目则等效于`center
.flex-container{
  display:flex;
  justify-content: space-around;
}

具体对其方式与轴的方向相关,这里假设主轴为从左到右。

justify-content 对其方式

纵轴对齐(Align Items)

align-items属性定义弹性项目(flex item)在交叉轴(cross axis)上如何对齐,用于设置或检索弹性项在纵轴(侧轴)方向上的对齐方式。

align-items: stretch | flex-start | flex-end | center | baseline;
纵轴对齐 描述
flex-start 顶对齐,弹性项纵轴起始位置边界紧靠该行纵轴起始边界。
flex-end 底对齐,弹性项纵轴结束位置边界紧靠父容器纵轴结束边界。
center 垂直居中,弹性项在该行纵轴上居中放置,若该行尺寸小于弹性项尺寸,则会向两个方向溢出相同的长度。
baseline 基线对齐,若弹性项行内轴与纵轴同为一条则等同于flex-start,其他情况下则将参与基线对齐。
stretch 垂直拉升,若指定纵轴大小为auto则项目边距尽可能接近所在行的尺寸。
纵轴对齐

具体的垂直对其方式与交叉轴的方向有关,假设交叉轴从上到下。

垂直拉伸

  • 默认若弹性项目未设置高度或auto,则项目将占满容器高度。
.flex-container{
  display:flex;
  align-items: stretch;
}
.flex-item{
  height:auto;
}
垂直拉伸 stretch

顶对齐

  • 交叉轴的起点对齐
.flex-container{
  display:flex;
  align-items:flex-start;
}
顶对齐

底对齐

  • 交叉轴的终点对齐
.flex-container{
  display:flex;
  align-items: flex-end;
}
底对齐

垂直居中

  • 交叉轴的中点对齐
.flex-container{
  display:flex;
  align-items: center;
}
垂直对齐

例如:搜索表单

<style>
.form{
  display:flex;
  align-items:center;
}
.form-input{
  flex-grow:1;
}
</style>
<form class="form">
  <input type="text" name="keyword" class="form-input"/>
  <button type="submit" class="form-btn">确定</button>
</form>

默认form中的inputbutton都是行内块级元素(inline-block),即默认并排在一行上,此时两控件之间存在3px~4px的间隔,这是浏览器内置样式所指定的。

使用display:flex指定form使用Flexbox布局后,inputbutton控件间隔消失,因为Flexbox弹性项目之间是不存在间隔的。

input控件上使用flex-grow:1时,input控件宽度拉伸后占据当前行所有剩余宽度。button控件未设置则保持flex-grow:0即本身宽度,不会被拉伸。

此时若button高度变化则整个form的高度也会自动跟着变化,因为Flexbox布局默认不改变Flex弹性项目的宽度,但会默认改变弹性项目的高度。如果弹性项目没有显式地指定高度则将占据弹性容器内所有高度。

可为弹性项目设置align-self属性(默认值为stretch高度自动拉伸)以改变这种默认行为,也可以为弹性容器设置align-items,容器内所有项目的align-self将自动继承父元素中的align-items属性值。这里为弹性容器设置align-items:center表示容器内所有项目保持垂直居中对齐。

表单

基线对齐

  • 项目的第一行文字的基线对齐
.flex-container{ 
  display:flex;
  align-items: baseline;
}
基线对齐

多行对齐(Align Content)

align-itemsalign-content都用于定义Flex容器中元素在交叉轴上的对齐方式,align-content用于设置或检索弹性盒子堆叠伸缩行的对齐方式。

  • align-content对单行无效,对多行有效。
  • align-content 定义多根轴线的对齐方式,如果弹性项目只有一根轴线,该属性无效。
  • align-content仅适用于多行Flex容器,即Flex容器中的Flex项不止一行时该属性才有效果。
  • align-content的作用是当Flex容器在交叉轴上存在多余空间时,会将所有Flex项作为一个整体进行对齐。
align-content: stretch | flex-start | flex-end | center | space-between | space-around;
多行对齐
  • flex-start
    各行向Flex弹性容器的起始位置堆叠,弹性容器中第一行的侧轴起始边界紧靠在该弹性容器的侧轴起始边界,之后每行都紧靠前一行。
# 以交叉轴的起点对齐
.flex-container{
  display:flex;
  align-content: flex-start;
}
内容对齐 起点对齐 flex-start
  • flex-end
    各行向弹性容器结束位置堆叠,弹性容器最后一行侧轴结束边界紧靠弹性容器侧轴结束边界,之后每行紧靠前一行。
# 以交叉轴的终点对齐
.flex-container{
  display:flex;
  align-content: flex-end;
}
内容对齐 低点对齐 flex-end
  • center
    各行向弹性容器中间位置堆叠,各行两两紧靠同时在弹性容器中居中对齐,同时保持弹性容器侧轴起始内容边界和第一行之间的距离与弹性容器侧轴结束内容边界 与最后一行之间的距离相等。若剩余空间为负数则各行会向两个方向溢出相等距离。
# 以交叉轴的中点对齐
.flex-container{
  display:flex;
  align-content: center;
}
内容对齐 居中 center
  • stretch
    各行拉伸以占据剩余空间,若剩余空间为负数,则等效于flex-start。其他情况下剩余空间会被所有行平分以扩大侧轴尺寸。
# 默认轴线占满整个交叉轴
.flex-container{
  display:flex;
  align-content: stretch;
}
内容对齐 stretch
  • space-between
    各行在弹性容器中平均分布,若剩余空间是负数或弹性容器中仅有一行,则该值等效于flex-start。其他情况下,第一行的侧轴起始边界紧靠弹性容器侧轴起始内容边界,最后一行侧轴结束边界紧靠弹性容器侧轴结束内容边界,剩余行按一定方式在弹性容器中排列,以保持两两之间空间相等。
# 与交叉轴两端对齐,轴线之间的间隔平均分布。
.flex-container{
  display:flex;
  align-content: space-between;
}
内容对齐 平均分布
  • space-around

各行在弹性容器中平均分布,两端保留子元素之间间距大小的一半儿,若剩余空间为负数或弹性盒子中仅有一行,则等效于center。其他情况各行按一定方式在弹性容器中排列以保持两两之间相等空间,同时第一行前和最后一行后空间是其他空间的一半儿。

# 每根轴线两侧的间隔相等,轴线之间的间隔比轴线与边框的间隔间隔大一倍。
.flex-container{
  display:flex;
  align-content: space-around;
}
内容对齐

案例

例如:垂直居中

Flexbox布局出现前要实现元素垂直居中的方式

  • 水平居中
    • 块级元素 水平居中:width:100px; height:100px; margin:0 auto; 设置宽高后使用margin: 0 auto实现
    • 行内元素 水平居中:text-align:center;
  • 垂直居中
    • 行内元素 单行 垂直居中:父元素上设置heightline-height两个相等的值即可
    • 行内元素 多行 垂直居中:配置使用tabletable-cell实现,或添加伪元素占位填充实现。
    • 块级元素 固定宽高 垂直居中:借助绝对定位,设置元素的top:50%;后在margin-top:-width/2以实现
    • 块级元素 宽高不定 垂直居中:借助绝对定位,设置元素的top:50%; transform:translateY(-50%)以实现

使用Flexbox布局实现元素的水平垂直居中的方式,只需要在弹性容器内让弹性项目在主轴和交叉轴上分别居中对齐即可。也就使用justify-content定义弹性项目在主轴上的排列方式为center,使用align-items定义弹性项目在交叉轴上的排列方式为center

.flex-container{
  display:flex;
  justify-content:center;
  align-items:center;
}

若针对弹性项目本身可使用align-self属性来覆盖弹性容器的align-items属性以定义弹性项目在弹性容器内部交叉轴上的排列方式。

.flex-container{display:flex; justify-content:center;}
.flex-item{align-self:center;}

弹性项目(Flex Item)

Flexbox弹性布局最大的特性是让Flex弹性项目可伸缩,也就是让Flex弹性项目的宽度和高度可以自动填充Flex弹性容器剩余空间,或缩小Flex弹性项目以适配Flex弹性容器不足的宽度。这一切都依赖于Flexbox属性中的flex属性来完成。

一个Flex弹性容器会等比的按照Flex弹性项目的扩展比率来分配Flex弹性容器的剩余空间,也会按照收缩比例来缩小Flex弹性项目,以免Flex弹性项目溢出Flex弹性容器。

Flexbox弹性布局中,flex属性是flex-grow(扩展比率)、flex-shrink(收缩比率)、flex-basis(伸缩基准)三个属性的简称,这三个属性可以控制一个弹性项目。

  • flex-grow 设置弹性项目的扩展比率,让弹性项目伸缩多少弹性容器多余空间。
  • flex-shrink 设置弹性项目的收缩比例,让弹性项目减去弹性容器不足的空间。
  • flex-basis 设置弹性项目未扩展或收缩前的大小

弹性项目6属性

属性 描述
flex-grow 扩展比例,默认为0。
flex-shrink 收缩比例,默认为1。
flex-base 用于定义在分配多余空间前,项目占据的主轴空间大小。
flex flex-grow、flex-shrink、flex-basis三个的简写,默认值为 0 1 auto。
align-self 设置单个项目对齐方式
order 设置弹性项排列位置,默认为0,值越小越靠前。

剩余空间

在Flexbox布局中,弹性容器包含一个或多个弹性项目,即父容器中的子节点或子元素。弹性容器和弹性项目都由自身的尺寸,因此会出现所有弹性项目尺寸之和大于或小于弹性容器尺寸的情况。

  • 剩余空间
    当所有弹性项目尺寸之和小于弹性容器时,弹性容器会存有多余空间没有被填充,这个多余空间被称为弹性容器的剩余空间(Positive Free Space)。

  • 空间不足
    当所有弹性项目尺寸之和大于弹性容器时,弹性容器将没有足够空间来容纳所有的弹性项目,这多出来的空间称为负空间(Negative Free Space)。

扩展比例(Flex Grow)

flex-grow属性用于设置弹性项目(Flex Item)的扩展比例,即根据弹性项目设置的扩展因子作为比率来计算并分配剩余空用空间。

flex-grow

flex-grow主要在父元素宽度大于子元素宽度之和时起作用,用于定义子元素如何分配父元素的剩余空间,默认为0,即默认不会索取父元素的宽度。

flex-grow: <number> (default 0);
  • <number> 使用数值来定义扩展比率,不允许为负数。
  • default 0 默认值为0

若没有显式的为弹性项声明flex-grow属性,弹性项目是不会拥有分配剩余空间的权利。

flex-grow不支持负数,默认为0表示不占用父元素剩余空间来扩展自己的宽度。若flex-grow大于0则Flex容器剩余空间的分配会发生:

  • 若只有一个Flex项目设置了flex-grow属性
    • flex-grow小于1时会分配给它的是“总剩余空间*比例”的计算值
    • flex-grow大于1时则独享剩余空间
  • 若存在多个Flex项目都设置列flex-grow属性
    • flex-grow总和小于1时分配给元素的是“总剩余空间 * 当前比例值”
    • flex-grow总和大于1时则所有剩余空间都被利用

例如:分配剩余空间

.flex-container{
  display:flex;
}
.flex-item:first-child{
  flex-grow:1;
}
.flex-item:last-child{
  flex-grow:1;
}
.flex-item:nth-child(2){
  flex-grow:2;
}
.flex-item:nth-child(3){
  flex-grow:1;
}
扩展比例

例如:实现三栏等高布局,两侧宽度固定,中间 一栏占满剩余空间。

.flex-container{
  display:flex;
}
.flex-item:first-child, .flex-item:last-child{
  width:200px;
}
.flex-item:nth-child(2){
  flex-grow:1;
}

弹性项设置flex-grow:1即可沾满弹性项目水平剩余空间

  • 若Flex容器没设置固定高度,Flex容器的高度会自动被最高的Flex项目撑开,同时其他元素高度也会被拉升到Flex容器一样的高度。
  • 若Flex容器设置了固定高度,Flex项目高度都设置为auto,则所有Flex项目都会自动跟父元素一样高。

flex-growflex-basis一样只适用于主轴,默认flex-direction:row时只会影响width,若flex-direction:column则此时影响的height

收缩比例(Flex Shrink)

flex-shrink属性适用于弹性容器内的弹性项目,用于设置或检索弹性项目的收缩比例,即根据弹性项目所设置的收缩因子作为比率来收缩空间。

flex-shrink
flex-shrink: <number> (default 1);

flex-shrink默认值为1,若没有显式定义该属性则自动按照默认值1在所有因子相加后计算并收缩空间。当空间不足时,将等比缩小。若弹性项中有一个设置flex-shrink为0,其他均为flex-shrink为1,当空间不足时,flex-shrink属性为0的元素不缩小。

flex-shrink

伸缩基准(Flex Basis)

flex-basis属性用于弹性项目告知父容器,在剩余空间被分配之前先定义子元素的默认尺寸,可指定百分比或rem等长度长度或auto关键字。

flex-basis: <length> | auto (default auto);
  • auto 表示无特定宽度值,具体取决于其他属性值。
  • <length> 表示使用长度值来定义宽度,不允许负数。
  • <percentage> 表示使用百分比来定义宽度,不允许为负数。

例如:

.flex-container{
  display:flex;
}
.flex-basis-0{
  flex-basis:0;
}
.flex-basis-1{
  flex-basis:1;
}
.flex-basis-auto{
  flex-basis:auto;
}

flex-basis设置为0则表示父容器分配剩余空间之前,会将每个子元素的默认尺寸视为0,剩余空间即父容器的全部空间,表现出直接按照flex-grow值设置的比例分配子元素的大小。

flex-basis设置为auto则表示父容器将每个子元素中的内容作为子元素的默认尺寸,通过计算剩余空间最后将剩余空间按照flex-grow值得比例平均分配到子元素中除内容以外得空间即padding

flex-basis

flex-basis属性适用于弹性项目,用于设置或检索弹性项目伸缩基准值。 flex-basis属性定义了在分配多余剩余空间之前,弹性项目占据主轴空间大小。浏览器会根据此属性,计算主轴是否具有多余空间,其默认值为auto即弹性项目本身大小。

flex-basis控制一个弹性项目的默认大小,但它可以被其它Flexbox属性影响。若同时为弹性项目设置flex-basiswidth属性,则flex-basis会覆盖width的取值。flex-basis属性看上去和width属性可以等价互换,它们之间有什么不同之处呢?

  • flex-basis是对应于Flex轴线而言的
  • flex-basis影响弹性项目在主轴上的大小
flex-basis VS width
flex-basis是对应于Flex轴线而言的

当保持flex-basis缩放基准不变的情况下,改变flex-direction主轴方向此时会发生什么情况呢?此时会发现,flex-basis是根据flex-direction的方向的不同来确定widthheight的,因此必须手动将height属性切换到width属性。

image

例如:

.flex-container{
  display:flex;
}
.flex-item:first-child{

}
.flex-item:nth-child(2){
  width:70px;
  flex-basis:auto;
}
.flex-item:last-child{
  width:50px;
  flex-basis:100px;
}
  • 弹性项目1:flex-basis为默认设置autowidth为默认设置auto,因此占据空间由内容所决定。
  • 弹性项目2:flex-basis设置为autowidth设置为70px,内容空间为70px。
  • 弹性项目3:flex-basis设置为100px,width设置为50px,flex-basis覆盖width,内容空间为100px。

复合属性(Flex)

  • flex属性适用于弹性项目,用于设置或检索弹性项目如何分配空间。
  • flex属性是flex-growflex-shrinkflex-basis三个的缩写,默认值为0 1 auto
flex: none | [flex-grow] || [flex-shrink] || [flex-basis];
flex
  • flex:none表示计算值为flex: 0 0 auto
  • flex:auto表示计算值为flex: 1 1 auto
  • flex:1表示计算值为flex:1 1 0

例如:三栏移动优先布局

.flex-container{
  display: flex;
  flex-flow: row wrap;
}
.header, .main, .nav, .aside, .footer{
  flex: 1 100%;
}

@media all and (min-width:600px){
  .aside{ flex:1 auto; }
}
@media all and (min-width:800px){
  .main{flex: 2 0px;}
  .aside-1{order:1;}
  .main{order:2;}
  .aside-2{order:3;}
  .footer{order:4;}
}
三栏移动优先

例如:圣杯布局

互联网早期由于网速限制,经常会出现HTML内容显示出来但样式还未加载完成而导致用户没能最先看到想看的内容,因此Matthew Levine于2006年提出了圣杯布局,即在HTML源码中将用户想看到的内容挪到次要内容的前面。

圣杯布局(Holy Grail Layout)即三三布局,页面从上到下分为三部分分别是头部、躯干、尾部,躯干由水分划分为三部分从左到右依次是导航、主栏、副栏。

圣杯布局
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>圣杯布局</title>
</head>
<body>
  <header>header</header>
  <div class="content">
    <main>main</main>
    <nav>nav</nav>
    <aside>aside</aside>
  </div>
  <footer>footer</footer>
</body>
</html>
body{display:flex; flex-direction:column; min-height:100vh;}
header, footer{flex:1;}
.content{flex:1; display:flex;}
.content nav, .content aside{flex:0 0 12em;}
.content main{flex:auto;}
.content nav{order:-1;}

@media (max-width:768px){
  .content{flex:1; flex-direction:column;}
  .content nav, .content aside, .content main{flex:auto;}
}

例如:输入框组

<style>
.flex-container{display:flex;}
.flex-1{flex;1;}
</style>

<div class="flex-container">
  <span>prepend</span>
  <input class="flex-1"/>
  <span>append</span>
</div>

例如:悬挂式布局,即主栏的左侧或右侧需添加一栏图片

<style>
.flex-container{display:flex;}
.align-items-start{align-items:flex-start;}
.flex-1{flex;1;}
.media-figure{margin-right:1em;}
</style>
<div class="media flex-container align-items-start">
  <img class="media-figure" src="http://www.quanbaike.com/tool/picapi/2d/api.php" width="400"/>
  <div class="media-body flex-1">
    media body media body media body media body media body
  </div>
</div>

例如:底栏固定,页面内容太少无法沾满一屏高度时底栏会被抬高到页面中间。

<style>
.container{display:flex; flex-direction:column; min-height:100vh;}
.flex-1{flex;1;}
</style>

<div class="container">
  <header>header</header>
  <main class="flex-1">main</main>
  <footer>footer</footer>
</div>

例如:两栏布局
两栏布局常用于博客或信息类页面,可分为固定宽度+自适应、不定宽度+自适应两种模式

<div class="container">
  <main>main</main>
  <aside>aside</aside>
</div>
  • 固定宽度+自适应
    aside侧边栏固定宽度为200px,main主内容区域自适应,main主内容区域结构靠前是为了优先加载显示,aside侧边栏可通过设置order属性来调整。main主内容区域设置flex-grow:1表示使该区域填充容器空白空间。使用flex-grow:1能达到填充弹性容器剩余空间在原因在于侧边栏aside默认的flex-grow:0即不伸缩放大,设置主内容区域mainflex-grow:1表示放大填充整个空白区域。
.container{display:flex;}
.container main{flex-grow:1;}
.container aside{width:200px; order:-1;}
  • 不定宽度 + 自适应
    即两栏均采用自适应宽度,可设置主内容区域宽度为侧边栏宽度的倍数来间接实现。
.container{display:flex;}
.container main{flex:2;}
.container aside{flex:1; order:-1;}

例如:弹性盒子自适应

<style>
*{margin:0; padding:0;}
.container{display:flex; flex-wrap:wrap; justify-content:center;}
.item{flex:0 1 300px; margin:20px; padding:20px; box-sizing:border-box; border:3px solid #9db783; background-color:#fdf6e3;}
</style>

<section class="container">
    <article class="item">
        <span class="title">将进酒</span> <br> 
        <span class="content">君不见, <br>黄河之水天上来, 奔流到海不复回, <br>君不见,<br> 高堂明镜悲白发, 朝如青丝暮成雪</span>
    </article>
    <article class="item">
        <span class="title">丹歌惊鸿</span> <br> 
        <span class="content">天地匆匆 惊鸿而过 路有千百个<br>遑遑无归 闲云逸鹤 人间红尘过<br>引势而流 鸿门乱局 各有各选择<br>乾震坎艮 坤巽离兑 定一切生克</span>
    </article>
    <article class="item">
        <span class="title">将进酒</span> <br> 
        <span class="content">君不见, <br>黄河之水天上来, 奔流到海不复回, <br>君不见,<br> 高堂明镜悲白发, 朝如青丝暮成雪</span>
    </article>
</section>

侧轴对齐(Align Self)

align-self属性适用于弹性项目,用于设置或检索弹性项目自身在纵轴方向上的对齐方式。

align-self: auto | flex-start | flex-end | center | baseline | stretch;
  • auto:若align-self设置为auto,其计算值为父元素的align-items,若无父元素则为stretch
  • flex-start:弹性项目侧轴起始位置边界紧靠该行侧轴起始边界
  • flex-end:弹性项目侧轴起始位置边界紧靠该行侧轴结束边界
  • center:弹性项目在该行侧轴上居中对齐,若该行尺寸小于弹性容器则会向两个方向溢出相同长度。
  • baseline:若弹性项目行内轴与侧轴为同一条则与flex-start等效,其它情况下则为基线对齐。
  • stretch:若侧轴大小为auto,则弹性项边距会尽可能接近所在行的尺寸,同时会遵照min/max-width/height限制。

排列顺序(Order)

默认情况下Flexbox弹性容器中的弹性项目会按照文档声明的顺序来排列,可使用order顺序控制弹性项目出现在父容器中的顺序,order属性值默认为0,order属性值越小越靠前。

例如:

.flex-container{
  display:flex;
}
.flex-item:first-child{
  order:-1;
}
.flex-item:last-child{
  order:1;
}

案例

音乐播放界面

UI
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>文档标题</title>
  <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body>
  <main>Item1</main>
  <footer>Item2</footer>
</body>
</html>


<body>
  <main>
    <aside>item 1b</aside>
    <section>item 1a</section>
  </main>
  <footer>Item2</footer>
</body>

<body>
  <main>
    <aside>item 1b</aside>
    <section>
      <div>item 1a - A</div>
      <div>item 1a - B</div>
    </section>
  </main>
  <footer>Item2</footer>
</body>

基本布局结构

*{box-sizing:border-box;}
html{height:100%}
/*layout*/
body{display:flex; flex-direction:column; background-color:#fff; height:100%; margin:0; font-size:0.9em; color:#222;}
main{flex:1 0 auto; display:flex;}
footer{flex:0 0 90px; display:flex; padding:10px; background-color:rgba(61, 100, 158, .9); color:#fff;}
/*main*/
main aside{flex:0 0 40px; display:flex; flex-direction:column; justify-content:space-around; align-items:center; background-color: #f2f2f2;}
main section{flex:1 0 auto; display:flex; flex-direction:column;}

设置body为Flexbox容器,footer吸附底部,main填满剩余空间。

  • footer作为弹性项目设置flex0 0 90px表示不缩放并固定为90px高度
  • main作为弹性项目设置flex1 0 auto
    其中flex-grow为1表示填满整个空间,由于部分浏览器中存在Flex项目收缩后会比其内容尺寸小,所以将flex-shrink设置为0而非默认的1,同时设置flex-basisauto。即告知浏览器自动计算Flex项目大小但禁止收缩。Flex项目会随着浏览器缩放而收缩,因此此时缩放并不是基于flex-shrink而是基于自动对Flex项目的宽度进行的重新计算即flex-basis:auto
基本布局结构

固定侧边栏

侧边栏
main aside{
    flex:0 0 40px;
    display:flex; 
    flex-direction:column; 
    justify-content:space-around; 
    align-items:center; 
    background-color: #f2f2f2;
}
/*aside*/
aside i{font-size:0.9em;}
  • aside设置flex0 0 40px表示不会放大或缩小,固定在40px。
  • aside设置displayflex将其转化为Flex容器,并设置其主轴方向flex-directioncolumn为垂直堆放。
  • aside内弹性项目通过设置justify-contentspace-aroundalign-itemscenter将垂直对齐。
<aside>
  <i class="fa fa-bars"></i>
  <i class="fa fa-home"></i>
  <i class="fa fa-search"></i>
  <i class="fa fa-volume-up"></i>
  <i class="fa fa-user"></i>
  <i class="fa fa-spotify"></i>
  <i class="fa fa-cog"></i>
  <i class="fa fa-soundcloud"></i>
</aside>

设置内容区域

/*content*/
.content .head{flex:0 0 280px; display:flex; padding:40px; background-color:#4e4e4e;}
.content .list{flex:1 0 auto; padding:5px 10px 0;}
/*content head*/
.head img{width:150px;}
.head .info{flex:1 0 auto; display:flex; flex-direction:column; padding-left:50px; font-weight:300; color:#fff; }
.info div:first-child{margin-bottom:auto;}
.info div:last-child{margin-top:0;}
.info div:last-child i{font-size:0.9em; font-weight:300; padding:0 0.7em;}
/*content list*/
.list .item{display:flex; padding:0 20px; min-height:50px;}
.list .item div{flex:0 0 25%;}
<section class="content">
  <section class="head">
    <img src="https://uploadbeta.com/api/pictures/random/?key=BingEverydayWallpaperPicture" />
    <div class="info">
      <div>
        <div>title</div>
        <div>author</div>
        <div>datetime</div>
      </div>
      <div>
        <i class="fa fa-play">play</i>
        <i class="fa fa-plus">add</i>
        <i class="fa fa-ellipsis-h">more</i>
      </div>
    </div>
  </section>
  <section class="list">
    <div class="item">
      <div>title</div>
      <div>author</div>
      <div>during</div>
      <div>cateory</div>
    </div>
  </section>
</section>

工具

Flexbox布局样例

https://flexbox.webflow.com/
http://www.yyyweb.com/tag/css3
https://c.runoob.com/front-end/61
https://lincenying.github.io/vue2-flex/
https://www.html.cn
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,233评论 6 495
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,357评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,831评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,313评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,417评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,470评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,482评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,265评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,708评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,997评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,176评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,827评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,503评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,150评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,391评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,034评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,063评论 2 352