flex布局和grid布局的详解

4,242 阅读9分钟

这是我参与11月更文挑战的第一天,活动详情请查看:2021最后一次更文挑战

前言

刚进公司的前端实习生,同事让我从页面样式布局写起,当时UI给我提的需求是页面可以适应任何屏幕的分辨率,同时在屏幕大小变化的情况下,内容居中,到左右俩边的margin永远一样(就是内容永远居中,到右边的距离为margin-right:15px;那么到左边的距离也应该为margin-left:15px;)。当时觉得这个问题应该很简单,使用简单的CSS 样式就可以实现,给内容设置一个div,在div上添加margin:0 auto的样式,应该就可以实现,在多次修改之后UI大哥还是不满意,而且自己第一做有好多东西不懂,就去请教了当时进公司带我的师傅,师傅和我说可以试试flex布局。在研究flex布局的时候,又发现了grid布局,今天就把flex布局和grid布局一起整理一下。

在正文开始之前,先给大家说一下容器和项目的概念,之前再看容器和项目概念的时候,总是朦胧的认知,想着这不是一样的吗?后来真的弄明白之后才发现这个是不一样的。容器相当于一个盒子外面的包装--大箱子,项目是具体的内容--大箱子里面的小箱子,根据项目的属性给小箱子设置样式(小箱子在大箱子中的摆放顺序)

flex布局

image.png

基本概念

Flex 是 Flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。任何一个容器都可以指定为 Flex 布局。采用 Flex 布局的元素,称为 Flex 容器,它的所有子元素自动成为容器成员,称为 Flex 项目。

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

容器的属性

容器的属性一共有6个,分别是:flex-direction、flex-warp、flex-flow、just-content、algin-items、align-content。

1. flex-direction:row(默认)——决定主轴的方向(项目排列的方向)

<style>
     /*这里的样式为接下来的所有页面的样式*/
    .container{
        width: 50%;
        display: flex;
        background-color: antiquewhite;
        box-shadow:  0px 2px 2px 0px rgba(9, 2, 4, 0.1);
    }
    .box{
        width: 100px;
        height: 100px;
        margin: 15px;
        background-color: coral;
    }
</style>
  • flex-direction:row/row-reverse(横向排列)
<body>
    <!--flex-direction:row--是默认排列方式,也是最常用的排列方式-->
    <h3>flex-direction:row--主轴为水平方向,从左向右排列</h3>
    <div class="container" style="flex-direction: row">
        <div class="box">第一个</div>
        <div class="box">第二个</div>
        <div class="box">第三个</div>
    </div>
    
    <h3>flex-direction:row-reverse--主轴为水平方向,从右向左排列</h3>
    <div class="container" style="flex-direction: row-reverse">
        <div class="box">第一个</div>
        <div class="box">第二个</div>
        <div class="box">第三个</div>
    </div>
</body>

image.png

  • flex-direction:column/column-reverse(纵向排列)
<body>
    <h3>flex-direction:column--主轴为垂直方向,从上向下排列</h3>
    <div class="container" style="flex-direction: column">
        <div class="box">第一个</div>
        <div class="box">第二个</div>
        <div class="box">第三个</div>
    </div>
</body>

image.png

<body>
    <h3>flex-direction:column-reverse----主轴为垂直方向,从下往上排列</h3>
    <div class="container" style="flex-direction: column-reverse">
        <div class="box">第一个</div>
        <div class="box">第二个</div>
        <div class="box">第三个</div>
    </div>
</body>

image.png

2.flex-warp:nowrap(默认)——当一条轴线上排列不下,怎么换行

<h3>flex-wrap: nowrap--不换行</h3>
<div class="container" style="flex-direction: row;flex-wrap: nowrap">
    <div class="box">第一个</div>
    <div class="box">第二个</div>
    <div class="box">第三个</div>
    <div class="box">第四个</div>
    <div class="box">第五个</div>
    <div class="box">第六个</div>
</div>

image.png

<h3>flex-wrap: wrap--换行</h3>
<div class="container" style="flex-direction: row;flex-wrap: wrap">
    <div class="box">第一个</div>
    <div class="box">第二个</div>
    <div class="box">第三个</div>
    <div class="box">第四个</div>
    <div class="box">第五个</div>
    <div class="box">第六个</div>
</div>

image.png

<div class="container" style="flex-direction: row;flex-wrap: wrap-reverse">
    <div class="box">第一个</div>
    <div class="box">第二个</div>
    <div class="box">第三个</div>
    <div class="box">第四个</div>
    <div class="box">第五个</div>
    <div class="box">第六个</div>
</div>

image.png

<h3>flex-direction:row-reverse 和 flex-wrap: wrap-reverse 的值的结合使用</h3>
<div class="container" style="flex-direction: row-reverse;flex-wrap: wrap-reverse">
    <div class="box">第一个</div>
    <div class="box">第二个</div>
    <div class="box">第三个</div>
    <div class="box">第四个</div>
    <div class="box">第五个</div>
    <div class="box">第六个</div>
</div>

image.png 注: 以上演示的情况为主轴方向为默认横向时,所排列的样式。即:flex-direction:row;如果flex-direction:column主轴纵向时,则排列方式就会如下图。

image.png

image.png

image.png

3.flex-flow:row nowrap(默认)

flex-flow: flex-direction flex-warp;用于同时设置之前属性的值,下面以默认轴向为横向做演示。

  • flex-flow: row nowrap
<h3>flex-flow: row nowrap</h3>
<div class="container" style="flex-flow: row nowrap">
    <div class="box">第一个</div>
    <div class="box">第二个</div>
    <div class="box">第三个</div>
    <div class="box">第四个</div>
    <div class="box">第五个</div>
    <div class="box">第六个</div>
</div>

image.png

  • flex-flow: row wrap
<h3>flex-flow: row wrap</h3>
<div class="container" style="flex-flow: row wrap">
    <div class="box">第一个</div>
    <div class="box">第二个</div>
    <div class="box">第三个</div>
    <div class="box">第四个</div>
    <div class="box">第五个</div>
    <div class="box">第六个</div>
</div>

image.png

  • flex-flow: row wrap-reverse
<h3>flex-flow: row wrap-reverse</h3>
<div class="container" style="flex-flow: row wrap-reverse">
    <div class="box">第一个</div>
    <div class="box">第二个</div>
    <div class="box">第三个</div>
    <div class="box">第四个</div>
    <div class="box">第五个</div>
    <div class="box">第六个</div>
</div>

image.png

4.justify-content: flex-start(默认)——设置主轴上的排列方式

  • justify-content: flex-start
<h3>justify-content: flex-start</h3>
<div class="container" style="justify-content: flex-start">
    <div class="box">第一个</div>
    <div class="box">第二个</div>
    <div class="box">第三个</div>
</div>

image.png

  • justify-content: flex-end
<h3>justify-content: flex-end</h3>
<div class="container" style="justify-content: flex-end">
    <div class="box">第一个</div>
    <div class="box">第二个</div>
    <div class="box">第三个</div>
</div>

image.png

  • justify-content: center
<h3>justify-content:center</h3>
<div class="container" style="justify-content: center">
    <div class="box">第一个</div>
    <div class="box">第二个</div>
    <div class="box">第三个</div>
</div>

image.png

之前我在前言中所遇到的问题,便是用这行代码样式解决的,到左右俩侧的距离永远一致。

  • justify-content: space-between 这个样式在排列布局的时候,会先将第一行和第二行的俩侧距离相等分配,之后在平均分配剩余的空间
<h3>两端对齐justify-content: space-between</h3>
<div class="container" style="justify-content: space-between;flex-wrap: wrap">
    <div class="box">第一个</div>
    <div class="box">第二个</div>
    <div class="box">第三个</div>
</div>
<div class="container" style="justify-content: space-between;">
    <div class="box">第一个</div>
    <div class="box">第二个</div>

</div>

image.png

  • justify-content: space-around 容器中的每个项目的左右边距相等,平均分配项目的左右边距。
<h3>justify-content: space-around:平均分配剩余空间</h3>
<div class="container" style="justify-content: space-around;flex-wrap: wrap">
    <div class="box">第一个</div>
    <div class="box">第二个</div>
    <div class="box">第三个</div>
    <div class="box">第四个</div>
    <div class="box">第五个</div>
    <div class="box">第六个</div>
    <div class="box">第七个</div>
</div>

image.png

补充: 当主轴为column时,必需设置高度;

<style>
    .container{
        width: 50%;
        background-color: antiquewhite;
        box-shadow:  0px 2px 2px 0px rgba(9, 2, 4, 0.1);
        display: flex;
        flex-direction: row;
    }
    .main{
        width: 50%;
        height:600px;/*如果不设置样式,则justify-content: center;就不起作用*/
        background-color: antiquewhite;
        box-shadow:  0px 2px 2px 0px rgba(9, 2, 4, 0.1);
        display: flex;
        flex-direction: column;
    }
    .box{
        width: 100px;
        height: 100px;
        margin: 15px;
        background-color: coral;
    }
</style>
<body>
<h3>justify-content: center</h3>
<div class="main" style="justify-content: center;">
    <div class="box">第一个</div>
    <div class="box">第二个</div>
    <div class="box">第三个</div>
</div>
</body>

image.png

5.algin-items:设置侧轴上的对齐方式(单行)

  • align-items: flex-start
<style>
    .container{
        width: 50%;
        height: 300px;
        display: flex;
        background-color: antiquewhite;
        box-shadow:  0px 2px 2px 0px rgba(9, 2, 4, 0.1);
        flex-direction: row;
    }
    .container1{
        width: 50%;
        height: 600px;
        display: flex;
        background-color: antiquewhite;
        box-shadow:  0px 2px 2px 0px rgba(9, 2, 4, 0.1);
        flex-direction: row;
    }
    .box{
        width: 100px;
        height: 100px;
        margin: 15px;
        background-color: coral;
    }
    .box1{
        width: 100px;
        height: 200px;
        margin: 15px;
        background-color: coral;
    }
    .box2{
        width: 150px;
        height: auto;
        background-color: #47f816;
    }
    .box3{
        width: 150px;
        background-color: #ee00ff;
    }
</style>
<body>
<h3>align-items: flex-start</h3>
<div class="container" style="align-items: flex-start">
    <div class="box">第一个</div>
    <div class="box1">第二个</div>
    <div class="box">第三个</div>
</div>
</body>

image.png

  • align-items: flex-end
<h3>align-items: flex-end</h3>
<div class="container" style="align-items: flex-end">
    <div class="box">第一个</div>
    <div class="box1">第二个</div>
    <div class="box">第三个</div>
</div>

image.png

  • align-items: center
<h3>align-items: center</h3>
<div class="container" style="align-items: center">
    <div class="box">第一个</div>
    <div class="box1">第二个</div>
    <div class="box">第三个</div>
</div>

image.png

  • align-items: baseline
<h3>align-items: baseline--以项目的第一行文字的对齐</h3>
<div class="container" style="align-items: baseline;">
    <div class="box">第一个 默认</div>
    <div class="box" style="align-self: flex-start">第二个 align-self: flex-start</div>
    <div class="box1" style="padding-top: 50px;">第三个 padding-top: 50px;</div>
    <div class="box" style="padding-top: 50px;"><p>第四个</p><p>padding-top: 50px;</p></div>
</div>

image.png

  • align-items: stretch
<h3>align-items: stretch</h3>
<div class="container" style="align-items: stretch;">
    <div class="box">第一个</div>
    <div class="box1">第二个</div>
    <div class="box">第三个</div>
</div>
<h3>align-items: stretch:不要设置高度</h3>
<div class="container" style="align-items: stretch;">
    <div class="box1">第一个</div>
    <div class="box2">height:auto</div>
    <div class="box3">没有设置高度</div>
</div>

image.png

image.png

6.align-content:设置侧轴上的对齐方式(多行)

  • align-content: flex-start
<style>
    .container{
        width: 50%;
        height: 500px;
        background-color: antiquewhite;
        box-shadow:  0px 2px 2px 0px rgba(9, 2, 4, 0.1);
        display: flex;
        flex-direction: row;
        flex-wrap: wrap;
    }
    .box{
        width: 100px;
        height: 100px;
        margin: 15px;
        background-color: coral;
    }

</style>
<body>
<h3>align-content: flex-start</h3>
<div class="container" style="align-content: flex-start">
    <div class="box">第一个</div>
    <div class="box">第二个</div>
    <div class="box">第三个</div>
    <div class="box">第四个</div>
    <div class="box">第五个</div>
    <div class="box">第六个</div>
    <div class="box">第七个</div>
    <div class="box">第八个</div>

</div>

image.png

  • align-content: flex-end
<h3>align-content: flex-end</h3>
<div class="container" style="align-content: flex-end">
    <div class="box">第一个</div>
    <div class="box">第二个</div>
    <div class="box">第三个</div>
    <div class="box">第四个</div>
    <div class="box">第五个</div>
    <div class="box">第六个</div>
    <div class="box">第七个</div>
    <div class="box">第八个</div>
</div>

image.png

  • align-content: center
<h3>align-content: center</h3>
<div class="container" style="align-content: center">
    <div class="box">第一个</div>
    <div class="box">第二个</div>
    <div class="box">第三个</div>
    <div class="box">第四个</div>
    <div class="box">第五个</div>
    <div class="box">第六个</div>
    <div class="box">第七个</div>
    <div class="box">第八个</div>
</div>

image.png

  • align-content: space-around
<h3>align-content: space-around</h3>
<div class="container" style="align-content: space-around">
    <div class="box">第一个</div>
    <div class="box">第二个</div>
    <div class="box">第三个</div>
    <div class="box">第四个</div>
    <div class="box">第五个</div>
    <div class="box">第六个</div>
    <div class="box">第七个</div>
    <div class="box">第八个</div>
</div>

image.png

  • align-content: space-between
<h3>align-content: space-between</h3>
<div class="container" style="align-content: space-between">
    <div class="box">第一个</div>
    <div class="box">第二个</div>
    <div class="box">第三个</div>
    <div class="box">第四个</div>
    <div class="box">第五个</div>
    <div class="box">第六个</div>
    <div class="box">第七个</div>
    <div class="box">第八个</div>
</div>

image.png

  • align-content: space-evenly
<h3>align-content: space-evenly</h3>
<div class="container" style="align-content: space-evenly">
    <div class="box">第一个</div>
    <div class="box">第二个</div>
    <div class="box">第三个</div>
    <div class="box">第四个</div>
    <div class="box">第五个</div>
    <div class="box">第六个</div>
    <div class="box">第七个</div>
    <div class="box">第八个</div>
</div>

image.png

项目的属性

项目的属性是针对一个大的div中的具体的内容设置的元素(也就是给大箱子中的小箱子设置样式)。一共6有个属性,分别是:order、flex-grow、flex-shrink、flex-basis、flex、align-self。

1. order

定义容器中项目的排列顺序,数值越小项目越靠前

   .container{
       width: 80%;
       height: 200px;
       display: flex;
       background-color: antiquewhite;
       box-shadow:  0px 2px 2px 0px rgba(9, 2, 4, 0.1);
       flex-direction: row;
   }
   .box{
       width: 100px;
       height: 100px;
       margin: 15px;
       background-color: coral;
   }
<div class="container" style="">
    <div class="box">第一个</div>
    <div class="box">第二个</div>
    <div class="box">第三个</div>
    <div class="box">第四个</div>
    <div class="box">第五个</div>
</div>

<h3>order:5--4--3--2--1</h3>
<div class="container" >
    <div class="box" style="order: 5">第一个</div>
    <div class="box" style="order: 4">第二个</div>
    <div class="box" style="order: 3">第三个</div>
    <div class="box" style="order: 2">第四个</div>
    <div class="box" style="order: 1">第五个</div>
</div>

<h3>order:2 和 4 交换--只对添加的order的item 做排练顺序</h3>
<div class="container" >
    <div class="box" >第一个</div>
    <div class="box" style="order: 2">第二个</div>
    <div class="box" >第三个</div>
    <div class="box" style="order: 4">第四个</div>
    <div class="box" >第五个</div>
</div>

image.png 补充: 当有俩个order的值相等时,按自己本身的值排列。如下:

<div class="container" >
    <!--这里有使俩个box 的order的值为3,style="order: 3-->
    <div class="box" style="order: 3">第一个</div>
    <div class="box" style="order: 3">第二个</div>
    <div class="box" style="order: 2">第三个</div>
    <div class="box" style="order: 4">第四个</div>
    <div class="box" style="order: 1">第五个</div>
</div>

image.png

2. flex-grow

属性定义项目存在剩余空间时的放大比例,默认值是flex-grow: 0。即使当宽度固定,子项目也会被放大。

<style>
    .container{
        width: 50%;
        height: 200px;
        display: flex;
        background-color: antiquewhite;
        box-shadow:  0px 2px 2px 0px rgba(9, 2, 4, 0.1);
        flex-direction: row;
    }
    .box{
        width: 100px;
        height: 100px;
        margin: 15px;
        background-color: coral;
    }
</style>
<h3>默认</h3>
<div class="container" style="">
    <div class="box">第一个</div>
    <div class="box">第二个</div>
    <div class="box">第三个</div>
</div>
<h3>flex-grow: 2</h3>
<div class="container" style="">
    <div class="box">第一个</div>
    <div class="box" style="flex-grow: 2">第二个</div>
    <div class="box">第三个</div>
</div>
<h3>flex-grow: 0.5</h3>
<div class="container" style="">
    <div class="box">第一个</div>
    <div class="box" style="flex-grow: 0.5">第二个</div>
    <div class="box">第三个</div>
</div>

image.png

3. flex-shrink

项目的缩小比例,默认为flex-shrink: 1,当实际的项目大小超过容器所规定的大小时(容器空间不足时),项目就会自动缩小自己的宽度或者高度。

.container{
    width: 50%;
    height: 200px;
    display: flex;
    background-color: antiquewhite;
    box-shadow:  0px 2px 2px 0px rgba(9, 2, 4, 0.1);
    flex-direction: row;
}
.box{
    width: 100px;
    height: 100px;
    margin: 15px;
    background-color: coral;
}
<h3>默认</h3>
<div class="container" style="">
    <div class="box">第一个</div>
    <div class="box">第二个</div>
    <div class="box">第三个</div>
    <div class="box">第四个</div>
    <div class="box">第五个</div>

</div>
<h3>2和4 的 flex-shrink: 0</h3>
<div class="container" style="">
    <div class="box">第一个</div>
    <div class="box" style="flex-shrink: 0">第二个</div>
    <div class="box">第三个</div>
    <div class="box" style="flex-shrink: 0">第四个</div>
    <div class="box">第五个</div>
</div>

image.png

4. flex-basis

在分配多余的空间之前,根据项目占据的主轴空间去计算在主轴上是否有多余的空间。默认值flex-basis: | auto; 即,项目本身的大小,我们设置项目元素的width的大小。

.container{
    width: 100%;
    display: flex;
    background-color: antiquewhite;
    box-shadow:  0px 2px 2px 0px rgba(9, 2, 4, 0.1);
    flex-direction: row;
}
.box{
    width: 100px;
    height: 100px;
    margin: 15px;
    background-color: coral;
}
.box1{
    height: 100px;
    margin: 15px;
    background-color: coral;
}
<h3>默认</h3>
<div class="container" style="">
    <div class="box">第一个</div>
    <div class="box">第二个</div>
    <div class="box">第三个</div>
    <div class="box">第四个</div>
</div>
<h3>设置auto 或者固定的像数值</h3>
<div class="container" style="">
    <div class="box" style="flex-basis: auto">第一个</div>
    <div class="box1" style="flex-basis: 300px;">flex-basis: 300px;</div>
    <div class="box">第三个</div>
    <div class="box" style="flex-basis: 500px;">设置宽度的基础上又设置了flex-basis: 500px;</div>
</div>

image.png

5. flex

flex-grow + flex-shrink + flex-basis = flex。定义子项目分配剩余空间,用flex来表述占多少份。

.container{
    width: 50%;
    height: 200px;
    display: flex;
    background-color: antiquewhite;
    box-shadow:  0px 2px 2px 0px rgba(9, 2, 4, 0.1);;
}
.box{
    width: 100px;
    height: 100px;
    margin: 15px;
    background-color: coral;
}
  • flex:0 1 auto; 也可以写成flex:1
<h3>flex:默认值 0 1 auto--不放大,会缩小</h3>
<div class="container" style="">
    <div class="box">第一个</div>
    <div class="box">第二个</div>
    <div class="box">第三个</div>
</div>

image.png

  • flex: 1 1 auto;也可以写成flex: auto
<h3>flex:auto(1 1 auto)--等分放大缩小</h3>
<div class="container" >
    <div class="box">第一个</div>
    <div class="box" style="flex:auto">第二个</div>
    <div class="box">第三个</div>

</div>

image.png

  • flex: 0 0 auto;flex:none
<h3>flex:none(0 0 auto)--不放大不缩小</h3>
<div class="container" >
    <div class="box">第一个</div>
    <div class="box" style="flex:none">第二个</div>
    <div class="box">第三个</div>

</div>

image.png

  • flex:1 0 auto;
<h3>flex:1 0 auto---会放大,不会缩小</h3>
<div class="container" >
    <div class="box">第一个</div>
    <div class="box" style="flex:1 0 auto">第二个</div>
    <div class="box">第三个</div>
</div>

image.png

6. align-self

默认值为align-self:auto,继承父元素设置的align-items的值。控制子项目在侧轴的对其方式。

.container{
    width: 50%;
    height: 400px;
    display: flex;
    background-color: antiquewhite;
    box-shadow:  0px 2px 2px 0px rgba(9, 2, 4, 0.1);
    align-items: center;
}
.box{
    width: 100px;
    height: 100px;
    margin: 15px;
    background-color: coral;
}
.box1{
    width: 100px;
    height: 200px;
    background-color: coral;
}
<h3>父容器设置的值为--align-items: center;</h3>
<div class="container" style="">
    <div class="box">第一个</div>
    <div class="box1" >第二个 </div>
    <div class="box" style="align-self: auto">第三个 align-self: auto</div>
    <div class="box" style="align-self: flex-end">第四个设置末端对齐align-self: flex-end</div>
    <div class="box" style="align-self: flex-start">第五个设置顶部对齐 align-self: flex-start</div>
</div>

image.png

最后

flex是一维布局 ,grid是二维布局;也就是说grid布局可以更好的操作行和列。flex布局和grid布局是现在的主流的两种布局方式。

项目演示获取代码地址

本来是想写grid布局的,但是感觉flex布局写的内容太多了,就临时打算把grid布局写在下一篇的更新文章中。。。。。。。。。