Flex布局

116 阅读5分钟

布局的传统解决方案,基于盒状模型,依赖 display属性 + position属性 + float属性。它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现。

Flex布局是什么?

flex意为“弹性布局”,用来为盒状模型提供最大的灵活性,我们常用的pc端和移动端的适配基本上都是用flex布局解决的,如果一个元素使用了flex弹性布局(以下都会简称为:flex布局),则会在内部形成BFC

交叉与主轴

image.png 学习flex布局需要明白”主轴“与”交叉轴“的概念,采用flex布局的元素,称为”容器“ ( flex container),它的所有子元素都是容器的”项目“(flex item),容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)。主轴的开始位置(与边框的交叉点)叫做 main start ,结束位置叫做 main end ;交叉轴的开始位置叫做 cross start ,结束位置叫做 cross end

容器的属性

  1. flex-direction:决定主轴的方向(即项目的排列方向)

    flex-direction有四个属性值

    row(默认值):主轴为水平方向,起点在左端

image.png

  .main {
    width: 500px;
    height: 300px;
    background: skyblue;
    display: flex;
    flex-direction: row;
  }

  .main div {
    width: 100px;
    height: 100px;
    background: pink;
    font-size: 20px;
  }
    <div class="main">
        <div>1</div>
        <div>2</div>
        <div>3</div>
        <div>4</div>
        <div>5</div>
        <div>6</div>
     </div>

row-reverse:主轴为水平方向,起点在右端

image.png

column:主轴为垂直方向,起点在上端

image.png

column-reverse:主轴为垂直方向,起点在下端

image.png

flex-wrap属性

在默认情况下,项目都排在一条线上,无论是否给定宽度,都是不会主动换行 默认属性:nowrap不换行

wrap属性:换行,第一行在上方

image.png wrap-reverse属性:第一行在下方

image.png flex-flow属性

flex-direction属性和flex-wrap属性的简写形式默认值是 row nowrap

flex-flow: row nowrap;//<flex-direction>|| <flex-wrap>

justify-content属性

justify-content属性定义了项目在主轴上的对齐方式

flex-start(默认值):左对齐

image.png flex-end:右对齐

image.png center:居中对齐

image.png space-around每个元素两侧的间隔相等

image.png space-between两侧元素靠边对齐中间元素均匀对齐

image.png space-evenly:每个项目的间隔与项目和容器之间的间隔是相等的

image.png align-items属性

align-items属性定义项目在交叉轴上(垂直方向)如何对齐

flex-start:交叉轴(垂直方向)的起点对齐

image.png flex-end:垂直方向底部对齐

image.png center:垂直方向居中对齐

image.png

stretch(默认值): 如果项目未设置高度或设为auto,将占满整个容器的高度(我把height高度清空了)

image.png

align-content属性

align-content属性定义了轴线的对齐方式,

  1. 前提是需要对父元素设置设flex-wrap:wrap否则不会生效
  2. 对父元素设置自由盒属性display:flex;
  3. 对父元素设置align-content相关的属性

flex-start属性:交叉轴的起点对齐

image.png

flex-end属性:交叉轴的底部对齐

image.png

stretch:轴线占满整个交叉轴

image.png

order(定义在子元素身上)

order 属性定义项目的排列顺序。数值越小,排列越靠前,默认为0,可以是负数。

.main {
    width: 500px;
    height: 300px;
    background: skyblue;
    display: flex;
    /* flex-direction: row;
    flex-wrap: wrap-reverse; */
    flex-flow: row wrap;
    /* justify-content: space-evenly; */
    /* align-items: stretch; */
    align-content: stretch;
  }

  .main div {

    width: 100px;
    height: 100px;
    background: pink;
    font-size: 20px;
  }

  .five {
    order: 1;
  }

  .one {
    order: 2;
  }

  .two {
    order: 3;
  }

<div class="main">
    <div class="one">1</div>
    <div class="two">2</div>
    <div class="three">3</div>
    <div class="four">4</div>
    <div class="five">5</div>

  </div>

image.png  flex-grow(定义在子元素身上)

flex-grow flex容器中剩余空间的多少应该分配给项目,也称为扩展规则。最终的项目的宽度为:自身宽度 + 容器剩余空间分配宽度,flex-grow最大值是1,超过1按照1来扩展

flex-grow: <number>; /* default 0 */

image.png

image.png

flex-grow: 0.2; /* default 0 *///盒子1

flex(定义在子元素身上)

flex 属性是 flex-grow , flex-shrinkflex-basis 的简写,默认值为 0 1 auto 。后两个属性可选。

flex: none | [ <'flex-grow'><'flex-shrink'>? || <'flex-basis'>]

flex-shrink

flex-shrink 属性指定了 flex 元素的收缩规则。flex 元素仅在默认宽度之和大于容器的时候才会发生收缩,其收缩的大小是依据 flex-shrink 的值,默认值是1

flex-shrink: <number>; /* default 1 */

默认情况下,第一个div宽度是200,第二个div宽度是300,两个相加应该超过父元素的400,但是由于 flex-shrink 都设置为1,将两个div都收缩在父元素中

.item {
    width: 400px;
    height: 300px;
    background: skyblue;
    display: flex;
    padding: 5px;
  }

  .item div {
    height: 100px;
    font-size: 20px;
  }

  .item div:nth-child(1) {
    flex-shrink: 1;
    width: 200px;
    background: pink;
  }

  .item div:nth-child(2) {
    flex-shrink: 1;
    width: 300px;
    background: cadetblue;
  }

image.png

image.png

那收缩后的子项宽度是怎么样计算的呢?实际上有一个公示:

  1. (200+300)所有子项的宽度的和 - (400)容器的宽度 = (100)
  2. 第一个子项的宽度占比:2/5,第二个子项的宽度占比:3/5
  3. 则第一个子项的的宽度为:200 - 2/5 * 100 = 160,第二个子项的宽度为:300 - 3/5 * 100 = 240

等高布局

每一列的内容不一样,但容器的高度时等高的

 .item {
    width: 400px;
    height: 300px;
    background: skyblue;
    display: flex;
    justify-content: space-between;
    padding: 5px;
  }

  .item div {
    width: 100px;
    font-size: 20px;
    background: pink;
  }

  .item div p {
    text-align: center;
  }

image.png 左侧宽度固定,右侧自适应布局

html,
  body {
    margin: 0;
    padding: 0;
  }

  .container {
    display: flex;
    width: 100%;
    height: 100vh;
    background: skyblue;
  }

  .left-tree {
    width: 200px;
    height: 100%;
    background: pink;
  }

  .main {
    flex: 1 1 auto;
  }

image.png 常见的TOB系统布局方式,左侧是菜单树,右侧是内容

黏贴性页脚

无论中间的内容有多少,页脚始终在底部展示

 html,
  body {
    margin: 0;
    padding: 0;
  }

  .container {
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100vh;
  }

  .header {
    width: 100%;
    height: 60px;
    background: pink;
  }

  .main {
    flex: 1 1 auto;
    background: skyblue;
  }

  .footer {
    width: 100%;
    height: 60px;
    background: pink;
  }

image.png flex布局 实现布局效果。缺点是相较于 grid网格布局 来说, flex布局 是 一维布局 ,一般用于单行或者单列的布局,如果要实现多行多列的布局,推荐使用 gird网格布局