Flex布局

在介绍Flex布局之前,先简述一下display属性。因为涉及到了 display: flex。详细介绍参考 https://developer.mozilla.org/en-US/docs/Web/CSS/display

display 属性是使用关键字值指定的。关键字值分为六个值类别:

.container {
display: [ <display-outside> || <display-inside> ] | <display-listitem> | <display- internal> | <display-box> | <display-legacy> ;
}
  • display-outside:这些关键字指定元素的外部显示类型,本质上是元素在流布局中的作用。

    • block:该元素生成一个块元素框,在正常流动中时在元素之前和之后都产生换行符。

    • inline:元素会生成一个或多个内联元素框,这些框不会在自身之前或之后产生换行符。在正常流动中,如果有空间,则下一个元素将在同一行上。

    • run-in:元素生成一个插入框。如果定义为display: run-in box 的元素的相邻同级 是一个block box,则该run-inbox成为其后的block box的第一个内联框。

  • display-inside:这些关键字指定元素的内部显示类型。

    • flow、flow-root、table、flex、grid、ruby

因此display属性值不仅有 block、inline、inline-block,还有flex。

Flex 布局

布局的传统解决方案,基于盒状模型,依赖 display 属性 + position属性 + float属性。它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现。2009年,W3C 提出了一种新的方案----Flex 布局,可以简便、完整、响应式地实现各种页面布局。目前,它已经得到了所有浏览器的支持,这意味着,现在就能很安全地使用这项功能。详细介绍参考阮一峰老师的教程。 http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html

1. Flex布局是什么

Flex 是 Flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。

两个重要的概念:

(1)开启 flex 布局的元素叫做 flex container(容器)

(2)flex container 里面的直接子元素叫做 flex items(项目)

设置 display 属性为 flex 或者 inline-flex 都可以成为 flex container:

(1)flex:flex container 以 block-level 形式存在

(2)inline-flex:flex container 以 inline-level 形式存在

// html:
<div class="box">
    <div></div>
    <div></div>
    <div></div>
</div>
<strong>strong是行内元素</strong>

// css:
<style>
    .box {
      width: 300px;
      height: 300px;
      background-color: pink;
      /* display: flex; */
      display: inline-flex
    }
</style>

Webkit 内核的浏览器,必须加上-webkit前缀。

.box{
display: -webkit-flex; /* Safari */
display: flex;
}

注意,设为 Flex 布局以后,子元素的floatclearvertical-align属性将失效。

2. 基本概念

采用 Flex 布局的元素,称为 Flex 容器(flex container),简称"容器"。它的所有子元素自动成为容器成员,称为 Flex 项目(flex item),简称"项目"。

容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)

主轴的开始位置(与边框的交叉点)叫做 main start,结束位置叫做 main end

交叉轴的开始位置叫做 cross start,结束位置叫做 cross end

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

3. 容器的属性

所有的flex布局必须把父元素的display设置成flex,才能够使用flex布局。

以下6个属性设置在容器上。

  • flex-direction

    • 该属性决定主轴的方向(即项目的排列方向)。有如下属性值:

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

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

    • column:主轴为垂直方向,起点在上沿。

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

     

  • flex-wrap

    • 默认情况下,项目都排在一条线("轴线")上。flex-wrap属性定义,如果一条轴线排不下,如何换行。

    • nowrap(默认):不换行。

    • wrap:换行,第一行在上方。

    • wrap-reverse:换行,第一行在下方。

     

  • flex-flow

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

     

  • justify-content

    • 定义了项目在主轴上的对齐方式。有如下属性值:

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

    • flex-end:右对齐

    • center: 居中

    • space-between:两端对齐(对准边线),项目之间的间隔都相等。

    • space-around:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。

    • space-evenly:均匀排列每个元素,每个元素之间的间隔相等。

     

  • align-items

    • 定义项目在交叉轴上如何对齐。有如下属性值:

    • stretch(默认值):如果项目未设置高度或设为auto,则项目将占满整个容器的高度。
    • flex-start:交叉轴的起点对齐。

    • flex-end:交叉轴的终点对齐。

    • center:交叉轴的中点对齐。

    • baseline: 项目的第一行文字的基线对齐。

 

  • align-content

    • 定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。

    • flex-start:与交叉轴的起点对齐。

    • flex-end:与交叉轴的终点对齐。

    • center:与交叉轴的中点对齐。

    • space-between:与交叉轴两端对齐,轴线之间的间隔平均分布。

    • space-around:每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。

    • stretch(默认值):轴线占满整个交叉轴。

 

4. 项目的属性

以下6个属性设置在项目上。

  • order

    • 定义项目的排列顺序。数值越小,排列越靠前,默认为0。

  • flex-grow

    • 定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。

    • 如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。

  • flex-shrink

    • 定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。

    • 如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。负值对该属性无效。

  • flex-basis

    • 定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。它可以设为跟widthheight属性一样的值(比如350px),则项目将占据固定空间。

  • flex

    • 它是flex-grow, flex-shrinkflex-basis的简写,默认值为0 1 auto。后两个属性可选。建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。

    • 该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)。

       

       

  • align-self

    • 允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch

    • align-self: auto | flex-start | flex-end | center | baseline | stretch;

    • 该属性可能取6个值,除了auto,其他都与align-items属性完全一致。

5. 骰子的布局(详细介绍参考上述提供网站)

6. 网格的布局

(1) 基本网格布局

最简单的网格布局,就是平均分布。在容器里面平均分配空间,跟骰子布局很像,但是需要设置项目的自动缩放。

 

 

 

 

 

 关于 flex: 1 的相关说明:(参考https://www.cnblogs.com/zhus/p/7161702.html

flexflex-growflex-shrinkflex-basis的缩写。故其取值可以考虑以下情况:

  • flex 的默认值是 0 1 auto。由于这里flex-grow是0,所以即使存在剩余空间,也不放大。

  • flex 取值为 none,计算值为 0 0 auto。即如果存在剩余空间,不放大。若空间不足,该项目也不缩小。
  • flex 取值为 auto,计算值为 1 1 auto。即如果存在剩余空间,会放大。若空间不足,该项目会缩小。

  • flex 取值为一个非负数字,则该数字为 flex-grow 值,flex-shrink 取 1,flex-basis 取 0%
  • flex 取值为两个非负数字,则分别视为 flex-growflex-shrink 的值,flex-basis 取 0%

下面举例说明:

<div class="parent">
  <div class="item-1"></div>
  <div class="item-2"></div>
  <div class="item-3"></div>
</div>

<style type="text/css">
  .parent {
      display: flex;
      width: 600px;
  }
  .parent > div {
      height: 100px;
  }
  .item-1 {
      width: 140px;
      flex: 2 1 0%;
      background: blue;
  }
  .item-2 {
      width: 100px;
      flex: 2 1 auto;
      background: darkblue;
  }
  .item-3 {
      flex: 1 1 200px;
      background: lightblue;
  }
</style>
  • 主轴上父容器总尺寸为 600px

  • 子元素的总基准值是:0% + auto + 200px = 300px,其中

    - 0% 即 0 宽度
    - auto 对应取主尺寸即 100px
  • 故剩余空间为 600px - 300px = 300px

  • 伸缩放大系数之和为: 2 + 2 + 1 = 5

  • 剩余空间分配如下:

    - item-1 和 item-2 各分配 2/5,各得 120px
    - item-3 分配 1/5,得 60px
  • 各项目最终宽度为:

    - item-1 = 0% + 120px = 120px
    - item-2 = auto + 120px = 220px
    - item-3 = 200px + 60px = 260px
  • 当 item-1 基准值取 0% 的时候,是把该项目视为零尺寸的,故即便声明其尺寸为 140px,也并没有什么用,形同虚设

  • 而 item-2 基准值取 auto 的时候,根据规则基准值使用值是主尺寸值即100px, 故这100px不会纳入剩余空间

 

 

(2) 百分比布局

<style>
    .Grid {
      display: flex;
      background-color: pink;
    width: 800px;
    }
    .Grid-cell {
      flex: 1;
    }
    .Grid-cell:nth-child(1) {
       flex: 0 0 50%;
    }

    .Grid-cell:nth-child(2) {
       flex: 0 0 30%;
      background-color: purple;
    }

    .Grid-cell:nth-child(3) {
       flex: 0 0 10%;
       background-color: blue;
    }

  </style>
</head>
<body>
  <div class="Grid">
    <div class="Grid-cell">盒子1</div>
    <div class="Grid-cell">盒子2</div>
    <div class="Grid-cell">盒子3</div>
  </div>
</body>

这里主要讨论以下 flex-basis 的取值情况:

  • auto:首先检索该子元素的主尺寸,如果主尺寸不为 auto,则使用值采取主尺寸之值;如果也是 auto,则使用值为 content

  • content:指根据该子元素的内容自动布局。有的用户代理没有实现取 content 值,等效的替代方案是 flex-basis 和主尺寸都取 auto

  • 百分比:根据其包含块(即伸缩父容器)的主尺寸计算。如果包含块的主尺寸未定义(即父容器的主尺寸取决于子元素),则计算结果和设为 auto 一样。

 

(3)圣杯布局

<style>
    .HolyGrail {
      display: flex;
      /* min-height: 100vh; */
      flex-direction: column;
      width: 500px;
      height: 500px;
      background-color: pink;
    }

    header,
    footer {
      flex: 1;
      background-color: purple;
    }

    .HolyGrail-body {
      display: flex;
      flex: 2;
    }

    .HolyGrail-content {
      flex: 1;
      background-color: blue;
    }

    .HolyGrail-nav,
    .HolyGrail-ads {
      /* 两个边栏的宽度设为 30% 空余部分会由 HolyGrail-content补齐*/
      flex: 0 0 30%;
    }

    .HolyGrail-nav {
      /* 导航放到最左边 */
      order: -1;
    }

  </style>


<body>
  <div class="HolyGrail">
    <header>header</header>
    <div class="HolyGrail-body">     
      <nav class="HolyGrail-nav">left</nav>
      <main class="HolyGrail-content">center</main>
      <aside class="HolyGrail-ads">right</aside>
    </div>
    <footer>footer</footer>
  </div>
</body>

 

 (4)输入框的布局

我们常常需要在输入框的前方添加提示,后方添加按钮。如下图效果:

 

 

<style>
    .InputAddOn {
      display: flex;
    }

    .InputAddOn-field {
      flex: 1;
    }
  </style>


<body>
  <div class="InputAddOn">
    <span class="InputAddOn-item">...</span>
    <input class="InputAddOn-field">
    <button class="InputAddOn-item">...</button>
  </div>
</body>

 

 (5)悬挂式布局

有时,主栏的左侧或右侧,需要添加一个图片栏。如下图效果:

HTML代码如下:
<div class="Media">
  <img class="Media-figure" src="" alt="">
  <p class="Media-body">...</p>
</div>
CSS代码如下:
.Media {
  display: flex;
  align-items: flex-start;  /* 定义代码在交叉轴的起点对齐 */
}

.Media-figure {
  margin-right: 1em;
}

.Media-body {
  flex: 1;
}
 

 

(6)固定的底栏

有时,页面内容太少,无法占满一屏的高度,底栏就会抬高到页面的中间。这时可以采用Flex布局,让底栏总是出现在页面的底部。

 

HTML代码如下:
<body class="Site">
  <header>...</header>
  <main class="Site-content">...</main>
  <footer>...</footer>
</body>

CSS代码如下:
.Site {
  display: flex;
  min-height: 100vh;
  flex-direction: column;
}

.Site-content {
  flex: 1;  /* 由于flex-grow默认为0,将中间部分设置为1,若存在剩余空间会放大 */
}

 

(7)流式布局

每行的项目数固定,会自动分行。

 

 

CSS的写法如下:
.parent {
  width: 200px;
  height: 150px;
  background-color: black;
  display: flex;
  flex-flow: row wrap;
  align-content: flex-start;
}

.child {
  box-sizing: border-box;
  background-color: white;
  flex: 0 0 25%;
  height: 50px;
  border: 1px solid red;
}

 

posted @ 2020-04-24 21:54  BAHG  阅读(239)  评论(1编辑  收藏  举报