CSS弹性布局总结

传统的响应式布局方式,通过position:absoulte和float

<main>
    <nav>1</nav>
    <article>2</article>
</main>

<style>
* {
    padding: 0;
    margin: 0;
}

// 父元素相对定位
main {
    position: relative;
    height: 100vh;
}

// 子元素绝对定位
nav {
    width: 80px;
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    background: linear-gradient(45deg,red,greenyellow);
}

// 另一个资源通过剩余宽度自适应
article {
    background: linear-gradient(90deg,gray,greenyellow);
    margin-left: 90px;
    height: 100vh;
}
</style>
flex_01.gif

弹性布局:

* {
    padding: 0;
    margin: 0;
}

main {
    display: flex;
    height: 100vh;
}

nav {
    width: 80px;
    background: linear-gradient(45deg,red,greenyellow);
}

article {
    background: linear-gradient(90deg,gray,greenyellow);
    flex: 1;
}

可以看出仅少量的代码就可以实现响应式布局,相比于传统的响应式布局方式方便许多。同时当页面增加元素的时候,会自适应布局,而不需要再改变代码。

1. 弹性盒子声明

如果某元素声明为弹性盒子display:flex,那么该元素内部的子元素的布局方式则由父元素弹性盒子的规则来定义。

弹性盒子有两种:块级弹性盒子、行内块级弹性盒子

  • 块级弹性盒子

    display: flex;
    

    声明为此方式的盒子表现为块级元素的特性。

  • 行内块级弹性盒子

    diplay: inline-flex;
    

    声明此方式的盒子表现为行内块级元素的特性。

2. 弹性盒子规则

弹性盒子中的内容称为元素。在弹性盒子上定义规则,会影响弹性盒子中元素的布局方式。以下的规则都是在弹性盒子上进行制定。(原因:影响所有的元素,而不是单个元素)

2.1 弹性元素布局方式

通过flex-direction设置弹性盒子中元素的布局方式。也即安排元素是从上往下,还是从左到右开始放置。

说明
row 从左到右水平排列元素(默认值)
row-reverse 从右向左排列元素
column 从上到下垂直排列元素
column-reverse 从下到上垂直排列元素

例子:

flex-direction: row-reverse;
flex_02.png
2.2 弹性元素溢出处理

当一行/一列的元素过多,不能显示完全。

此时弹性盒子有两种方式安排元素的布局:

  • 改变元素宽/高尺寸自适应盒子的变化(默认的情况)
  • 通过属性设置元素换行处理(flex-wrap

如果没有设置flex-wrap,则元素溢出的处理则是采用默认方式,也即改变元素本身的尺寸。

flex_03.gif

如果设置了flex-wrap,则按照属性值换行处理

选项 说明
nowrap 元素不拆行或不拆列(默认值)
wrap 容器元素在必要的时候拆行或拆列。
wrap-reverse 容器元素在必要的时候拆行或拆列,但是以相反的顺序

如果盒子的布局方式为row,那么换行时,元素所转换到的那行则在当前行的下面。

也即:flex-wrap会根据横轴(flex-direction设置的布局方式)决定新行的堆叠方向。

display: flex;
flex-direction: row-reverse;
flex-wrap: wrap;

此时结果为:

\flex_04.png

flex-wrap:wrap-reverse时,反方向换行。默认情况下新行都是在原来所处行下方,则此属性则规定新行在原来所处行的上方。注意:则属性只是规定在原来行上方/下方新建一行来放置溢出的元素,而元素在新行上的布局仍然是由flex-direction来控制

display: flex;
flex-direction: row-reverse;
flex-wrap: wrap-reverse;

结果为:

\flex_05.png
2.3 flex-direction和flex-wrap的组合写法

flex-flowflex-directionflex-wrap的组合写法,不考虑顺序。

flex-flow: wrap-reverse row-reverse;
2.4 主轴和交叉轴
  • 主轴:元素布局的方向也就是主轴的方向
flex-direction: row;
flex_06.png
flex-direction: row-reverse;
flex_07.png
  • 交叉轴:属性flex-wrap指定元素溢出时新建行是从上到下/从下到上,还是从左到右/从右到左

    flex-wrap: wrap;
    
flex_08.png
flex-wrap: wrap-reverse;
flex_09.png"
  • 练习

    flex-flow: column-reverse wrap-reverse;
    
    flex_10.png
2.5 主轴对齐方式

flex-direction规定了元素的排列方向,也即从上往下开始放置元素/从左往右开始放置元素。但是这个属性没有规定元素放置的位置,也即排列方式。

justify-content,则用于规定元素的主轴上的排列方式,也即平均放置在主轴上,还是从左开始放置,还是从右开始放置。

因此,可以通过flex-direction规定元素排列方向,justify-content规定元素排列方式。

属性值 说明
flex-start 元素对齐主轴起点
flex-end 元素对齐主轴终点
center 元素对齐弹性容器中心
space-between 第一个元素紧靠起点,最后一个元素紧靠终点,余下元素平均分配空间
space-around 每个元素两侧的间隔相等。所以,元素之间的间隔比元素与容器的边距的间隔大一倍
space-evenly 元素间距离平均分配
flex-direction: row;
justify-content: flex-end;
flex_11.png
flex-direction: row;
justify-content: center;    
flex_12.png
flex-direction: row;
justify-content: space-between;
flex_13.png
flex-direction: row-reverse;
justify-content: space-around;
flex_15.png
flex-direction: row-reverse;
justify-content: space-evenly;
\flex_16.png
2.6 交叉轴对齐方式

当弹性盒子放不下元素时,且允许换行,此时换行可能会导致交叉轴上有多行元素存在。

flex_17.png

此时可以对交叉轴上的单行元素在交叉轴方向规定显示位置,或者对交叉轴上的行与行之间(多行元素)规定显示位置。

  • 规定交叉轴上单行元素的显示位置

    align-items

    属性值 说明
    stretch 元素被拉伸以适应容器(默认值)(当不设置元素在交叉轴方向上的长度时)
    center 元素位于容器的中心
    flex-start 元素位于容器的交叉轴开头
    flex-end 元素位于容器的交叉轴结尾

    假设弹性盒子默认规则为:

    display: flex;
    flex-direction: row;
    

基于以上规则进一步讨论align-items属性

假设元素不设置高度,那么弹性盒子默认规定元素align-items属性值为stretch,表现为元素被拉伸以适应容器。

  align-items: stretch;
flex_18.png

如果设置了高度,那么该属性就不起作用了。

align-items: flex-start;

表明单行元素紧靠交叉轴起点

flex_19.png
align-items: center

表明单行元素位于交叉轴中心

flex_20.png
  • 规定交叉轴上多行元素之间的显示方式

    align-content,用法与justify-content一样。

    属性值 说明
    stretch 拉伸元素,使其平均分配空间(默认值),但是需要在不设置元素在交叉轴上的长度才有效。
    flex-start 所有行紧靠交叉轴起点
    flex-end 所以行紧靠交叉轴终点
    center 所有行对齐于交叉轴中心
    space-between 第一行紧靠起点,最后一行紧靠终点,余下行元素平均分配空间
    space-around 每一行两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍
    space-evenly 行间距离平均分配
    • 假设弹性盒子默认规则为:

      display: flex;
      flex-direction: row;
      flex-wrap: wrap;
      

    基于以上规则进一步讨论align-content属性

    align-content: flex-start;
    

    所以行紧靠交叉轴起点

    flex_21.png
align-content: space-evenly

行之间平分空间

flex_22.png

注意:设置了align-content会覆盖align-items的设置

3. 弹性元素规则

弹性元素规则定义单个元素在弹性盒子中的显示方式。

3.1 弹性元素在交叉轴上的排列方式

align-self元素可以控制单个元素在交叉轴上的排列方式。不同于align-items是控制一行元素整体在交叉轴上的排列方式。

属性值 说明
stretch 将空间平均分配给元素
flex-start 元素紧靠主轴起点
flex-end 元素紧靠主轴终点
center 元素从弹性容器中心开始

用法与align-items一样。

div:nth-of-type(1) {
    align-self: flex-end;
}
flex_23.png
3.2 主轴上可用空间分配

弹性元素在主轴上可以对可用空间进行分配。

flex-grow

属性值为数值,表示可用空间分为几等份,以及当前元素所占的比例。可以为整数/小数

计算公式

当前元素所分配的剩余可用空间 = (剩余空间 / 划分等份)* 当前元素所占份数

实际元素所占空间 = 原来的空间 + 当前元素所分配的剩余可用空间

如果没有设置缩放比例,那么默认为0;

<main>
    <div>1</div>
    <div>2</div>
    <div>3</div>
</main>

<style>
main {
    display: flex;
    width: 600px;
    height: 200px;
    margin: 10px auto;
    border: 1px solid red;
    flex-flow: row wrap;
}

div {
    width: 100px;
    height: 60px;
    padding: 10px;
    // 使得元素的高和宽限于边框内
    box-sizing: border-box;
    background-clip: content-box;
    background-image: linear-gradient(to top,pink,palegoldenrod);
    flex-grow: 1;
}

   // 设置元素所占可用空间的比例
div:nth-of-type(1) {
    flex-grow: 1;
}

div:nth-of-type(2) {
    flex-grow: 2;
}

div:nth-of-type(3) {
    flex-grow: 0;
}
</style>
flex_24.png

注意:该属性是弹性元素在主轴上可用空间的划分。

使用场景:弹性布局,头部 主体 尾部 通过此属性实现弹性布局。

3.3 主轴上不足空间时元素缩放

当在主轴方向上元素所占空间大于弹性盒子在主轴上的空间的时候,如果没有设置flex-wrap换行处理。那么默认会进行缩放。且每个元素缩放比例默认是一样的。

flex-shrink可以设置每个元素的缩放比例。

<main>
    <div>1</div>
    <div>2</div>
    <div>3</div>
</main>

<style>
main {
    display: flex;
    width: 500px;
    height: 200px;
    margin: 10px auto;
    border: 1px solid red;
    flex-flow: row;
}

div {
    width: 200px;
    height: 60px;
    padding: 10px;
    // 使原来宽高固定在边框内
    box-sizing: border-box;
    background-clip: content-box;
    background-image: linear-gradient(to top,pink,palegoldenrod);
    flex-grow: 1;
}

    // 设置缩放比例
div:nth-of-type(1) {
    flex-shrink: 0;
}

div:nth-of-type(2) {
    flex-shrink: 1;
}

div:nth-of-type(3) {
    flex-shrink: 3;
}
</style>
flex_25.png
3.4 主轴的基准尺寸定义

flex-basis属性定义了在分配多余空间之前,元素占据的主轴空间。浏览器会根据这个属性计算主轴上是否有多余的空间。类似于width height以及max/min-height max/min-width

但是存在一定的优先级的问题。

max/min-width/height > flex-basis > width/height

也即如果设置了flex-basis,则width/height是无效的

单位: px/百分比

3.5 flex-组合写法

flexflex-grow flex-shrink flex-basis组合写法

顺序为: flex-grow flex-shrink

如果只写一个数值,则表示缩放,缩小都为此比例。

3.6 控制弹性元素位置

在主轴上面可以通过flex-direction规定弹性元素整体排列方向,通过justify-content规定元素排列方式,通过flex-grow规定元素对可用空间的分配,通过flex-shrink规定元素在空间不足的时候的缩放比例,通过flex-basis设定元素的基准尺寸。但是以上这些属性都是在元素原来放置顺序上进行的一系列的操作,并不能单独控制元素之间互相交换位置。

order用于控制弹性元素的位置,默认为0,数值越小越在前面(前与后是相对于主轴的方向的),可以是负数或者整数。

默认值:order: 0 表示所有元素都按照原来的顺序进行放置,没有优先级之分。

div:nth-of-type(1) {
    order: 1;
}

设置第一个元素的order: 1,由于数值越大越在后面,所以第一个元素放置在主轴的结束处。

flex_26.png

4. 弹性文本

弹性盒子中的元素不仅可以包含标签节点,也可以操作文本节点

<main>
    1 // 文本节点
    <div>div盒子</div>
    3 // 文本节点
</main>

<style>
main {
    display: flex;
    width: 300px;
    height: 200px;
    margin: 10px auto;
    border: 1px solid red;
    flex-flow: row;
    justify-content: space-between;
}

div {
    width: 60px;
    height: 60px;
    background: linear-gradient(45deg,pink,deeppink);
}
</style>
flex_27.png

5. 定位属性应用于弹性元素

在弹性元素上应用定位属性,那么弹性布局的规则不再适用于添加了定位的元素。

因此:添加定位属性的弹性元素不参与弹性布局。

6. 自动空间

在弹性布局中对元素使用margin-right等属性可以自动撑满空间(当前元素把剩余空间撑开,使得其元素右边相邻的元素紧靠有边界,且当前元素中子元素的增加不会影响整体的布局效果)。

以上为一种方式可以自动分配剩余空间,也可以通过弹性盒子主轴上的规则来进行布局也行。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352