flex布局全解析
前言
很长一段时间, 我知道有flex
这个布局方式, 但是始终没有去学它. 3点原因:
- 感觉还比较新, 担心兼容性不好.
- 普通的布局方式能满足我的绝大多数需求.
- 好像蛮复杂的.
最近由于开发需要, 学习了下WeUI的实现, 发现里面大量使用了flex
布局, 于是决定学习一下.
什么是flex
Flexbox Layout
, 官方名为CSS Flexible Box Layout Module, 意为"弹性布局", 是CSS3中引入的一种更加灵活高效的布局/对齐/排序方式(还有一种更适合大型布局的网格布局CSS Grid Layout Module). flex
是flexible
的缩写.
任何一个容器都可以指定为flex布局。
.box {
display: flex;
}
行内元素也可以使用flex布局。
.box {
display: inline-flex;
}
flex的基本概念
采用flex布局的元素被称为flex容器 (flex container), 它的子元素即为flex元素 (flex item).
flex容器中包含两个相互垂直的轴, 即主轴 (main axis)和副轴 (cross axis).
flex元素沿主轴从主轴起点 (main start)到主轴终点 (main end)依次排布.
如果flex容器包含多行flex元素, 则flex行 (flex lines)沿副轴从副轴起点 (cross start)到副轴终点 (cross end)依次排布.
单个flex元素占据的主轴空间叫做主轴长度 (main size), 占据的副轴空间叫做副轴长度 (cross size).
flex的兼容性
Getting Dicey With Flexbox中提到:
There's a popular myth floating around that flexbox isn't ready for prime time. Wrong! 93% of people are now running a browser that supports flexbox. That's better than the support for the HTML5
<video>
element.
前一段时间同事做过video
相关的开发, 踩到各种坑, 因此我知道video
的支持不那么好, 特别是在Android上. 让我惊奇的是flex
竟然比video
的支持更好?
从CanIUse的数据来看, flex
的支持度是: 82.65% (支持) + 14.17% (部分支持) = 96.81%
, 而video
的支持度是: 92.48%
. 浏览器对flex
的支持好像并没有特别好...
但是有微信的WeUI使用了flex
布局, 我觉得在移动端flex
应该还是支持度比较高的.
所以, 如果你是做移动端开发的, 可以优先考虑flex
.
flex属性
下面就开始介绍与flex
布局相关的属性. 以作用对象分为两组, 第一组作用于flex容器, 第二组作用于flex元素.
注意: 以下属性值都可以有initial
(该属性的默认值)和inherit
(继承自父元素), 本处省略.
用于flex容器的属性
这类属性有6种, 分别为:
属性 | 含义 |
---|---|
flex-direction |
主轴方向 |
flex-wrap |
换行样式 |
flex-flow |
前两个的简写形式 |
justify-content |
主轴对齐方式 |
align-items |
单行的副轴对齐方式 |
align-content |
多行的副轴对齐方式 |
注意:
- flex容器的
column-*
属性会失效. - flex容器无法拥有
::first-line
和::first-letter
虚元素.
flex-direction
含义 | 主轴方向 |
可选值 | row | row-reverse | column | column-reverse |
默认值 | row |
row |
direction 为ltr 时从左向右→, rtl 时从右向左←. |
row-reverse |
direction 为ltr 时从右向左←, rtl 时从左向右→. |
column |
从上到下↓. |
column-reverse |
从下到上↑. |
注意: row
和row-reverse
受到了direction
属性(默认值为ltr
, 可改为rtl
)的影响.
flex-wrap
含义 | 换行样式 |
可选值 | nowrap | wrap | wrap-reverse |
默认值 | nowrap |
nowrap |
不换行 |
wrap |
换行. 行与行从上到下↓排布 |
wrap-reverse |
换行. 行与行从下到上↑排布 |
flex-flow
含义 | flex-direction 和flex-wrap 的简写形式 |
可选值 | flex-direction flex-wrap |
默认值 | row nowrap |
justify-content
含义 | 主轴对齐方式 |
可选值 | flex-start | flex-end | center | space-between | space-around |
默认值 | flex-start |
align-items
含义 | 单行的副轴对齐方式 |
可选值 | flex-start | flex-end | center | stretch | baseline |
默认值 | stretch |
align-content
含义 | 多行的副轴对齐方式 |
可选值 | stretch | flex-start | center | flex-end | space-between | space-around |
默认值 | stretch |
注意: 此属性只在flex容器中有多行flex元素时才有作用.
用于flex元素的属性
这类属性有6种, 分别为:
属性 | 含义 |
order |
排列顺序 |
align-self |
flex元素的副轴对齐方式. 对应于flex容器的align-items . |
flex-grow |
放大比例 |
flex-shrink |
缩小比例 |
flex-basis |
初始大小 |
flex |
上面三个的简写形式 |
注意: flex元素的float
, clear
和vertical-align
会失效.
order
含义 | 排列顺序. 沿着主轴, flex元素按order 的增序排列. |
可选值 | <integer> |
默认值 | 0 |
align-self
含义 | flex元素的副轴对齐方式. 对应于flex容器的align-items . |
可选值 | auto | stretch | center | flex-start | flex-end | baseline |
默认值 | auto |
当flex元素有父元素时, 它的align-self: auto
即为父元素的align-items
属性; 否则(无父元素时), 相当于stretch
.
flex-grow
含义 | 放大比例 |
可选值 | <number> (非负值) |
默认值 | 0 |
当有剩余空间时, flex元素会根据flex-grow
按比例分配剩余空间.
默认值0
代表, 即使有剩余空间, 该flex元素也不放大.
flex-shrink
含义 | 缩小比例 |
可选值 | <number> (非负值) |
默认值 | 1 |
当flex容器空间不足时, flex元素会根据flex-shrink
按比例缩小.
flex-shrink
为0
则表示, 即使flex容器空间不足, 该flex元素也不缩小.
flex-basis
含义 | 初始大小 |
可选值 | auto|<length> (非负值) |
默认值 | auto |
flex-basis
定义了分配剩余空间之前flex元素的初始大小, 可为长度值(如20%
, 5rem
等)或auto
等关键词.
flex-basis: auto
表示, 以flex元素的主轴长度为flex-basis
. 若flex元素的主轴长度也是auto
, 则以flex元素内容(即所有子元素)的大小为flex-basis
.
除了auto
还有content
, max-content
, min-content
和fit-content
关键词, 但是现在浏览器对它们的支持太少, 可以忽略.
flex
含义 | flex-grow , flex-shrink 和flex-basis 的简写形式 |
可选值 | none | [ <‘flex-grow’> <‘flex-shrink’>? || <‘flex-basis’> ] |
默认值 | 0 1 auto |
(敲黑板) 同学们注意, 这里是重点!
这里的可选值我参照了W3C flexbox的写法. 其中:
||
用来分割两个或多个选项, 从中选取一个或多个, 不限次序.|
用来分割两个或多个选项, 从中选取一个.[]
只是用来分组的.?
代表可选.
举例来说, a | [ b || c ]
包含的可能情况有a
, b
, c
, b c
, c b
.
现在回过头来再看none | [ <‘flex-grow’> <‘flex-shrink’>? || <‘flex-basis’> ]
就清晰多了.
注意, none
是一个特殊值, 相当于0 0 auto
.
另外, 如果flex
中不指定:
flex-grow
成员, 则flex-grow
会被置为1
.flex-shrink
成员, 则flex-shrink
会被置为1
.flex-basis
成员, 则flex-basis
会被置为0
.
注意: flex
的初始值是0 1 auto
, 即由每个flex
因子本身的默认值组成(比方说flex-grow
的默认值就是0
).
但是, 如果利用flex
设置了至少一个flex
因子, 那么没被设置的那些flex
因子的默认值(按grow, shrink, basis的顺序)分别是1 1 0
.
我来举几个栗子.
/* 特殊值none */
flex: none; /* 相当于0 0 auto */
/* 单值,没有单位的数字,是flex-grow */
flex: 2; /* 相当于 flex: 2 1 0 */
/* 单值,有单位的,宽、高,是flex-basis */
flex: 10em; /* 相当于 flex: 1 1 10em */
flex: 30px; /* 相当于 flex: 1 1 30px */
flex: auto; /* 相当于 flex: 1 1 auto */
flex: content; /* 相当于 flex: 1 1 content */
/* 两个值:flex-grow flex-basis */
flex: 1 30px; /* 相当于 flex: 1 1 30px */
/* 两个值:flex-grow flex-shrink */
flex: 2 2; /* 相当于 flex: 2 2 0 */
/* 三个值:flex-grow flex-shrink flex-basis */
flex: 2 2 10%;
W3C建议使用简写形式flex
, 因为它可以方便地应对下面4种常见情况.
flex: initial |
即flex: 0 1 auto . 以auto 方式计算flex-basis , 不可放大, 可缩小. |
flex: auto |
即flex: 1 1 auto . 以auto 方式计算flex-basis , 可放大, 可缩小. |
flex: none |
即flex: 0 0 auto . 以auto 方式计算flex-basis , 不可放大, 不可缩小. |
flex: <positive-number> |
即<positive-number> 1 0 . flex-basis 为0 , 以<positive-number> 比例增大, 以1 的比例缩小. |
flex元素大小的计算方法
自此, 我们已经知道了flex-grow
, flex-shrink
和flex-basis
的作用. 根据这三个值, 计算flex元素的大小只需三步:
第一步: 计算元素的flex-basis
, 有两种情况: 1. 具体的长度值, 或, 2.auto
(即flex元素的大小). (这里忽略了content
等目前支持还不完善的关键词).
第二步: 计算剩余空间, 即剩余空间 = flex容器的内部空间 - flex元素flex-basis值的总和
.
第三步: 按照flex
因子(放大时为flex-grow
; 缩小时为flex-shrink
)分配剩余空间到每个元素. flex元素的最终大小 = flex-basis - flex-factor * 剩余空间
.
举个栗子.
假设flex容器的内部空间为200px
, flex元素的大小的总和是160px
. 看起来, 还有200 - 160 = 40px
的剩余空间, 应该放大flex元素, 是不是? 不一定! 要看它们的flex-basis
总和.
假设它们的flex-basis
总和是300px
, 那么剩余空间应该是300 - 200 = -100px
. 此时剩余空间是负数, 应该以flex-shrink
对每个flex元素在flex-basis
的基础上进行缩小.
.item {
background-color: #dfdfdf;
border: .3em solid #aaa;
color: orange;
border-radius: .3em;
text-align: center;
font-weight: bold;
padding: .5em 0;
font-family: "Courier New", sans-serif;
color: #c7254e;
box-sizing: border-box;
}
.exmpl-flex-basis .container1,
.exmpl-flex-basis .container2 {
width: 200px;
display: flex;
margin: 1em auto 0;
}
.exmpl-flex-basis .item {
flex-grow: 0;
width: 80px;
}
.exmpl-flex-basis .item:nth-child(1) {
flex-shrink: 1;
}
.exmpl-flex-basis .item:nth-child(2) {
flex-shrink: 3;
}
.exmpl-flex-basis .container1 .item {
flex-basis: auto;
}
.exmpl-flex-basis .container2 .item {
flex-basis: 150px;
}
.exmpl-flex-basis .ruler {
border: dashed 1px #aaa;
color: #aaa;
box-sizing: border-box;
text-align: center;
font-size: 12px;
margin: 0;
display: block;
}
.exmpl-flex-basis .ruler1 {
border-bottom-width: 0;
width: 200px;
}
.exmpl-flex-basis .ruler2, .ruler3 {
border-top-width: 0;
float: left;
padding-top: 1em;
}
.exmpl-flex-basis .ruler2 {
width: 125px;
}
.exmpl-flex-basis .ruler3 {
width: 75px;
float: right;
}
.exmpl-flex-basis .ruler-container {
width: 200px;
}
.exmpl-flex-basis {
width: 200px;
margin: 0 auto;
}
下例中, 所有flex元素本身的大小为80px
, 元素中为flex
值.
你可以看到, 第一行的flex元素因为设置了flex-basis:auto
, 所以它们的flex-basis
就相当于元素大小, 即80px
, 即flex-basis
总和为160px
, 不足容器的200px
空间, 此时应该放大元素. 但又由于元素的flex-grow
为0
, 所以每个元素分配到0 * 40 = 0px
的剩余空间, 即不放大.
第二行的flex元素设置了flex-basis:150px
, 所以它们的flex-basis
总和为300px
, 超过了容器的200px
空间, 故按照flex-shrink
(比例为1:3
)进行缩小. 由于剩余空间为-100px
, 所以第一个元素应缩小25px
变成125px
, 第二个元素应缩小75px
变成75px
.
"绝对flex"和"相对flex"
绝对flex: 从0开始分配空间.
第一行中flex-basis
为0
, 表示每个flex元素的初始大小都视为0
. 此时, 剩余空间就是"flex容器的大小".
相对flex: 从flex元素大小开始分配空间.
第二行中flex-basis
为auto
, 表示每个flex元素的初始大小都是它本身的大小. 此时, 剩余空间就是"flex容器的大小 - flex元素大小的总和".
结语
呃... flex的东西还是挺多的, 特别是flex
因子相关的部分, 得花点儿时间理解.
但是, 我相信学flex是值得的, 谁用谁知道!
参考
- Flex 布局教程: 语法篇
- A Visual Guide to CSS3 Flexbox Properties
- A Complete Guide to Flexbox
- Getting Dicey With Flexbox: 用flex画骰子
- W3C: CSS Flexible Box Layout Module Level 1
flex布局全解析的更多相关文章
- css相关,flex布局全通!
寻根溯源话布局 一切都始于这样一个问题:怎样通过 CSS 简单而优雅的实现水平.垂直同时居中. 记得刚开始学习 CSS 的时候,看到 float 属性不由得感觉眼前一亮,顺理成章的联想到 Word 文 ...
- CSS Grid 网格布局全解析
介绍 CSS Grid(网格) 布局使我们能够比以往任何时候都可以更灵活构建和控制自定义网格. Grid(网格) 布局使我们能够将网页分成具有简单属性的行和列.它还能使我们在不改变任何HTML的情况下 ...
- flex布局实例demo全解
上篇文章介绍了Flex布局的语法,今天介绍常见布局的Flex写法. 你会看到,不管是什么布局,Flex往往都可以几行命令搞定. 我只列出代码,详细的语法解释请查阅<Flex布局教程:语法篇> ...
- 小程序开发全栈1.2/3/4组件、flex布局、样式
1.2 组件 1.2.1 text组件 编写文本信息,类似于HTTP中的span 1.2.2 view组件 容器,类似于HTTP中的div 1.2.3 image组件 图片显示组件 1.3 页面fle ...
- es6 Object.assign ECMAScript 6 笔记(六) ECMAScript 6 笔记(一) react入门——慕课网笔记 jquery中动态新增的元素节点无法触发事件解决办法 响应式图像 弹窗细节 微信浏览器——返回操作 Float 的那些事 Flex布局 HTML5 data-* 自定义属性 参数传递的四种形式
es6 Object.assign 目录 一.基本用法 二.用途 1. 为对象添加属性 2. 为对象添加方法 3. 克隆对象 4. 合并多个对象 5. 为属性指定默认值 三.浏览器支持 ES6 O ...
- 在移动端中的flex布局
flex布局介绍: flex布局很灵活, 这种布局我们也可以称之为弹性布局, 弹性布局的主要优势就是元素的宽或者高会自动补全; flex布局实例: 比如有两个div,一个div的宽度为100px, ...
- FLEX布局的一些问题和解决方法
前言 露珠最近研究了一下flex的布局方式,发现项w3c推出的这套布局解决方案对于日益复杂的前端开发布局来说是确实是一利器,并且在不同的屏幕上实现了真正的响应式布局:不再单纯地依赖百分比和float的 ...
- [flex布局]-flex教程
简介:2009年,W3C提出了一种新的方案----Flex布局,可以简便.完整.响应式地实现各种页面布局.目前,它已经得到了所有浏览器的支持,这意味着,现在就能很安全地使用这项功能. Flex布局是什 ...
- flex 布局 初次接触这个好使又不是特别好用的布局方法
刚开始学前端的童鞋们应该也是一样先学习的table然后再学习了盒子模型,感觉终于学会了简单的网页布局,使用各种display,float,position绞尽脑汁给页面布局成自己想要的页面样式,然而, ...
随机推荐
- WPF 实现QQ抖动
//wpf中实现类似于qq的抖动窗效果 //前段页面 <Window x:Class="WpfApplication4.MainWindow" xmlns="htt ...
- EHCache 实现通用类 CacheManager
package com.zhubaje.api.workflow.ehcache; import java.io.Serializable; import java.util.ArrayList; i ...
- AJAX异步同步
为了更好的用户体验,AJAX的异步同步技术给了我们一个很好的用户体验下面是我做的一个例子. 1.客户端处理 UserId.HTML <!DOCTYPE html PUBLIC "-// ...
- Oracle 异常处理
1.什么是异常 在PL/SQL中的一个警告或错误的情形都可被称为异常.包括编译时错误(PLS)和运行时错误(ORA).一个异常通常包含一个错误代码和错误文本,分别指示异常的编号和具体错误信息. 异 ...
- 怎么删除有外键约束的MySQL表中的数据
SET FOREIGN_KEY_CHECKS = 0 操作结束后 SET FOREIGN_KEY_CHECKS = 1
- C语言基础:指针类型与指针和数组、字符串的关系
//指针变量就是用来存储地址的,只能存储地址 格式: int *p; 这个p为指针变量:指针变量占8个字节 类型是用来说明这个指针指向的类型: 比如上边的int代表这个指针变量会指向int类型的 ...
- c语言编程之循环队列
利用链表实现的循环队列,完成了队列的入队和出队,对于队空和队满用了一个flag进行标记.入队flag++,出队flag-- #include"stdio.h" typedef in ...
- android studio 不能在线更新android SDK Manager问题解决办法
Failed to fetch URL https://dl-ssl.google.com/android/repository/addons_list-2.xml, reason: Connecti ...
- 学习Linux第二天
1.Linux目录: 保存系统命令:根目录下的bin和sbin,usr下的bin和sbin /etc:保存配件 /usr:系统软件资源目录 /proc:系统内存分配目录,直接写入内存的 /var:保存 ...
- asp.net 中插入数据到access
这样报语法错误: insert into Menu_wx(userid,menutype,MenuID,menuname,MenuTitle,Url,Key,OrderValue,State) val ...