前言
由于之前一直在开发b端的项目,基本都基于现有的组件库开发,手动写样式布局的情况很少,最近手里拿到了一个移动端的项目,正好进行下查缺补漏,希望也能对大家有一些小小滴帮助~
flex
flex也就是我们常说的Flexible Box("弹性"布局),我对"弹性"的理解是定义为display:flex
为容器内的元素在"弹性"空间内可一放大或者缩小,flexbox是一种一维的布局,它提供了十分强大的空间分布和对齐能力,但是只能处理一行或者一列的一个纬度上的元素布局,任何一个容器都可以指定为flex布局,行内用display:inline-flex
。
设定为flex后,子元素的float、clear和vertical-align属性将失效。
弹性容器的属性
flex-direction
flex布局一共有两根轴线-主轴(main axis)和交叉轴(cross axis)。主轴就由flex-direction
属性定义,另一根轴垂直与它,由于我们是一维布局,所以所有的flex属性都和这两根轴线有关,flex-direction
有四个取值:
.item {
flex-direction: "row" | "row-reverse" | "column" | "column-reverse";
}
定义为前两种主轴则横向伸展,后两种则纵向伸展。
flex-wrap
在默认的情况下,弹性盒子内元素在一条线上,默认不换行,flex-wrap属性定义了如果一排拍不下怎么换行,有三个取值:
.item {
flex-wrap:"nowrap" | "wrap" | "wrap-reverse";
}
分别为不换行、向下换行、向上换行。
flex-flow
是上两种属性的简写:
.item {
flex-flow: "flex-direction" | "flex-wrap";
}
默认为 row nowrap
justify-content | align-items | align-content
这三种属性定义分别定义了弹性盒子内元素在主轴和交叉轴,以及多根轴线时的对齐方式,我们可以借由这前两种属性实现简单的元素水平垂直居中:
.item {
display:flex;
justify-content:center;
align-items: center;
}
justify-content
有五种属性:
.item {
justify-content: "flex-start" | "flex-end" | "center" | "space-between" | "space-around";
}
按顺序为左对齐、右对齐、居中、两端对齐,元素间距相等、每个项目间的距离都相等,所以两侧的距离才会看起来小于中间的。
align-items
有五种属性:
.item {
algin-items: "stretch" | "flex-start" | "flex-end" | "center" | "baseline";
}
按顺序为占满设置容器的高度、交叉轴的起点对齐、交叉轴的终点对齐、交叉轴的中点对齐、第一行的文字底部对齐。
algin-content
定义了多跟轴线的对齐方式,只有一根轴线时不起作用,有六种属性:
.item {
algin-content: "stretch" | "flex-start" | "flex-end" | "center" | "space-between" | "space-around";
}
按顺序为轴线占满整个交叉轴、交叉轴的起点对齐、交叉轴的终点对齐、交叉轴的中点对齐、两端对齐中间距离平分、两根轴线距离平分,所以两侧看起来小于中间的。
弹性元素的属性
order
弹性容器内的元素根据order
去决定顺序,值是整数,值越小越靠前,默认为0.
.item {
order: "整数";
}
flex-grow
|flex-shrink
|flex-basis
在说着三个属性之前我先说两个概念:正自由空间positive free space
(个人理解:剩下的空间),负自由空间negative free space
(个人理解:超出的空间)。
以这两张图片为例,500px
的弹性容器,上边空余的200px
就是剩下的,下边多出的100px
就是超出的。
为什么要介绍这两个概念呢?
flex
子元素没有positive free space
就不会增长, 没有negative free space
就不会缩小.也就是说我们所有元素的宽度加起来小于容器总宽,那么我们的flex-grow
才会生效,反之我们所有元素的宽度加起来大于容器总宽,那么我们的flex-shrink
才会生效。
flex-grow
该属性定义了flex元素在容器内的放大比例,默认为0,即不放大。
.item {
flex-grow: "number";
}
如果我们定义了元素的flex-grow
属性,且弹性容器有剩余的空间,我们的元素会根据flex-grow
去分配剩余的空间,那我们是怎么计算该属性的呢,我写了下边的demo:
html
部分:
<div class="container">
<div class="one">A<br>width:100px<br>flex-grow:1</div>
<div class="two">B<br>width:200px<br>flex-grow:2</div>
<div class="three">C<br>width:150px<br>flex-grow:3</div>
</div>
css
部分:
* {
margin: 0;
padding: 0;
}
.container {
width: 600px;
height: 300px;
display: flex;
border: 2px dotted #333333;
margin: 0 auto;
}
.container > div {
text-align: center;
}
.one {
width: 100px;
flex-grow: 1;
background-color: #ff4466;
}
.two {
width: 200px;
flex-grow: 2;
background-color: #42b989;
}
.three {
width: 150px;
flex-grow: 3;
background: #61daff;
}
效果:
我们有如下的计算方式: 以A为例子,A的实际宽度为 width + A/(A+B+C)* X
,ABC分别为三个元素的flex-grow
的值,X
为剩余空间的大小,width
为之前的宽度,依次计算下ABC的实际宽度为:125px
、250px
、225px
.大家也可以自己尝试一下。
flex-shrink
该属性定义了元素的缩小比例,默认为1,则如果有溢出空间,将缩小。
.item {
flex-shrink: "number";
}
如果我们定义了元素的flex-shrink
属性,且弹性容器有超出的空间,我们的元素会根据flex-shrink
去缩小,我们也通过下面我写的demo去看一下:
html
部分:
<div class="container">
<div class="one">A<br>width:300px<br>flex-shrink:1</div>
<div class="two">B<br>width:300px<br>flex-shrink:2</div>
<div class="three">C<br>width:300px<br>flex-shrink:3</div>
</div>
css
部分:
* {
margin: 0;
padding: 0;
}
.container {
width: 600px;
height: 300px;
display: flex;
border: 2px dotted #333333;
margin: 0 auto;
}
.container > div {
text-align: center;
}
.one {
width: 300px;
flex-shrink: 1;
background-color: #ff4466;
}
.two {
width: 300px;
flex-shrink: 2;
background-color: #42b989;
}
.three {
width: 300px;
flex-shrink: 3;
background: #61daff;
}
效果:
我们计算方式如下:还是以A为例子,首先计算压缩的权重,也就是系数,ABC
为flex-shrink
的值,权重:weight = A * w1 + B * w2 + C * w3
,X
为多余的空间,则A的实际宽度就为300-(300/1800)*300 = 250px
,也就是原有的宽度减去,压缩率乘多余的空间,压缩率的计算以A为例子就是A * w1 / weight
.剩余的计算下来就是200px
和150px
,大家也可以自己算一下。
flex-basis
该属性定义了在分配多余空间之前,元素占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的原本大小。
.item {
flex-basis: "length" | "auto";
}
该属性和元素的宽度相关,我们通过一个demo看一下他和width
min/max-width
的优先级:
html
部分:
<div class="container">
<div class="box one">A</div>
<div class="box two">B</div>
<div class="box three">C</div>
</div>
css
部分:
* {
margin: 0;
padding: 0;
}
.container {
width: 600px;
height: 300px;
display: flex;
border: 2px dotted #333333;
margin: 0 auto;
}
.box {
text-align: center;
}
.one {
width: 100px;
flex-basis: 150px;
background-color: #ff4466;
}
.two {
max-width: 50px;
width: 100px;
flex-basis: 200px;
background-color: #42b989;
}
.three {
width: 100px;
background: #61daff;
}
效果:
我们可以看出优先级比较是: min/max-width > flex-basis > width
align-self
该属性可以控制单个元素和其他元素不相同的方式对齐,会覆盖父元素的align-items
属性,默认为auto
继承父元素,如果没有父元素则为stretch
.item {
align-self: "auto" | "flex-start" | "flex-end" | "center" | "stretch" | "baseline"
}
该属性主要应用于子元素上,其特征除了auto
有点特殊,其余和align-items
完全一致。
浏览器支持
实际使用
我们在日常的开发中,太多太多的地方用到了布局的概念,顶部或者底部导航我们有了flex后就显得十分的简单,直接在content
部分设置为flex: 1 === flex: 1 1 0%
,这样这个唯一可以伸缩的空间就会把我们的footer
推到我们的底部去啦~ 更多的比如开头说道的水平垂直居中,以及一些媒体对象的处理,都会用到我们的flex,所以说这一块还是有必要好好的思考一下的~
写在后面
(个人学习笔记,grid下次更新~)