Flex布局经验汇总

2021-07-22 fishedee 前端

0 概述

Flex布局,这个布局学了很久了,每次都是学了又忘,学了又忘,这次要决心把它学起来

Flex布局的关键知识点在于:

  • 父flex的,主轴方向,环绕,整体排列,辅轴方向的元素对齐,整体对齐
  • 子flex的,个体排序,宽度,剩余宽度伸展分配,超出宽度缩减分配,次轴方向的个体对齐

1 父flex

代码在这里

1.1 主轴方向,flex-direction

<style>
    .flex1{
        display: flex;
        flex-direction: row;
    }
    .flex2{
        display: flex;
        flex-direction: column;
    }
</style>
<div class="flexBox">
    <h1>flex-direction:row direction</h1>
    <div class="flex1">
        <div class="rent">a</div>
        <div class="rent">b</div>
        <div class="rent">c</div>
    </div>
    <h1>flex-direction:column direction</h1>
    <div class="flex2">
        <div class="rent">a</div>
        <div class="rent">b</div>
        <div class="rent">c</div>
    </div>
</div>

使用flex-direction来设置主轴方向,是横放,还是竖放。flex-direction还有个row-reverse和column-reverse,就是行列不变,只是元素反过来存放而已。

这个简单,没啥好说的

1.2 主轴环绕,flex-wrap

<style>
.flex3{
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
}
.flex4{
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
}
</style>
<div class="flexBox">
    <h1>flex-wrap:no wrap</h1>
    <div class="flex3">
        <div class="bigRent">a</div>
        <div class="bigRent">b</div>
        <div class="bigRent">c</div>
        <div class="bigRent">d</div>
        <div class="bigRent">e</div>
        <div class="bigRent">f</div>
        <div class="bigRent">g</div>
        <div class="bigRent">h</div>
        <div class="bigRent">i</div>
    </div>
    <h1>flex-wrap:wrap</h1>
    <div class="flex4">
        <div class="bigRent">a</div>
        <div class="bigRent">b</div>
        <div class="bigRent">c</div>
        <div class="bigRent">d</div>
        <div class="bigRent">e</div>
        <div class="bigRent">f</div>
        <div class="bigRent">g</div>
        <div class="bigRent">h</div>
        <div class="bigRent">i</div>
    </div>
</div>

默认的flex-wrap为no-wrap,就是不环绕

这个也简单

1.3 主轴间隙,gap

<style>
.flex21{
    display: flex;
    gap:10px;
    flex-wrap: wrap;
}
.flex22{
    display: flex;
    column-gap:20px;
    flex-wrap: wrap;
}
.flex23{
    display: flex;
    row-gap:30px;
    flex-wrap: wrap;
}
</style>
<div class="flexBox">
    <h1>flex-direction:gap 10</h1>
    <div class="flex21">
        <div class="rent">a</div>
        <div class="rent">b</div>
        <div class="rent">c</div>
        <div class="rent">a</div>
        <div class="rent">b</div>
        <div class="rent">c</div>
        <div class="rent">a</div>
        <div class="rent">b</div>
        <div class="rent">c</div>
    </div>
    <h1>flex-direction:column gap 20</h1>
    <div class="flex22">
        <div class="rent">a</div>
        <div class="rent">b</div>
        <div class="rent">c</div>
        <div class="rent">a</div>
        <div class="rent">b</div>
        <div class="rent">c</div>
        <div class="rent">a</div>
        <div class="rent">b</div>
        <div class="rent">c</div>
    </div>
    <h1>flex-direction:row gap 30</h1>
    <div class="flex23">
        <div class="rent">a</div>
        <div class="rent">b</div>
        <div class="rent">c</div>
        <div class="rent">a</div>
        <div class="rent">b</div>
        <div class="rent">c</div>
        <div class="rent">a</div>
        <div class="rent">b</div>
        <div class="rent">c</div>
    </div>
</div>

间隙描述的是主轴,以及环绕时候的间隙。默认的gap是0,同时表达了row-gap与column-gap。而column-gap是水平方向的间隙,row-gap是垂直方向的间隙

这点也是很直观的

注意,这个gap属性在IE下是不能正常运行的,需要在各个子控件中加入margin属性。如果你是用React的话,不妨改用Antd的Space控件来代替,它可以实现不同浏览器上的兼容性。

1.4 主轴排列,justify-content

<style>
.flex5{
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
}
.flex6{
    display: flex;
    flex-direction: row;
    justify-content: flex-end;
}
.flex7{
    display: flex;
    flex-direction: row;
    justify-content: center;
}
.flex8{
    display: flex;
    flex-direction: row;
    justify-content: space-between;
}
.flex9{
    display: flex;
    flex-direction: row;
    justify-content: space-around;
}
</style>
<div class="flexBox">
    <h1>justify-content:flex-start</h1>
    <div class="flex5">
        <div class="rent">a</div>
        <div class="rent">b</div>
        <div class="rent">c</div>
    </div>
    <h1>justify-content:flex-end</h1>
    <div class="flex6">
        <div class="rent">a</div>
        <div class="rent">b</div>
        <div class="rent">c</div>
    </div>
    <h1>justify-content:center</h1>
    <div class="flex7">
        <div class="rent">a</div>
        <div class="rent">b</div>
        <div class="rent">c</div>
    </div>
    <h1>justify-content:space-between</h1>
    <div class="flex8">
        <div class="rent">a</div>
        <div class="rent">b</div>
        <div class="rent">c</div>
    </div>
    <h1>justify-content:space-around</h1>
    <div class="flex9">
        <div class="rent">a</div>
        <div class="rent">b</div>
        <div class="rent">c</div>
    </div>
</div>

这里就开始有点混乱了,justify-content描述的是,在主轴方向,内容整体如何排列,包括:

  • 整体靠左(flex-start),默认值
  • 靠右(flex-end)
  • 中间(center)
  • 中间有空隙均匀排列(space-between)
  • 两侧有空隙均匀排列(space-around)

justify-content描述的是,主轴方向(justify),内容整体(content)如何排列

1.5 辅轴元素对齐,align-items

<style>
.flex10{
    display: flex;
    flex-direction: row;
    align-items: flex-start;
}
.flex11{
    display: flex;
    flex-direction: row;
    align-items: flex-end;
}
.flex12{
    display: flex;
    flex-direction: row;
    align-items: center;
}
.flex13{
    display: flex;
    flex-direction: row;
    align-items: baseline;
}
.flex14{
    display: flex;
    flex-direction: row;
    align-items: stretch;
}
.flexAlignItems .rent,
.flexAlignItems .rent2,
.flexAlignItems .rent3,
.flexAlignItems .rent4{
    height:auto;
}
</style>
<div class="flexBox flexAlignItems">
    <h1>align-items:flex-start</h1>
    <div class="flex10">
        <div class="rent">a</div>
        <div class="rent2">b</div>
        <div class="rent3">c</div>
        <div class="rent4">d</div>
    </div>
    <h1>align-items:flex-end</h1>
    <div class="flex11">
        <div class="rent">a</div>
        <div class="rent2">b</div>
        <div class="rent3">c</div>
        <div class="rent4">d</div>
    </div>
    <h1>align-items:center</h1>
    <div class="flex12">
        <div class="rent">a</div>
        <div class="rent2">b</div>
        <div class="rent3">c</div>
        <div class="rent4">d</div>
    </div>
    <h1>align-items:baseline</h1>
    <div class="flex13">
        <div class="rent">a</div>
        <div class="rent2">b</div>
        <div class="rent3">c</div>
        <div class="rent4">d</div>
    </div>
    <h1>align-items:stretch</h1>
    <div class="flex14">
        <div class="rent">a</div>
        <div class="rent2">b</div>
        <div class="rent3">c</div>
        <div class="rent4">d</div>
    </div>
</div>

当元素在主轴排列以后,它在副轴就就可以选择,元素之间在副轴的对齐,包括:

  • flex-start,元素的头部在副轴方向对齐
  • flex-end,元素的尾部在副轴方向对齐
  • center,元素的中间在副轴方向对齐
  • baseline,元素的基线在副轴方向对齐
  • stretch,元素在副轴方向拉伸对齐,仅当元素在副轴的没有设置大小时,默认值

align-items,描述的是在副轴方向(align),各个元素(items)之间拿什么进行对齐

1.6 辅轴整体对齐,align-content

<style>
.flex15{
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-content: flex-start;
    height:500px;
}
.flex16{
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-content: flex-end;
    height:500px;
}
.flex17{
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-content: center;
    height:500px;
}
.flex18{
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-content: stretch;
    height:500px;
}
.flex19{
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-content: space-between;
    height:500px;
}
.flex20{
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-content: space-around;
    height:500px;
}
</style>
<div class="flexBox">
    <h1>align-content:flex-start</h1>
    <div class="flex15">
        <div class="bigRent">a</div>
        <div class="bigRent">b</div>
        <div class="bigRent">c</div>
        <div class="bigRent">d</div>
        <div class="bigRent">e</div>
        <div class="bigRent">f</div>
        <div class="bigRent">g</div>
        <div class="bigRent">h</div>
        <div class="bigRent">i</div>
    </div>
    <h1>align-content:flex-end</h1>
    <div class="flex16">
        <div class="bigRent">a</div>
        <div class="bigRent">b</div>
        <div class="bigRent">c</div>
        <div class="bigRent">d</div>
        <div class="bigRent">e</div>
        <div class="bigRent">f</div>
        <div class="bigRent">g</div>
        <div class="bigRent">h</div>
        <div class="bigRent">i</div>
    </div>
    <h1>align-content:center</h1>
    <div class="flex17">
        <div class="bigRent">a</div>
        <div class="bigRent">b</div>
        <div class="bigRent">c</div>
        <div class="bigRent">d</div>
        <div class="bigRent">e</div>
        <div class="bigRent">f</div>
        <div class="bigRent">g</div>
        <div class="bigRent">h</div>
        <div class="bigRent">i</div>
    </div>
    <h1>align-content:stretch</h1>
    <div class="flex18">
        <div class="bigRent">a</div>
        <div class="bigRent">b</div>
        <div class="bigRent">c</div>
        <div class="bigRent">d</div>
        <div class="bigRent">e</div>
        <div class="bigRent">f</div>
        <div class="bigRent">g</div>
        <div class="bigRent">h</div>
        <div class="bigRent">i</div>
    </div>
    <h1>align-content:space-between</h1>
    <div class="flex19">
        <div class="bigRent">a</div>
        <div class="bigRent">b</div>
        <div class="bigRent">c</div>
        <div class="bigRent">d</div>
        <div class="bigRent">e</div>
        <div class="bigRent">f</div>
        <div class="bigRent">g</div>
        <div class="bigRent">h</div>
        <div class="bigRent">i</div>
    </div>
    <h1>align-content:space-around</h1>
    <div class="flex20">
        <div class="bigRent">a</div>
        <div class="bigRent">b</div>
        <div class="bigRent">c</div>
        <div class="bigRent">d</div>
        <div class="bigRent">e</div>
        <div class="bigRent">f</div>
        <div class="bigRent">g</div>
        <div class="bigRent">h</div>
        <div class="bigRent">i</div>
    </div>
</div>

副轴整体对齐,是指在副轴方向上,内容整体如何对齐,包括:

  • flex-start,内容整体在副轴方向的头部对齐
  • flex-end,内容整体在副轴方向的尾部对齐
  • center,内容整体在副轴方向的中央对齐
  • stretch,内容整体在副轴方向顺序wrap对齐
  • space-between,内容整体在副轴方向的中间有空隙均匀排列
  • space-around,内容整体在副轴方向的两侧有空隙均匀排列

align-content,描述的是在副轴方向(align)上,内容整体(content)如何对齐

1.7 父flex盒子,dispaly

<style>
.flex1{
    display:inline-flex;
}
.flex2{
    display:flex;
}
</style>

可以设置为inline或者block方式的flex,这点与block与inline-block的区别是一样的,就没啥好说的了

1.8 语法糖,flex-flow

<style>
.flex{
    flex-flow:row nowrap;
}
</style>

flex-flow就是flex-direction,与flex-wrap的组合而已,这点也没啥好说的

2 子flex

代码在这里

2.1 顺序,order

<style>
.flexBox{
    margin-top:30px;
    border-bottom:1px solid black;
}
.flex{
    display: flex;
    flex-direction: row;
    width:100%;
}
</style>
<div class="flexBox">
    <h1>order</h1>
    <div class="flex">
        <div class="rent" style="order:2">a</div>
        <div class="rent" style="order:1">b</div>
        <div class="rent" style="order:3">c</div>
    </div>
</div>

order也很好理解,就是强行指定渲染的顺序,而不是以DOM的出现来分主次

这个还是比较直观的

2.2 主轴大小,flex-basis

<div class="flexBox">
    <h1>flex-basis</h1>
    <div class="flex">
        <div class="rent" style="flex-basis:100px">a</div>
        <div class="rent" style="flex-basis:200px">b</div>
        <div class="rent" style="flex-basis:400px">c</div>
    </div>
</div>

flex-basis,可以用百分比,也可以用像素,它描述的是主轴方向的大小。在row方向的时候,我们也可以用width来描述节点的大小呀,为什么要用flex-basis。因为flex-basis的优先级更高。默认值为auto。总的来说,优先级等级为:

  • flex-basis,最高
  • width或者height,显式在css指定它的宽或者高
  • content width或者content height,内容自身的宽或者高

这点也没啥好说的,具体可以看这里

2.3 主轴剩余空间分配,flex-grow

<div class="flexBox">
    <h1>flex-grow</h1>
    <div class="flex">
        <div class="rent" style="flex-grow:0">a</div>
        <div class="rent" style="flex-grow:1">b</div>
        <div class="rent" style="flex-grow:2">c</div>
    </div>
</div>

当flex是row方向nowrap的时候,多个元素的大小总和依然少于父flex的宽度的时候,就会产生主轴的剩余空间分配。它的分配方法也简单,就是按照flex-grow的权重进行分配,默认的flex-grow为0,就是该元素不分配剩余空间。经过剩余空间分配以后,flex总是能保证元素的总宽度刚好为父flex的宽度

我们看到c的flex-grow为2,b的flex-grow为1,所以,c总是能比b多1倍的剩余宽度。

剩余宽度的计算公式看这里,要注意尽可能不要让权重总和少于1,会产生你意外的布局效果,会造成剩余宽度不分配的情况。

2.4 主轴缩减空间分配,flex-shrink

<style>
.rentLong{
    margin:15px;
    border:1px solid black;
    color:red;
    background: blue;
    width:500px;
    height:30px;
    text-align:center;
    line-height: 30px;
    vertical-align: middle;
}
</style>
<div class="flexBox">
    <h1>flex-shrink</h1>
    <div class="flex">
        <div class="rentLong" style="flex-shrink:1">a</div>
        <div class="rentLong" style="flex-shrink:2">b</div>
        <div class="rentLong" style="flex-shrink:4">c</div>
    </div>
</div>

每个子div的长度都是500像素,显然会超出父flex的总宽度。那么,各个子flex就需要承担等比例收缩宽度的任务,他们各自需要收缩多少,显然这也是flex-shrink的事情,他通过权重来做等比例的收缩。经过缩减空间分配以后,flex总是能保证元素的总宽度刚好为父flex的宽度

如图所示,虽然a,b,c都是500像素的宽度,但是c的flex-shrink权重最大,所以它被缩减的空间最大。

缩减宽度的计算公式看这里,要注意尽可能不要让权重总和少于1,会产生你意外的布局效果,会造成剩余宽度不分配的情况。另外,权重的计算不仅会考虑flex-shrink,也会考虑width自身,这是因为我们尽量避免原来大width的组件收缩的程度太大。如果对所有组件的flex-shrink设置为1,那么flex布局就会根据原来组件自身的width尽可能等比例的收缩。

2.5 副轴元素对齐,align-self

<div class="flexBox">
    <h1>align-self</h1>
    <div class="flex2">
        <div class="rent">a</div>
        <div class="rent">b</div>
        <div class="rent" style="align-self: flex-end;">c</div>
    </div>
</div>

align-self其实就是父flex的align-items的各自特别版本而已,这个也没啥好说的

align-self的可能取值与align-items的是一致的

2.6 语法糖,flex

<style>
    .flex{
        flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
    }
</style>

flex其实是flex-grow,flex-shrink与flex-basis的组合语法糖而已,默认可以省略flex-shrink与flex-basis,只写flex-grow也是没问题的。

3 应用

代码在这里

3.1 管理系统布局

<style>
*{
    margin:0px;
    padding:0px;
}
.flex{
    display: flex;
    flex-direction: column;
    align-items: stretch;
    width:100%;
    height: 100vh;
}
.flex .header{
    height:70px;
    background: blue;
}
.flex .flex2{
    flex:1;
    display: flex;
}
.flex .sidebar{
    width:70px;
    background: red;
}
.flex .content{
    flex:1;
    background: pink;
}
.flex .footer{
    height: 70px;
    background: yellow;
}
</style>
<div>
    <h1>flex admin</h1>
    <div class="flex">
        <div class="header">
            header
        </div>
        <div class="flex2">
            <div class="sidebar">
                sidebar
            </div>
            <div class="content">
                content
            </div>
        </div>
        <div class="footer">
            footer
        </div>
    </div>
</div>

注意一下用100vh来描述屏幕高度

3.2 等比例布局

<style>
*{
    margin:0px;
    padding:0px;
}
.flex{
    display: flex;
}
.flex div{
    flex-basis:25%;
    text-align: center;
    border:1px solid black;
}
</style>
<div>
    <h1>flex 25%precent</h1>
    <div class="flex">
        <div>a</div>
        <div>b</div>
        <div>c</div>
        <div>d</div>
    </div>
</div>

直接用flex-basis的百分比就可以了,注意,border的大小不影响flex-basis的布局,也不修改box-sizing属性,也不需要考虑空格问题,确实好用。

3.3 垂直与宽度居中

<style>
*{
    margin:0px;
    padding:0px;
}
.center1{
    display: flex;
    justify-content: center;
    align-items: center;
    height:300px;
    border:1px solid black;
}
</style>
<div>
    <h1> flex center</h1>
    <div class="center1">
        <p>123456</p>
    </div>
</div>

直接用justify-content和align-items就可以了,如果有多个item,就用justify-content和align-content。比原来的方法也好用多了。

3.4 类float布局

<style>
*{
    margin: 0px;
    padding: 0px;
}
.flex{
    border:1px solid blue;
    padding: 30px;
}
.flex .item{
    display: flex;
    width: 300px;
    border:1px solid black;
    align-items: flex-start;
}
.flex .item img{
    flex:0;
    width: 30px;
}
.flex .item p{
    flex:1;
}
</style>
<div>
    <h1>flex hang</h1>
    <div class="flex">
        <div class="item">
            <img src="./icon.jpg"/>
            <p>你好你好你好你好你好你好你好你好你好你好你好你好你好你好</p>
        </div>
        <div class="item">
            <img src="./icon.jpg"/>
            <p>你好你好你好你好你好你好你好你好你好你好你好你好你好你好</p>
        </div>
    </div>
</div>

一侧有图片,另外一侧占用剩余宽度,两者顶部对齐,也是简单的

3.5 左右浮动布局

<style>
*{
    margin:0px;
    padding:0px;
}
.right1{
    display: flex;
    flex-direction: row;
}
.right1 .l{
    flex:0;
}
.right1 .c{
    flex:1;
    text-align: center;
}
.right1 .r{
    flex: 0;
}
</style>
<div>
    <h1>flex right</h1>
    <div class="right1">
        <div class="l">left</div>
        <div class="c">center</div>
        <div class="r">right</div>
    </div>
</div>

左右浮动,可以看成是justify-content的space-between,也可以看成是主轴三部分,中间部分占据所有的剩余宽度。

3.6 maxWidth与no-wrap不兼容

<!doctype html>
<html>
    <head>
        <meta charset="utf-8"/>
        <title>flex测试</title>
        <style>
            *{
                margin:0px;
                padding:0px;
            }
            .container{
                display: flex;
                flex-direction: row;
                border:1px solid green;
                width: 500px;
            }
            .nowrap{
                flex-wrap: nowrap;/*默认值*/
            }
            .wrap{
                flex-wrap: wrap;
            }
            .body{
                flex:1;
            }
            .right{
                display:flex;
                flex-direction: row;
                max-width:100px;/*max-width与wrap合并以后,宽度计算会不准确,计算的宽度依然是100px,而不是wrap以后的60px*/
            }
            .content{
                border:1px solid black;
                width:60px;
                height:60px;
            }
        </style>
    </head>
    <body>
        <div>
            <h1>flex nowrap</h1>
            <div class="container">
                <div class="body">
                    <h1>123</h1>
                    <h1>23</h1>
                </div>
                <div class="right nowrap">
                    <div class="content">123</div>
                    <div class="content">23</div>
                </div>
            </div>
        </div>
        <div>
            <h1>float wrap</h1>
            <div class="container">
                <div class="body">
                    <h1>123</h1>
                    <h1>23</h1>
                </div>
                <div class="right wrap">
                    <div class="content">123</div>
                    <div class="content">23</div>
                </div>
            </div>
        </div>
    </body>
</html>

代码如上,right都设置了max-width为100px,区别在于,一个为默认的nowrap,另外一个为wrap

惊讶的是,wrap了以后的占用宽度依然为100px,而不是最小换行间距的60px,这一点需要注意。

3.7 flex-grow与overflow不兼容

3.7.1 普通的管理系统布局

<!doctype html>
<html>
    <head>
        <meta charset="utf-8"/>
        <title>flex测试</title>
        <style>
            *{
                margin:0px;
                padding:0px;
            }
            .flex{
                display: flex;
                flex-direction: column;
                align-items: stretch;
                width:100%;
                height: 100vh;
            }
            .flex .header{
                height:70px;
                background: blue;
            }
            .flex .flex2{
                flex:1;
                display: flex;
            }
            .flex .sidebar{
                width:70px;
                background: red;
            }
            .flex .content{
                flex:1;
                background: pink;
            }
            .flex .footer{
                height: 70px;
                background: yellow;
            }
            .flex .content{
                overflow:auto;
            }
            .flex .realContent{
                width:1800px;
                height:1800px;
            }
        </style>
    </head>
    <body>
        <div>
            <div>
                <div class="flex">
                    <div class="header">
                        header
                    </div>
                    <div class="flex2">
                        <div class="sidebar">
                            sidebar
                        </div>
                        <div class="content">
                            <div class="realContent">
                                content
                            </div>
                        </div>
                    </div>
                    <div class="footer">
                        footer
                    </div>
                </div>
            </div>
        </div>
    </body>
</html>

与3.1的代码基本上是一样的,区别在于content里面的内容很宽很高,然后我们希望只在content里面加滚动条,于是有了overflow:auto;

结果是body出现了竖直的滚动条,而且其他的header,footer,flex2被压缩了

3.7.2 嵌套一个absolute

<!doctype html>
<html>
    <head>
        <meta charset="utf-8"/>
        <title>flex测试</title>
        <style>
            *{
                margin:0px;
                padding:0px;
            }
            .flex{
                display: flex;
                flex-direction: column;
                align-items: stretch;
                width:100%;
                height: 100vh;
            }
            .flex .header{
                height:70px;
                background: blue;
            }
            .flex .flex2{
                flex:1;
                display: flex;
            }
            .flex .sidebar{
                width:70px;
                background: red;
            }
            .flex .content{
                flex:1;
                background: pink;
            }
            .flex .footer{
                height: 70px;
                background: yellow;
            }
            .flex .realContent{
                width:1800px;
                height:1800px;
            }
            .flex .content{
                position: relative;
            }
            .flex .wrapper{
                position: absolute;
                top:0px;
                left:0px;
                right:0px;
                bottom:0px;
                width: 100%;
                height: 100%;

                overflow:auto;
            }
        </style>
    </head>
    <body>
        <div>
            <div>
                <div class="flex">
                    <div class="header">
                        header
                    </div>
                    <div class="flex2">
                        <div class="sidebar">
                            sidebar
                        </div>
                        <div class="content">
                            <div class="wrapper">
                                <div class="realContent">
                                    content
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="footer">
                        footer
                    </div>
                </div>
            </div>
        </div>
    </body>
</html>

一个较好的方法是,在realContent的外面套一层wrapper。wrapper取父级的宽高,在其自身加入overflow:auto即可。要注意的是,content需要加入position:relative.

一个较好的解决方案

3.7.3 明确指定高度与宽度

<!doctype html>
<html>
    <head>
        <meta charset="utf-8"/>
        <title>flex测试</title>
        <style>
            *{
                margin:0px;
                padding:0px;
            }
            .flex{
                display: flex;
                flex-direction: column;
                align-items: stretch;
                width:100%;
                height: 100vh;
            }
            .flex .header{
                height:70px;
                background: blue;
            }
            .flex .flex2{
                flex:1;
                display: flex;
            }
            .flex .sidebar{
                width:70px;
                background: red;
            }
            .flex .content{
                flex:1;
                background: pink;
            }
            .flex .footer{
                height: 70px;
                background: yellow;
            }
            .flex .content{
                overflow:auto;
                height:calc(100vh - 140px);
                width:calc(100% - 40px);
            }
            .flex .realContent{
                width:1800px;
                height:1800px;
            }
        </style>
    </head>
    <body>
        <div>
            <div>
                <div class="flex">
                    <div class="header">
                        header
                    </div>
                    <div class="flex2">
                        <div class="sidebar">
                            sidebar
                        </div>
                        <div class="content">
                            <div class="realContent">
                                content
                            </div>
                        </div>
                    </div>
                    <div class="footer">
                        footer
                    </div>
                </div>
            </div>
        </div>
    </body>
</html>

另外一个方法是,为content指定明确的width与height,需要引入calc来指定,受限制较多。优点是少了一层wrapper.

也能达到一个较好的效果

3.7.4 flex-shrink + overflow

<!doctype html>
<html>
    <head>
        <meta charset="utf-8"/>
        <title>flex测试</title>
        <style>
            * {
                margin: 0px;
                padding: 0px;
            }
            .flex {
                display: flex;
                flex-direction: column;
                align-items: stretch;
                width: 100%;
                height: 100vh;
            }
            .flex .header {
                flex-grow: 0;
                flex-shrink: 0;
                height: 70px;
                background: blue;
            }
            .flex .flex2 {
                flex-grow: 1;
                flex-shrink: 1;
                display: flex;
                overflow: auto;
            }
            .flex .sidebar {
                flex-grow: 0;
                flex-shrink: 0;
                width: 70px;
                background: red;
            }
            .flex .content {
                flex-grow: 1;
                flex-shrink: 1;
                background: pink;
                overflow: auto;
            }
            .flex .footer {
                flex-grow: 0;
                flex-shrink: 0;
                height: 70px;
                background: yellow;
            }
            .flex .realContent {
                width: 1800px;
                height: 1800px;
            }
        </style>
    </head>
    <body>
        <div class="flex">
            <div class="header">
                header
            </div>
            <div class="flex2">
                <div class="sidebar">
                    sidebar
                </div>
                <div class="content">
                    <div class="realContent">
                        content
                    </div>
                </div>
            </div>
            <div class="footer">
                footer
            </div>
        </div>
    </body>
</html>

最好的方法是:

  • header,footer和sidebar,不仅需要指定flex-grow为0,还需要指定flex-shrink为0,可以简写为flex:0 0。
  • content和flex2,不仅需要指定flex-grow为0,还需要指定flex-shrink为0,可以简写为flex:1 1。重要的是,还需要指定overflow:auto,这样才能保证不会被子组件扩大本组件的大小。

4 absolute布局的使用

4.1 围绕div的辅助元素

<!doctype html>
<html>
    <head>
        <meta charset="utf-8"/>
        <title>absolute的Square</title>
        <style>
            *{
                margin:0px;
                padding:0px;
            }
            body{
                padding:20px;
            }
            .wrapper{
                position:absolute;
                outline: 1px solid blue;
            }
            .topSquare{
                position: absolute;
                top:0px;
                left:50%;
                margin-left:-4px;
                margin-top:-4px;
                width:8px;
                height:8px;
                border:1px solid blue;
                background: white;
                cursor: n-resize;
            }
            .topMove{
                position: absolute;
                top:-5px;
                left:0px;
                width:100%;
                height:10px;
                cursor: move;
            }
            .leftSquare{
                position: absolute;
                top:50%;
                left:0;
                margin-left:-4px;
                margin-top:-4px;
                width:8px;
                height:8px;
                border:1px solid blue;
                background: white;
                cursor: w-resize;
            }
            .leftMove{
                position: absolute;
                top:0px;
                left:-5px;
                width:10px;
                height:100%;
                cursor: move;
            }
            .content{
                width:100px;
                height:100px;
            }
        </style>
    </head>
    <body>
        <div class="wrapper">
            <div class="topMove"></div>
            <div class="leftMove"></div>
            <div class="topSquare"></div>
            <div class="leftSquare"></div>
            <div class="content">uuu</div>
        </div>
    </body>
</html>

为content提供了辅助元素,并且为该辅助元素提供了cursor范围

4.2 增大点击范围

<!doctype html>
<html>
    <head>
        <meta charset="utf-8"/>
        <title>absolute的Square</title>
        <style>
            *{
                margin:0px;
                padding:0px;
            }
            body{
                padding:20px;
            }
            .wrapper{
                position:absolute;
            }
            .content::before{
                content:' ';
                position: absolute;
                width:10px;
                left:-5px;
                top:0px;
                height:100%;
            }
            .content{
                width:1px;
                height:500px;
                border:1px dashed blue;
                cursor:ew-resize;
                box-sizing: border-box;
            }
        </style>
    </head>
    <body>
        <div class="wrapper">
            <div class="content"></div>
        </div>
    </body>
</html>

为一条垂直线提供了更大的点击范围

5 总结

有用且兼容性较好的布局方式,需要转换一下思维,难度并不大。参考资料

相关文章