css弹性盒子-flex真实场景应用

129 阅读4分钟

Flex 布局是什么?

Flex 简介

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

任何一个容器都可以指定为 Flex 布局。

.box {
  display: flex;
}

行内元素也可以使用 Flex 布局。

.box {
  display: inline-flex;
}

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

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

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

Flex 容器属性

  • flex-direction
  • flex-wrap
  • flex-flow
  • justify-content
  • align-items
  • align-content

flex 是以下属性的简写属性:

  • flex-grow
  • flex-shrink
  • flex-basis

flex 设置的是弹性项目的弹性长度。

flex: flex-grow flex-shrink flex-basis|auto|initial|inherit;
描述
默认值:0 1 auto
flex-grow数字,规定项目相对于其余弹性项目的增长量。
flex-shrink数字,规定项目相对于其余弹性项目的收缩量。
flex-basis项目的长度。合法值:"auto"、"inherit",或单位为 "%", "px", "em" 的值,或任何其他长度单位。
auto等同于 1 1 auto。
initial等同于 0 1 auto。参阅 initial
none等同于 0 0 auto。
inherit从其父元素继承该属性。参阅 inherit

Flex 基本使用

场景一

整个页面分为两大部分,我们希望左边部分作为菜单栏,宽度固定;右边部分作为内容展示区,宽度自适应且占满剩余部分。

类似如下布局

image.png 常规方式:浮动(float)

首先,将框架搭起来

<div id="app">
  <div id="nav">
    <div class="main-content">
      <div class="left-content">Left</div>
      <div class="right-content">Right</div>
    </div>
  </div>
</div>

为了方便查看效果,给每个盒子设置大小与添加背景色

<style>
.main-content {
  width: 100%;
  height:100%;
  background: #72f884;
}
.left-content {
  box-sizing: border-box;
  width: 200px;
  height: 200px;
  background: rgb(238, 119, 34);
}
.right-content {
  box-sizing: border-box;
  width: 200px;
  height: 200px;
  background: rgb(68, 133, 255);
}
</style>

初始页面展示效果

image.png

现在,使用浮动(float),使左边跟右边并列布局

<style>
.main-content {
  width: 100%;
  height:100%;
  background: #72f884;
}
.left-content {
  box-sizing: border-box;
  width: 200px;
  height: 200px;
  background: rgb(238, 119, 34);
  /* 使用浮动完成左右并列布局 */
  float: left;
}
.right-content {
  box-sizing: border-box;
  width: 200px;
  height: 200px;
  background: rgb(68, 133, 255);
  /* 使用浮动完成左右并列布局 */
  float: left;
}
</style>

页面展示效果

image.png

此时,再将右边的宽度通过 calc() 方法计算,实现右边自适应

<style>
.right-content {
  box-sizing: border-box;
  /* width: 200px; */
  height: 200px;
  background: rgb(68, 133, 255);
  /* 使用浮动完成左右并列布局 */
  float: left;
  /* 使用calc(),右边宽度 = 总宽度 - 左边菜单栏宽度  */
  width: calc(100% - 200px);
}
</style>

缩小窗口,查看效果

image.png

此时,实现了场景一的需求,效果看起来也还OK。但是有个问题,现在的这个布局使用的是浮动,即代表着这两个块脱离了文档流,如果页面有其他布局区域,如头部导航栏、底部关于栏、甚至是其他主内容区,这时候我们可能就需要花点时间去清除浮动带来的影响,或者是增加更多的浮动来完成其他区域的布局。

那么有没有一种布局是既可以不使用浮动(或者说是不脱离文档流),又能实现上面的布局呢?答案是肯定的,可以使用Flex(弹性布局),且写起来也更简便。

现在,我们将浮动样式去掉,在包含左右两个盒子的父盒子加上 display:flex,表示使用弹性布局

.main-content { width: 100%; height:100%; background: #72f884; /* 使用flex弹性布局 */ display: flex; } .left-content { box-sizing: border-box; width: 200px; height: 200px; background: rgb(238, 119, 34); } .right-content { box-sizing: border-box; width: 200px; height: 200px; background: rgb(68, 133, 255); }

此时查看页面效果

实现右边部分自适应只需要为右边添加样式 flex:1 即可

.right-content {
  box-sizing: border-box;
  width: 200px;
  height: 200px;
  background: rgb(68, 133, 255);
  /* 表示该盒子自动占满剩余空间(往下展开) */
  flex: 1;
}

此时左右两个盒子并列布局,且右边自适应,why?以下详细展开。

  • row(默认值):主轴为水平方向,起点在左端。
  • row-reverse:主轴为水平方向,起点在右端。
  • column:主轴为垂直方向,起点在上沿。
  • column-reverse:主轴为垂直方向,起点在下沿。

布局图示

image.png

上面例子不设置该属性,因此为默认值(row),即主轴水平、从左到右排列。

场景二

整个页面分为多个部分,我们希望这些部分是并列布局,且宽度自适应。

页面布局如下(以三个部分举例,若更多部分做法一致)

<div id="app">
  <div id="nav">
    <div class="main-content">
      <div class="left-content">Left</div>
      <div class="middle-content">Middle</div>
      <div class="right-content">Right</div>
    </div>
  </div>
</div>

初始样式(同样,父盒子使用flex布局)

<style>
.main-content {
  width: 100%;
  height:100%;
  background: #72f884;
  /* 使用flex弹性布局 */
  display: flex;
}
.left-content {
  box-sizing: border-box;
  width: 200px;
  height: 200px;
  background: rgb(238, 119, 34);
}
.middle-content {
  box-sizing: border-box;
  width: 200px;
  height: 200px;
  background: rgb(173, 40, 250);
}
.right-content {
  box-sizing: border-box;
  width: 200px;
  height: 200px;
  background: rgb(68, 133, 255);
}
</style>

初始页面效果

image.png

现在,我们三个子盒子的宽度是固定的,因此实现不了自适应,我们可以使用 %(百分比)方式设置各个子盒子相对于父盒子所占的百分比

<style>
.left-content {
  box-sizing: border-box;
  /* 宽度使用 % ,实现自适应 */
  width: 30%;
  height: 200px;
  background: rgb(238, 119, 34);
}
.middle-content {
  box-sizing: border-box;
  /* 宽度使用 % ,实现自适应 */
  width: 40%;
  height: 200px;
  background: rgb(173, 40, 250);
}
.right-content {
  box-sizing: border-box;
  /* 宽度使用 % ,实现自适应 */
  width: 30%;
  height: 200px;
  background: rgb(68, 133, 255);
}
</style>

页面展示效果

image.png

缩小查看页面展示效果

image.png

注意观察,此时三个子盒子的宽度总和等于父盒子的宽度,即30% + 40% + 30% = 100%。

如果三个盒子的宽度占比总和小于100%,即都为30%,页面效果如下

image.png

场景三

当有三层结构时,里面内容超出出现滚动条,img与tabs需要滚动吸顶,需要满足响应式布局,而且 img高度不固定,tabs高度也不固定,都是需要响应试

效果如图

image.png

代码如下

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <!-- <link rel="stylesheet" href="./css/icon.css"> -->
    <!-- <link rel="stylesheet" href="https://at.alicdn.com/t/c/font_3707518_9pf84wy6xl5.css"> -->
    <!-- <script src="./moment.min.js"></script> -->
    <style>
      body {
        overflow: auto;
      }
      *{
        margin: 0;
        padding: 0;
      }
      .box1{
        display: flex;
        flex-direction: column;
        background-color: aqua;
        height: 100vh;
       
      }
      .img{
        height: 80px;
        background: red;
        text-align: center;
        line-height: 80px;
        font-weight: bold;
        color: #fff;
      }
      .box3{
        flex: 1;
        overflow: auto;
        display: flex;
        flex-direction: column;
      }
      .tabs{
        display: flex;
        justify-content: space-evenly;
        align-items: center;
        height: 60px;
        line-height: 60px;
        background: #fff;
      }
      .item{
        height: 100%;
        text-align: center;
        background-color: orange;
        flex: 0 1 30% ;
      }
      .box5{
        flex: 1;
        overflow: auto;
      }
      .content1{
        height: 200vh;
      }
    </style>
  </head>
  <body>
    <div class="box">
      <div class="box1">
        <div class="img">img</div>
        <div class="box3">
          <div class="tabs" onclick="item(event)">
            <div class="item">1</div>
            <div class="item">2</div>
            <div class="item">3</div>
          </div>
          <div class="box5">
            <div class="content1">content1</div>
          </div>
        </div>
      </div>
    </div>
    <script>
      function item(event){
        console.log(event.target.innerHTML);
      }
    </script>
  </body>
</html>