Souffle css3 弹性盒
传统的布局一般使用 display、float、position 实现的,但有局限性,
比如“垂直水平的居中”就不好实现,用定位 position 实现还要设置其他属性配合,所以在 2009 年 css3 提出 flex 弹性盒的布局方案
一、设置弹性盒模型
定义主轴方向
flex-direction: row(默认) | row-reverse | column | column-reverse
溢出换行
flex-wrap: nowrap(默认)| wrap | wrap-reverse
当设置 flex-grow 属性的时候
1. wrap 换行失效,会尽可能按 flex-basis 的值往大了去从而达到折行的目的,根据弹性项目的实际宽度判断是否换行
2. flex-shrink 也会失效
以 align 开头的都是设置侧轴的对齐方式,当容器侧轴还有剩余空间的时候,设置在侧轴的对齐方式
align-content:center 居中对齐,如果只有一行项目不会生效,因为它设置的是整体
align-items:center 单行居中对齐
flex 布局是一个弹性盒子,它让容器里面的所有的子元素有了伸缩的特性
1. 在父元素上设置弹性盒子 display: flex,父元素叫容器,
2. 子元素有伸缩性,叫弹性项目
<style> .wrapper{ width: 500px; height: 500px; background-color: cornsilk; display: flex; /* 在父元素上设置弹性布局 */ } .box{ width: 200px; /* 每个项目宽200,4*200超出了容器宽度 */ height: 100px; background-color: bisque; } .box:nth-child(2n){ background-color: burlywood; } .item1{ height: 200px; } .item2{ background-color: saddlebrown; } .item3{ height: 400px; } .item4{ height: 600px; } </style> <div class="wrapper"> <div class="box item1">box1</div> <div class="box item2">box2</div> <div class="box item3">box3</div> <div class="box item4">box4</div> </div>
弹性项目默认横向排列,
如果项目的 width 宽之合超出容器的宽度,会按一定比例自动压缩,
弹性项目的高度没有伸缩变化,如果高度超出了容器也不会压缩
box1box2box3box4
二、弹性项目的对齐方式
flex 布局有两个轴主轴和侧轴,对齐方式就分成两类
1. 主轴上的对齐方式
2. 侧轴上的对齐方式
1、主轴上的对齐方式
justify-content 属性设置在容器上,定义弹性项目在主轴上的对齐方式,单行多行都可以使用
属性值 | 说明 |
flex-start | 左对齐(默认),容器起始位置 |
flex-end | 右对齐,容器结束位置 |
center | 居中 |
space-between | 左右两边对齐,并且项目之间的间隔相等 |
space-around | 每个项目两侧的间隔相等,所以项目之间的间隔,比项目与边框的间隔大一倍 |
space-evenly | 项目之间的间隔与容器与项目之间的空隙是一样的 |
space-evenly 对齐
<style> .wrapper{ width: 500px; height: 500px; border:1px solid #ccc; display: flex; justify-content: space-evenly; /* 项目之间的间隔与容器与项目之间的空隙一样 */ } .box{ height:100px; width: 100px; background-color: bisque; } .box:nth-child(2n){ background-color: burlywood; } </style> <div class="wrapper"> <div class="box item1">box1</div> <div class="box item2">box2</div> <div class="box item3">box3</div> <div class="box item4">box4</div> </div>
项目之间的间隔与容器与项目之间的空隙一样
box1box2box3box4
如果主轴设置为垂直方向,间隔就变成上下
<style> .wrapper{ width: 500px; height: 500px; border:1px solid #ccc; display: flex; flex-direction: column; /* 设置主轴为垂直方向 */ justify-content: space-evenly; } .box{ height:100px; width: 100px; background-color: bisque; } .box:nth-child(2n){ background-color: burlywood; } </style> <div class="wrapper"> <div class="box item1">box1</div> <div class="box item2">box2</div> <div class="box item3">box3</div> <div class="box item4">box4</div> </div>
主轴垂直,间隔垂直方向
box1box2box3box4
2、侧轴方向的对齐方式
align-items 属性设置沿测轴方向上的对齐方式,该属性也设置在容器上(单行对齐方式)
属性值 | 说明 |
flex-start | 交叉轴的起点位置对齐,就是容器顶部 |
flex-end | 交叉轴的终点位置对齐,就是容器底部 |
center | 交叉轴中心对齐,容器中间 |
baseline | 弹性项目第一行文字基线对齐,基线是小写字母 x 的底部 |
stretch(默认) | 如果弹性项目没有设置高度或为auto的时候有效,项目高度将占满整个容器高度 |
基线对齐
第一个元素设置 padding,
第二个元素里面有 p 元素,p 元素有默认 margin,
弹性盒子的顶部不是对齐的,但是盒子里面的文字都是对齐的,因为设置了 baseline 基线对齐
<style> .wrapper{ width: 500px; height: 500px; border:1px solid #ccc; display: flex; justify-content: space-between; align-items: baseline; /* 侧轴基线对齐 */ } .box{ height:100px; width: 100px; background-color: bisque; } .box:nth-child(2n){ background-color: burlywood; } .item1{ padding-top: 20px; /* 往下移动 */ } </style> </head> <body> <div class="wrapper"> <div class="box item1">box1</div> <div class="box item2"> <p>box2</p> </div> <div class="box item3">box3</div> <div class="box item4">box4</div> </div>
基线指的是只要有文字,基线是小写字母 x 的底部,
如果项目里面没有文字,基线是盒子的底边
box1box2box3box4
stretch 字面是伸展延伸的意思,
1. 如果弹性项目不设置高度,侧轴的对齐方式的不是 stretch,默认高度是被内容撑开的
2. 如果弹性项目设置高度,侧轴设置 stretch 没有效果
3. 只有在弹性项目没有设置高度或高度为 auto 的时候,侧轴设置 stretch 对齐有效,高度将占满整个容器高度
<style> .wrapper{ width: 500px; height: 500px; border:1px solid #ccc; display: flex; justify-content: space-between; align-items: stretch; /* 默认的对齐方式 */ } .box{ /* height:100px; */ width: 100px; background-color: bisque; } .box:nth-child(2n){ background-color: burlywood; } </style> </head> <body> <div class="wrapper"> <div class="box">box1</div> <div class="box">box2</div> <div class="box">box3</div> <div class="box">box4</div> </div>
项目不设置高度,stretch 默认占满整个容器高度
box1box2box3box4
flex-self 和 align-item 都是设置侧轴对齐的方式
1. flex-self 和 align-item属性值是一样的
2. align-item 设置在容器上,表示设置的是所有的弹性项目
3. flex-self 单独设置在某一个项目上的
4. flex-self 的权重高于 agin-item
flex-self: center 设置居中对齐在项目 .item1 上
<style> .wrapper{ width: 500px; height: 500px; border:1px solid #ccc; display: flex; justify-content: space-between; align-items: stretch; } .box{ /* height:100px; */ width: 100px; background-color: bisque; } .box:nth-child(2n){ background-color: burlywood; } .item1{ align-self: center; /* 权重高于agin-item */ } </style> <div class="wrapper"> <div class="box item1">box1</div> <div class="box item2">box2</div> <div class="box item3">box3</div> <div class="box item4">box4</div> </div>
box1 元素居中对齐
box1box2box3box4
align-content 属性定义了多根主轴线在测轴的对齐方式,如果项目只有一根主轴,该属性不起作用
属性值 | 说明 |
flex-start | 与交叉轴起点对齐,整体在容器的顶端 |
flex-end | 与交叉轴终点对齐,在容器的下面 |
center | 与交叉轴中心点对齐 |
space-between | 交叉轴两端对齐,轴与轴之间平均分布剩余空间 |
space-around | 每根轴线两侧的间隔相等 |
space-evenly | 平均分配剩余空间 |
stretch(默认值) | 如果不设置高,高度占满整个交叉轴 |
容器宽度 300 像素,设置 flex-wrap: wrap 表示换行,弹性项目超出容器尺寸不进行压缩,
1. 换行后有两个主轴,两个主轴平分容器,第二条主轴在容器的中间,
2. 每条主轴默认都是从左到右,从上到下排列
<style> .wrapper{ width: 300px; height: 500px; border:1px solid #ccc; display: flex; flex-wrap: wrap; /* 换行 */ } .box{ height:100px; width: 100px; background-color: bisque; } .box:nth-child(2n){ background-color: burlywood; } </style> </head> <body> <div class="wrapper"> <div class="box item1">box1</div> <div class="box item2">box2</div> <div class="box item3">box3</div> <div class="box item4">box4</div> <div class="box item5">box5</div> </div>
换行后两个主轴平分容器
box1box2box3box4box5
设置 align-content: center 多行项目整体居中
<style> .wrapper{ width: 300px; height: 500px; border:1px solid #ccc; display: flex; flex-wrap: wrap; align-content:center; /* 多行居中对齐 */ } .box{ height:100px; width: 100px; background-color: bisque; } .box:nth-child(2n){ background-color: burlywood; } </style> </head> <body> <div class="wrapper"> <div class="box item1">box1</div> <div class="box item2">box2</div> <div class="box item3">box3</div> <div class="box item4">box4</div> <div class="box item5">box5</div> </div>
换行后多行居中对齐
box1box2box3box4box5
align-items 和 align-content
1. 只要 align 开头的属性都是设置侧轴的
2. align-content 把多行看做一个整体在交叉轴对齐的方式(align-content 属性和 justity-content 属性的值是类似的)
3. align-item 每一行项目在交叉轴对齐的方式
三、弹性项目的伸缩变化
flex-grow 放大比例,按比例分配剩余空间,也就是放大比例,默认值 0
flex-shrink 缩小比例,压缩比例,默认值 1 表示按照 1:1:1 比例伸缩变换
flex-basis 伸缩基准值
order 排列顺序,默认值是0
align-self 单个项目的对齐方式
flex 复合属性由 flex-grow, flex-shrink, flex-basis 三个子属性组成
flex-shrink 属性设置的是,如果项目尺寸超出容器,按什么比例压缩,默认值是 1
弹性项目的宽度合 1100,大于父元素宽度,多出了 600 像素
500 + 200 + 200 + 200 = 1100
1100 - 500 = 600
<style> .wrapper{ width: 500px; height: 500px; background-color: cornsilk; display: flex; } .box{ width: 200px; height: 100px; background-color: bisque; } .box:nth-child(2n){ background-color: burlywood; } .item1{ width: 500px; /* 第一个盒子宽度500 */ } </style> <div class="wrapper"> <div class="box item1">box1</div> <div class="box item2">box2</div> <div class="box item3">box3</div> <div class="box item4">box4</div> </div>
项目自动缩减尺寸,根据 flex-shrink 默认值 1 进行压缩
box1box2box3box4
压缩的计算公式
(flex-shrink * width1) / (flex-shrink * width1 + flex-shrink * width2 + flex-shrink * width3 + flex-shrink * width4) * moreWidth
计算第一个盒子 .demo1 的缩减后的尺寸,
1. 计算缩减的比例
(1 * 500) / (1 * 500 + 1 * 200 + 1 * 200 + 1 * 200) = 0.45454545454545453
2. 计算需要缩减的尺寸,
缩减比例乘以超出的尺寸 600
0.45454545454545453 * 600 = 272.7272727272727
3. 最后得出 .dome1 缩减后的尺寸,用第一个元素宽度 500 减掉 272.7272727272727
500 - 272.7272727272727 = 227.272727272728
注意这样的问题
如果只有第一个子元素 .item1 进行缩减 flex-shrink:1
其他子元素不进行缩减 flex-shrink: 0,
其它三个子项目的宽度还是超出父元素的宽度,会出现问题
flex-grow 表示按比例分配容器剩余部分,默认值为 0 表示不分配
每个盒子宽度 100px,容器出现剩余的空间,
设置第一个元素 flex-grow:1 表示按比例吃掉容器的剩余部分,第一个元素变成 200 像素
<style> .wrapper{ width: 500px; height: 500px; background-color: cornsilk; display: flex; } .box{ width: 100px; height: 100px; background-color: bisque; } .box:nth-child(2n){ background-color: burlywood; } .item1{ flex-grow:1; /* 吃掉剩余部分 */ } </style> <div class="wrapper"> <div class="box item1">box1</div> <div class="box item2">box2</div> <div class="box item3">box3</div> <div class="box item4">box4</div> </div>
.box1 吃的剩余部分
box1box2box3box4
主轴和侧轴
主轴,弹性项目默认在水平方向,从左到右排列,这种默认的排列方式我们叫主轴,弹性项目沿着主轴进行压缩或扩展
侧轴,与主轴垂直的轴叫侧轴(也可以叫交叉轴)
flex-direction: column 在容器上设置主轴为垂直排列
<style> .wrapper{ width: 500px; height: 500px; background-color: cornsilk; display: flex; flex-direction: column; /* 主轴纵向排列 */ } .box{ width: 200px; height: 100px; background-color: bisque; } .box:nth-child(2n){ background-color: burlywood; } .item1{ height: 200px; } .item3{ height: 400px; } .item4{ height: 600px; } </style> <div class="wrapper"> <div class="box item1">box1</div> <div class="box item2">box2</div> <div class="box item3">box3</div> <div class="box item4">box4</div> </div>
设置纵向排列后,变成了对高度 height 的压缩或扩展
box1box2box3box4
flex-basis 表示沿着主轴方向的“伸缩的基准值”,因为主轴的方向是可以变化的
1. 当主轴水平方向时,基准值相当于 width 宽度
2. 当主轴垂直方向时,基准值相当于 height 高度
3. flex-basis 的优先级高于 width/height,并按照基准值进行伸缩变化
给所有的盒子设置基准值 flex-basis: 200px
设置基准值后 width 就失效了,按照基准值的宽度压缩盒子
<style> .wrapper{ width: 500px; height: 500px; background-color: cornsilk; display: flex; } .box{ flex-basis: 200px; /* 设置基准值,每个盒子宽度200像素 */ height: 100px; background-color: bisque; } .box:nth-child(2n){ background-color: burlywood; } .item1{ width:100px; flex-shrink: 1; /* 压缩 */ } .item2{ width:300px; flex-shrink: 1; /* 压缩 */ } .item3{ width: 400px; flex-shrink: 1; /* 压缩 */ } .item4{ width: 600px; flex-shrink: 1; /* 压缩 */ } </style> <div class="wrapper"> <div class="box item1">box1</div> <div class="box item2">box2</div> <div class="box item3">box3</div> <div class="box item4">box4</div> </div>
计算压缩尺寸
1. 缩减比例 (200 * 1) / (200*1 + 200*1 + 200*1 + 200*1) = 0.25
2. 超出的尺寸 (4 * 200) - 500 = 300
3. 项目要减去的尺寸 300 * 0.25 = 75
4. 最后 200 - 75 = 125
flex: flex-grow flex-shrink flex-basis
该复合属性,由三个子属性复合而成,上面的效果可以简写为 flex: 0 1 200px
flex 复合属性
设置一个值代表 flex-grow
设置二个值分别代表 flex-grow 和 flex-shrink
设置二个值分别代表 flex-grow flex-shrink flex-basis
order 设置元素的顺序,默认从左到右,默认值 0
.wrapper{ width: 500px; height: 500px; background-color: cornsilk; display: flex; } .box{ height: 100px; background-color: bisque; } .box:nth-child(2n){ background-color: burlywood; } .item1{ flex: 0 1 200px; order: 2; /* 第四 */ } .item2{ flex: 0 1 200px; order: 1; /* 第三 */ } .item3{ flex: 0 1 200px; order: 0; /* 第二 */ } .item4{ flex: 0 1 200px; order: -1; /* 第一*/ }
align-self 设置单个项目在侧轴方向(交叉轴)的对齐方式
center 居中
flex-start 测轴方向的起始位置
flex-end 测轴方向的终止位置
baseline
stretch
因为主轴是可以变换的
如果主轴是水平排列,align-self 代表垂直方向的排列
如果主轴是垂直排列,align-self 代表水平方向的排列