首页 > 技术文章 > flex布局---8.flex布局原理

deer-cen 2019-12-28 09:13 原文

1 传统布局与flex布局

传统布局(以之前所学的PC端布局为例)

  • 兼容性好
  • 布局繁琐
  • 局限性,不可以在移动端很好的布局
    flex弹性布局
  • 操作方便简单,移动端应用广泛
  • PC端浏览器支持情况较差
  • IE11或更低版本,不支持或仅部分支持
    建议
  • 如果是PC端页面布局,采用传统布局
  • 如果是移动端或者不考虑兼容性问题的PC端布局,采用flex弹性布局

2 布局原理

flex用来为盒状模型提供最大的灵活性,任何一个容器都可以指定为flex布局。

  • 当为父盒子设置为flex布局之后,子元素的float、clear、vertical-align属性将失效。(不需要浮动、清除浮动、盒子垂直居中,因为flex都可以代替这些功能)
  • 伸缩布局=弹性布局=伸缩盒布局=弹性盒布局=flex布局

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

  • 体验中div就是flex父容器
  • 体验中span就是子容器flex项目
  • 子容器可以横向排列也可以纵向排列

总结flex布局原理:
就是通过给父盒子添加flex属性,来控制子盒子的位置和排列方式。

3 父项常见属性

3.1 flex-direction设置主轴的方向

flex-direction属性决定主轴的方向(即项目的排列方向)
注意:主轴和侧轴是会变化的,就看flex-direction设置谁为主轴,剩下的就是侧轴,我们的子元素是根据主轴来排列的。
flex-direction的属性值:

  • row(默认值从左到右)
  • row-reverse(从右到左)
  • column(从上到下)
  • column-reverse(从下到上)
<body>
    <div>
        <span>1</span>
        <span>2</span>
        <span>3</span>
    </div>
</body>
<style>
    div {
        /* 给父亲添加flex属性 */
        display: flex;
        /* 添加flex之后,行内元素也有宽高;*/
        width: 500px;
        height: 200px;
        background-color: pink;
        /* 默认沿着x轴排列 */
        /* flex-direction: row; 默认值 */
        flex-direction: row-reverse;
        /* flex-direction: column; */
        /* flex-direction: column-reverse; */
    }
    
    div span {
        width: 100px;
        height: 50px;
        background-color: skyblue;
        margin: 2px 10px;
    }
</style>
  • flex-direction: row;

  • flex-direction: row-reverse;

  • flex-direction: column;

  • flex-direction: column-reverse;

3.2 justify-content设置主轴的子元素对齐方式

justify-content属性定义了项目在主轴上的对齐方式;注意:使用这个属性之前要确定好主轴是哪一个。

  • flex-start:头对齐(默认值)
  • flex-end:尾对齐
  • center:在主轴居中对齐,如果主轴是x轴则水平居中
  • space-around:平分剩余空间
  • space-between:先两边贴边再平分剩余空间(重要)
<body>
    <div>
        <span>1</span>
        <span>2</span>
        <span>3</span>
        <span>4</span>
    </div>
</body>
<style>
    div {
        /* 给父亲添加flex属性 */
        display: flex;
        /* 添加flex之后,行内元素也有宽高;*/
        width: 800px;
        height: 200px;
        background-color: pink;
        /* 主轴默认是x轴 */
        /* 1. 左对齐 */
        /* justify-content: flex-start; */
        /* 2. 右对齐 (子盒子顺序不变)*/
        /* justify-content: flex-end; */
        /* 3. 居中对齐 */
        /* justify-content: center; */
        /* 4. 平分剩余空间  此时对span设置的左右外边距会失效*/
        /* justify-content: space-around; */
        /* 5. 先两边贴边再平分所有空间  span如果设置了左右外边距,则两端盒子的外边距会保留*/
        justify-content: space-between;
    }
    
    div span {
        width: 100px;
        height: 50px;
        background-color: skyblue;
        margin: 2px 10px;
    }
</style>
  • justify-content: flex-start;左对齐

  • justify-content: flex-end; 右对齐 (子盒子顺序不变)

  • justify-content: center;居中对齐

  • justify-content: space-around;平分剩余空间 此时对span设置的左右外边距会失效

  • justify-content: space-between;先两边贴边再平分所有空间 span如果设置了左右外边距,则两端盒子的外边距会保留

3.3 flex-wrap设置主轴的子元素是否换行

默认情况下,项目都排在一条线(轴线)上。flex-wrap属性定义,flex布局默认是不换行的。

  • nowrap:默认值,不换行
  • wrap:换行
<body>
    <div>
        <span>1</span>
        <span>2</span>
        <span>3</span>
        <span>4</span>
        <span>5</span>
    </div>
</body>
<style>
    div {
        /* 给父亲添加flex属性 */
        display: flex;
        /* 添加flex之后,行内元素也有宽高;*/
        width: 500px;
        height: 200px;
        background-color: pink;
        /* flex布局中,默认的子元素是不换行的,如果装不开,会缩小子元素宽度,放到父元素里面 */
        /* 1.默认值 默认不换行 */
        flex-wrap: nowrap;
        /* 2. 换行 */
        /* flex-wrap: wrap; */
    }
    
    div span {
        width: 150px;
        height: 100px;
        background-color: skyblue;
        margin: 2px 10px;
    }
</style>
  • flex-wrap: nowrap;默认值 默认不换行

  • flex-wrap: wrap;放不下就换行

3.4 align-items设置侧轴上的子元素对齐方式(单行)

该属性是控制子项在侧轴(默认是y轴)上的排列方式,在子项为单行的时候使用。

  • flex-start:头对齐
  • fllex-end:尾对齐
  • center:挤在一起(垂直居中)
  • stretch:拉伸

center:挤在一起(垂直居中)举例如下

<body>
    <div>
        <span>1</span>
        <span>2</span>
        <span>3</span>
    </div>
</body>
<style>
    div {
        /* 给父亲添加flex属性 */
        display: flex;
        /* 添加flex之后,行内元素也有宽高;*/
        width: 800px;
        height: 200px;
        background-color: pink;
        /* 沿着主轴(x轴) 水平居中对齐 */
        justify-content: center;
        /* 沿着侧轴(y轴) 垂直居中 */
        align-items: center;
    }
    
    div span {
        width: 150px;
        height: 100px;
        background-color: skyblue;
        color: #fff;
        margin: 10px;
    }
</style>

对于stretch:拉伸,举例如下

<body>
    <div>
        <span>1</span>
        <span>2</span>
        <span>3</span>
    </div>
</body>
<style>
    div {
        /* 给父亲添加flex属性 */
        display: flex;
        /* 添加flex之后,行内元素也有宽高;*/
        width: 800px;
        height: 200px;
        background-color: pink;
        /* 沿着主轴(x轴) 水平居中对齐 */
        justify-content: center;
        /* 沿着侧轴(y轴) 拉伸 */
        align-items: stretch;
    }
    
    div span {
        width: 150px;
        /* height: 100px;  使用stretch的时候要将子项的height取消,否则无法拉伸 */
        background-color: skyblue;
        color: #fff;
        margin: 10px;
    }
</style>

3.5 align-content设置侧轴上的子元素排列方式(多行)

align-items只适用于单行,就像让文字垂直居中line-height=height也是只适用于单行,所以出现了align-content用于设置多行。
align-content设置子项在侧轴上的排列方式,且只可以用于子项出现换行的情况(多行),在单行下是没有效果的。

  • flex-start:头对齐
  • flex-end:尾对齐
  • center:在侧轴中间显示
  • space-around:子项在侧轴平分剩余空间
  • space-between:子项在侧轴先分布在两头,再平分剩余空间
  • stretch:设置子项元素高度平分父元素高度(设置该属性的时候子项不可以给高度)
<body>
    <div>
        <span>1</span>
        <span>2</span>
        <span>3</span>
        <span>4</span>
        <span>5</span>
        <span>6</span>
    </div>
</body>
<style>
    div {
        /* 给父亲添加flex属性 */
        display: flex;
        /* 添加flex之后,行内元素也有宽高;*/
        width: 800px;
        height: 250px;
        background-color: pink;
        /* 换行 */
        flex-wrap: wrap;
        /* 因为有了换行,此时我们侧轴上控制子元素的对齐方式适用的是align-content */
        /* 1.错误 两行直接空出较大距离 */
        /* align-items: flex-start; */
        /* 2. 正确 行与行之间隔着的仅仅是自己设定的margin */
        /* align-content: flex-start; */
        /* 3. 错误 */
        /* align-items: center; */
        /* 4. 正确 两行的盒子整体都居中了 */
        /* align-content: center; */
        /* 5. space-between */
        /* align-content: space-between; */
        /* 6. space-around */
        /* align-content: space-around; */
        /* 7.子项平分父盒子的高度 设置该属性的时候,子项的高度应该注释掉 */
        align-content: stretch;
    }
    
    div span {
        width: 150px;
        /* height: 50px; */
        background-color: skyblue;
        color: #fff;
        margin: 10px;
    }
</style>
  • 1 align-items: flex-start;错误 两行直接空出较大距离

  • 2 align-content: flex-start;正确 行与行之间隔着的仅仅是自己设定的margin

  • 3 align-items: center;错误

  • 4 align-content: center;正确 两行的盒子整体都居中了

  • 5 space-between

  • 6 space-around

  • 7 align-content: stretch;子项平分父盒子的高度 设置该属性的时候,子项的高度应该注释掉

align-items和align-content区别

  • align-items适用于单行情况下,只有上对齐、下对齐、居中和拉伸
  • align-content适应于换行(多行)的情况(单行情况下无效)可以设置上对其、下对齐、居中、拉伸、平均分配剩余空间等属性。
  • 总结就是单行找align-items多行找align-content
  • 关键看“行数”而不是flex-wrap: wrap;

3.6 flex-flow是flex-direction和flex-wrap属性的复合属性

/* 设置主轴方向 */
/* flex-direction: column; */
/* 是否换行 */
/* flex-wrap: wrap; */
/* 设置主轴方向和是否换行可以简写如下 */
flex-flow: column wrap;

4. flex布局子项常见属性

  • flex子项占的份数
  • align-self控制子项在自己侧轴的排列方式
  • order属性定义子项的排列顺序(前后顺序)

4.1 flex属性

flex属性定义子项分配“剩余”空间,用flex来表示占有多少份数,flex默认值是1

  • 利用flex来实现两侧盒子固定,中间盒子自适应
<body>
    <section>
        <div></div>
        <div></div>
        <div></div>
    </section>
</body>
<style>
    section {
        display: flex;
        width: 60%;
        height: 150px;
        background-color: pink;
        margin: 0 auto;
    }
    
    section div:nth-child(1) {
        width: 100px;
        height: 150px;
        background-color: red;
    }
    
    section div:nth-child(2) {
        flex: 1;
        background-color: green;
    }
    
    section div:nth-child(3) {
        width: 100px;
        height: 150px;
        background-color: blue;
    }
</style>

说明:1和3号盒子有宽度,它们一共占据了200px宽,那么剩余空间就是section的宽减去这200px的宽,即2号盒子将剩余空间全占了。

  • 用flex实现不同盒子的固定比例占据
<body>
    <p>
        <span>1</span>
        <span>2</span>
        <span>3</span>
    </p>
</body>
<style>
    p {
        display: flex;
        width: 60%;
        height: 150px;
        background-color: pink;
        margin: 0 auto;
    }
    
    p span {
        /* border: 1px solid #000; */
        flex: 1;
    }
    
    p span:nth-child(2) {
        flex: 2;
        background-color: skyblue;
    }
</style>


三个盒子所占宽带的比例就是1:2:1

4.2 控制子项自己在侧轴上的排列方式

  • 让3个子盒子沿着侧轴底侧对齐
<body>
    <div>
        <span>1</span>
        <span>2</span>
        <span>3</span>
    </div>
</body>
<style>
    div {
        display: flex;
        width: 80%;
        height: 200px;
        background-color: pink;
        /* 1. 让3个子盒子沿着侧轴底侧对齐 */
        align-items: flex-end;
    }
    
    div span {
        width: 150px;
        height: 60px;
        background-color: skyblue;
        margin-right: 5px;
    }
    /* div span:nth-child(3) {
        align-self: flex-end;
    } */
</style>

  • 只让第三个盒子沿着底侧对齐
<body>
    <div>
        <span>1</span>
        <span>2</span>
        <span>3</span>
    </div>
</body>
<style>
    div {
        display: flex;
        width: 80%;
        height: 200px;
        background-color: pink;
        /* 2. 只让第三个盒子沿着底侧对齐 */
    }
    
    div span {
        width: 150px;
        height: 60px;
        background-color: skyblue;
        margin-right: 5px;
    }
    /* 2. 只让第三个盒子沿着底侧对齐 */
    
    div span:nth-child(3) {
        align-self: flex-end;
    }
</style>

4.3 order属性定义项目的排列顺序

数值越小,排列越靠前,默认值为0
注意:和z-index不一样

<body>
    <div>
        <span>1</span>
        <span>2</span>
        <span>3</span>
    </div>
</body>
<style>
    div {
        display: flex;
        width: 80%;
        height: 200px;
        background-color: pink;
    }
    
    div span {
        width: 150px;
        height: 60px;
        background-color: skyblue;
        margin-right: 5px;
    }
    
    div span:nth-child(2) {
        /* order默认值是0,-1比0小,所以在前面 */
        order: -1;
    }
</style>

推荐阅读