flex布局

  • 教程(来自CSS Tricks
  • 忘掉
  • 用flex重写float布局
  • flex布局对性能的影响
  • FFC

容器container,子项item

一个规矩:不缩写具有特殊明确含义或者非约定行业规范、业界共识(HTML CSS JS)的英文,即使很长:class="container"

  • 容器.container,作父元素
  • 直接的子元素,.item
  • 设置了 display: flex 的父元素(在本例中是 .container)被称之为 flex 容器(flex container
  • 在 flex 容器中表现为弹性的盒子的元素被称之为 flex 项(flex item)(本例中是.item )元素

容器flex container的样式

让一个元素变成flex容器

1
2
3
4
.container{
    display:flex;
    /* or inline-flex */
}
  • display:flex;不另起一行
  • display:inline-flex;另起一行
  • 直接子元素自动变为flex item

属性不写就是默认值

改变items流动方向(主轴main axis)

即改变默认文档流方向:

1
2
3
4
.container{
    display:flex;
    flex-direction:column;
}
  • 默认取值row,从左往右排列
  • 弹性盒模型的流flex flow,之前是普通normal flow
  • 可取值:row | row-reverse | column | column-reverse

    1
    2
    3
    4
    
    .container{
    display:flex;
    flex-direction: row | row-reverse | column | column-reverse;
    }

改变折行

弹性盒模型中,设置的宽高不是计算宽高(Computed)

挤满一行,有多少空间就挤多少空间

wrap-reverse一般不用

  • flex-wrap:nowrap;:默认不折行,可能会压缩子元素,强制在一行中显示
  • 可取值nowrap | wrap | wrap-reverse

    1
    2
    3
    4
    
    .container{
    display:flex;
    flex-wrap: nowrap | wrap | wrap-reverse;
    }

flex-flow:

  • flex-directionflex-wrap 的缩写形式

    1
    2
    3
    
    .container {
    flex-flow: <flex-direction> || <flex-wrap>;
    }
  • 默认值为 flex-flow: row nowrap

  • 如果写了两个值都写了,则第一个为flex-direction,第二为flex-wrap

  • 若只写一个,即简写,则会根据写的内容来判断是flex-direction还是flex-wrap


主轴(main axis)对齐方式:justify-content

Emmet缩写jc

  • 默认从左往右:justify-content:flex-start;
  • 弹性流的方式都往开始那里挤
  • 可取值flex-start | flex-end | center
  • flex-start:尽量往前靠
  • flex-end:尽量往后靠
  • center:居中,尽量往中间靠

还有三种:

  • space-between:把所有剩余空间尽量放到间隙里,和 space-around 非常相似,只是它不会在两端留下任何空间。
  • space-around:把所有剩余空间平均放到子元素周围(所有子元素左右各得一份相同大小的空间间隙,等分间隙),会使所有 flex 项沿着主轴均匀地分布,在任意一端都会留有一点空间
  • space-evenly:平均围绕子元素,即所有子元素间的空隙宽度相同,空隙等宽

    1
    2
    3
    4
    
    .container{
    display:flex;
    justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
    }

次轴对齐方式:align-items

默认次轴是纵轴,即交叉轴

子元素高度不一致时用

Emmet缩写ai

  • 默认值align-items: stretch :延伸,拉伸
  • 子元素设固定高度时,容器高度由最高子元素撑开,不会拉长所有子元素,各元素往上顶
  • 子元素不设固定高度时,高度由内容撑开,会拉长所有子元素,直至和最高一个子元素一样高

其会使所有 flex 项沿着交叉轴的方向拉伸以填充父容器。

如果父容器在交叉轴方向上没有固定宽度(即高度),则所有 flex 项将变得与最长的 flex 项一样长(即高度保持一致)

  • align-items: flex-start :各元素往上顶
  • align-items: flex-end :各元素往下顶
  • align-items: center:居中
  • align-items: baseline及其他:不用,不学

    1
    2
    3
    4
    
    .container{
    display:flex;
    align-items: stretch | flex-start | flex-end | center | baseline等
    }

MDN:

  • 主轴(main axis)是沿着 flex 元素放置的方向延伸的轴(比如页面上的横向的行、纵向的列)

  • 该轴的开始和结束被称为 main start 和 main end

  • 交叉轴(cross axis)是垂直于 flex 元素放置方向的轴

  • 该轴的开始和结束被称为 cross start 和 cross end

多行内容(很少用到)

高度、宽度都有多余空间

语法

1
2
3
.container{
    align-content: flex-start | flex-end | center | stretch | space-between | space-around;
}

如何分布

  • align-content: stretch;:默认值,拉伸
  • align-content: flex-start;:子元素往上顶,多余的行高全部分配到底部
  • align-content: flex-end;:子元素网下顶,多余的行高全部分配到顶部
  • align-content: center;:子元素居中,多余的行高分别分配到顶部和底部
  • align-content: space-between;:各个相邻子元素之间的间隙平均分配
  • align-content: space-around;:所有子元素沿着次轴均匀地各得一份相同大小的空间间隙
  • align-content: space-evenly;:平均围绕子元素,即所有子元素间的空隙宽度相同,等分间隙,空隙等宽

代码演示:css-demo_layout_flexbox_container

小结

容器上的属性,有下面六种属性可以设置在容器上,它们分别是:

  • flex-directionflex-wrap 、简写flex-flow、 - justify-contentalign-itemsalign-content

flex item的样式:基本样式

.item 上面加order

order默认值为0,取值范围:正负整数,指定取值从小到大排列

改变子元素显示顺序

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
.item:first-child {
    order:100;
}

.item:nth-child(2){
    order:2;
}

.item:last-child{
    order:-1;
}

注意.item:first-child这个选择器冒号:前后,不能有空格


flex item的样式:实现flex响应式

flex响应式实现_1:.item 上面加flex-grow

  • 定义了子元素的尺寸增长因子
  • flex item未设置固定宽度
  • 未加flex-grow属性时,不写则表示默认值 flex-grow: 0;flex item收缩至内容的宽高
  • 加了flex-grow属性,表示flex item挤占剩余空间的增长因子
  • 设置每个flex item都为flex-grow: 1;,则表示等比例的增长来填充剩余的空间
  • 是剩余空间的增长,不是所有的空间
  • 即使设置了增长因子,flex item也受到内容宽度的影响,overflow: auto;无效

growflex container 容器下的子元素的宽度和比容器和小的时候起作用

grow 容器中除去子元素之和剩下的尺寸会按照各个子元素的 grow 值进行平分加到各个子元素上

flex响应式实现_2:flex-shrink控制如何变瘦

  • 默认flex item的收缩因子是flex-shrink:1;
  • 收缩是当空间不够时才起效,即flex item的原始宽度被压缩的时候
  • 收缩因子flex-shrink值设得越大,收缩越快
  • flex item要加原始宽度
  • 一般写flex-shrink:0;,配合设置min-width,或者flex-basis的值,防止变瘦压缩内容
  • 一般让内容区正文收缩,其他区域防止收缩

flex-wrapflex-growflex-shrink的影响

flex-wrapwrap | wrap-reverse
且子项宽度和小于父容器宽度时

flex-grow 会起作用,子项会根据 flex-grow 设定的值放大(为0的项不放大)

且子项宽度和超过父容器宽度时

首先一定会换行,换行后,每一行的右端都可能会有剩余空间(最后一行包含的子项可能比前几行少,所以剩余空间可能会更大)

这时 flex-grow 会起作用,若当前行所有子项的 flex-grow 都为0,则剩余空间保留

若当前行存在一个子项的 flex-grow 不为0,则剩余空间会被 flex-grow 不为0的子项占据

flex-wrapnowrap,且子项宽度和小于父容器宽度时

flex-grow 会起作用,子项会根据 flex-grow 设定的值放大,为0的项不放大

flex-wrapnowrap,且子项宽度和超过父容器宽度时

flex-shrink 会起作用,子项会根据 flex-shrink 设定的值进行缩小(为0的项不缩小)

但这里有一个较为特殊情况,就是当这一行所有子项 flex-shrink 都为0时,也就是说所有的子项都不能缩小,就会出现横向滚动条

小结2

可以看出不管在什么情况下,在同一时间,flex-shrinkflex-grow 只有一个能起作用

这其中的道理细想起来也很浅显:空间足够时,flex-grow 就有发挥的余地,而空间不足时,flex-shrink 就能起作用

当然,flex-wrap 的值为 wrap | wrap-reverse 时,表明可以换行,既然可以换

一般情况下空间就总是足够的,flex-shrink 当然就不会起作用

flex响应式实现_3:flex-basis控制基准宽度

  • 未设置flex item的宽度时可用
  • 不写就是默认值flex-basis:auto;,计算值为width的值
  • 就是宽度的意思,可以代替宽度

详细地可看以下两篇:

【翻译】Flex Basis与Width的区别

【译】 width 与 flex-basis 的区别

缩写

1
2
3
.item{
    flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
} 
  • 空格隔开:flex:flex-grow flex-shrink flex-basis;
  • 默认值 flex-grow: 0;
  • 默认值 flex-shrink:1;
  • flex-basis可不写,就是默认值auto
  • 缩写默认值0 1 auto

关于 flex 取值,还有许多特殊的情况,可以按以下来进行划分:

flex 取值为一个非零非负数字

则该数字为 flex-grow 值,flex-shrink 取 1,flex-basis0%

如下是等同的:

1
2
3
4
5
6
7
.item {flex: 1;}
/* 等同 */
.item {
    flex-grow: 1;
    flex-shrink: 1;
    flex-basis: 0%;
}

flex 取值为 0

对应的三个值分别为0 1 0%

如下是等同的:

1
2
3
4
5
6
7
.item {flex: 0;}
/* 等同 */
.item {
    flex-grow: 0;
    flex-shrink: 1;
    flex-basis: 0%;
}

flex 取值为一个长度或百分比

则视为 flex-basis 值,flex-grow 取 1,flex-shrink1,有如下等同情况(注意 0% 是一个百分比而不是一个非负数字)

如下是等同的:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
.item-1 {flex: 0%;}
/* 等同 */
.item-1 {
    flex-grow: 1;
    flex-shrink: 1;
    flex-basis: 0%;
}

.item-2 {flex: 24px;}
/* 等同 */
.item-2 {
    flex-grow: 1;
    flex-shrink: 1;
    flex-basis: 24px;
}

flex 取值为两个非负数字

则分别视为 flex-growflex-shrink 的值,flex-basis0%

如下是等同的:

1
2
3
4
5
6
7
.item {flex: 2 3;}
/* 等同 */
.item {
    flex-grow: 2;
    flex-shrink: 3;
    flex-basis: 0%;
}

flex 取值为一个非负数字和一个长度或百分比

则分别视为 flex-growflex-basis 的值,flex-shrink1

如下是等同的:

1
2
3
4
5
6
7
.item {flex: 11 32px;}
/* 等同 */
.item {
    flex-grow: 11;
    flex-shrink: 1;
    flex-basis: 32px;
}

如果记不住,就分开写

以上,即可实现flex响应式


align-self特殊定制align-items

  • container里设置align-items,是统一控制所有子项
  • 某个item里设置align-self,是特殊定制这个子项

代码演示:css-demo_layout_flexbox_item

小结3

Flex 伸缩项上的属性

伸缩项有6种属性:

  • orderflex-basisflex-growflex-shrink flexalign-self

重点 工作基本只用这些

  • display:flex;
  • flex-direction:[row | colum];
  • flex-wrap:wrap;
  • justify-content:[center | space-between]
  • align-items:center

实践

flex做横向布局:

  • 两栏布局
  • 三栏布局
  • 四栏布局
  • 平均布局
  • 组合使用,实现更复杂布局

代码演示:css-demo_layout_flexbox

经验

  • 永远不要把widthheight写死,除非特殊说明
  • [min-width | max-width | min-height | max-height]代替
  • flexmargin-xxx:auto;配合有意外的效果
  • flex使用负margin
  • flex可基本满足所有布局要求
  • 使子元素分列两侧,容器container上加样式:justify-content:space-between,或者在右侧子元素加样式:margin-left:auto;
  • 去掉图片下方空白:vertical-align: middle;
  • 使图片居中:在图片的父元素上加样式display: flex;align-items: center;

不写死width:100px

可以是:

  • width:50%;
  • max-width:100px;
  • width:30vw;
  • width:80%;

要么加前缀minmax,要么别使用px

负margin

FFC

flex项目深入分析


·未完待续·

参考文章

FlexBox布局全解

【翻译】Flex Basis与Width的区别

【译】 width 与 flex-basis 的区别

Flex 布局教程:语法篇

Flex 布局教程:实例篇

MDN Flexbox

Flexplorer

Flexplorer2

Learnable Flexbox

Flex小游戏

CSS 布局.pdf

W3C Flex Layout Box Model

A flexbox grid demo

相关文章