1. 什么是flex布局?
1.1 背景
Flexbox Layout (Flexible Box)模块(2017年10月W3C候选推荐)旨在提供一种更有效的方式来布局、对齐和分配容器中的项,即使它们的大小是未知的或者是动态的(因此单词“flex”)。
flex布局背后的主要思想是让容器能够改变其项的宽度/高度(和顺序),以最好地填充可用空间(主要是为了适应各种显示设备和屏幕大小)。
伸缩容器扩展项以填充可用的空闲空间,或收缩项以防止溢出。最重要的是,与常规布局(基于垂直的块和基于水平的内联)相比,flexbox布局是方向无关的。
虽然这些功能在页面上工作得很好,但它们缺乏支持大型或复杂应用程序的灵活性(特别是在改变方向、调整大小、拉伸、收缩等方面)。
注意:Flexbox布局最适合应用程序的组件和小规模布局,而网格布局则适合较大规模的布局。
2. 适用浏览器版本
2.1 已知问题
- Safari 10及更低版本使用min / max width / height声明来实际渲染flex项目的大小,但是在计算多行flex容器的一行中应该有多少项目时,它会忽略这些值。相反,它仅使用项目的flex-basis值,或者将flex基础设置为auto时使用其宽度。看到错误。在所有版本> 10中已修复。
- IE 11需要在第三个参数中添加一个单元,flex- base属性参见MSFT文档
- 在IE10和IE11中,如果容器有最小高度但没有显式的高度属性,那么带有display: flex和flex-direction: column的容器将不能正确计算其已弯曲的子容器的大小。看到错误。
- Firefox 51及以下版本的按钮元素不支持Flexbox。在版本52中修正。
- 在Safari 10.1及以下版本中,(非伸缩)子元素的高度不能以百分比表示。然而,其他浏览器根据百分比高度识别和缩放孩子。固定在所有版本>这个问题在Chrome中也出现过,但是在Chrome 51中得到了修复
- Flexbugs:社区策划的flexbox问题列表和跨浏览器解决方案
- 在IE10中,flex的默认值是0 0 auto,而不是最新规范中定义的0 1 auto。
- CSS方框对齐模块Level 3中所描述的justify-content属性的等间距值只有一些浏览器支持。
3. flex布局的基础讲解
3.1 父组件属性(flex容器)
3.1.1 display
这定义了一个flex容器;内联或块取决于给定的值。它为它的所有直接子元素启用flex上下文。
.container {
display: flex; /* or inline-flex */
}
// 注意CSS列对flex容器没有影响。
3.1.2 flex-direction
可以将flex项目看作主要以水平行或垂直列布局。
.container {
flex-direction: row | row-reverse | column | column-reverse;
}
- row (默认):在ltr中从左到右;在rtl中从右到左
- row-reverse:在ltr中从右到左;在rtl中从左到右
- column :与行相同,但从上到下
- column-reverse:与行反向相同,但从下到上
3.1.3 flex-wrap
默认情况下,flex项目都将试图适应一行。您可以对此进行更改,并允许项目根据需要使用此属性进行包装。
.container {
flex-wrap: nowrap | wrap | wrap-reverse;
}
- nowrap(默认):所有flex项目将在一行上
- wrap:伸缩项目将从上到下换行到多行。
- wrap-reverse:伸缩项目将从下到上缠绕到多行上。
3.1.4 flex-flow
这是flex-direction和flex-wrap属性的简写,它们一起定义了flex容器的主轴和交叉轴。默认值是row nowrap。
.container {
flex-flow: column wrap;
}
3.1.5 justify-content
这定义了沿主轴的对齐方式。当一行上的所有伸缩项都是不灵活的,或者是灵活的但已达到最大大小时,它有助于分配剩余的空闲空间。当项目溢出行时,它还对项目的对齐施加一些控制。
.container {
justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly | start | end | left | right ... + safe | unsafe;
}
- flex-start(默认):项目被打包到开始弹性的方向。
- flex-end:项目是包装接近结束的弹性方向。
- start:项目被打包到写入模式的开始方向。
- end:项目被打包到写入模式方向的末尾。
- left:项目被包装到容器的左边缘,除非这与弯曲方向没有意义,那么它的行为就像开始。
- right:项目被打包到容器的右边缘,除非这与弯曲方向没有意义,那么它的行为就像开始。
- center:项目沿直线居中
- space-between:项目在一行中均匀分布;第一项在起始行,最后一项在结束行
- space-around:物品均匀地分布在一行中,周围的空间相等。注意,视觉上的空间并不相等,因为所有的项目在两边都有相等的空间。第一项在容器边缘有一个单位的空间,但在下一项之间有两个单位的空间,因为下一项有自己的空间。
- space-evenly:项目的分布使任意两个项目之间的间距(以及到边缘的空间)相等。
- 请注意,浏览器对这些值的支持有细微差别。例如,空格在某些版本的Edge中还没有得到支持,开始/结束/左/右还没有在Chrome中。MDN有详细的图表。最安全的值是起始、结束和中心。
- 您还可以将另外两个关键字与这些值配对:安全和不安全。使用safe可以确保无论你如何进行这种类型的定位,你都不能将元素推到屏幕外(例如,推到顶部),这样内容就不能被滚动(称为“数据丢失”)。
3.1.6 align-items
这定义了flex项如何沿当前行的交叉轴布局的默认行为。可以将它看作是交叉轴(垂直于主轴)的正当内容版本。
.container {
align-items: stretch | flex-start | flex-end | center | baseline | first baseline | last baseline | start | end | self-start | self-end + ... safe | unsafe;
}
- stretch (默认):拉伸以填充容器(仍然尊重最小宽度/最大宽度)
- flex-start / start / self-start:项目被放置在交叉轴的起点。它们之间的区别是很微妙的,并且是关于服从弹性方向规则或书写模式规则的。
- flex-end / end / self-end:项目被放置在交叉轴的末端。区别还是很微妙的,是关于弹性方向规则和书写模式规则的。
- center:项目在交叉轴居中
- baseline:条目被对齐,就像它们的基线对齐一样
- 安全和不安全的修饰语关键字可以与这些关键字一起使用(尽管注意浏览器支持),并帮助您防止对齐元素使内容变得不可访问。
3.1.7 align-content
当交叉轴中有额外空间时,这将对齐flex容器中的行,类似于正当内容对齐主轴中的各个项。
注意:当只有一行伸缩项目时,此属性不起作用。
.container {
align-content: flex-start | flex-end | center | space-between | space-around | space-evenly | stretch | start | end | baseline | first baseline | last baseline + ... safe | unsafe;
}
- flex-start / start:打包到容器开始处的物品。(更受支持的)flex-start支持flex方向,而start支持写入模式方向。
- flex-end:包装到容器末端的物品。(更多支持)flex-end支持flex方向,而end支持写入模式方向。
- center:在容器中居中的项目
- space-between:物品均匀分布;第一行在容器的开头,最后一行在末尾
- space-around:项目在每行周围以相等的空间均匀分布
- space-evenly:项目被均匀地分布,周围有相等的空间
- stretch(默认):行拉伸以占据剩余的空间
- safe 和unsafe的修饰语关键字可以与这些关键字一起使用(尽管注意浏览器支持),并帮助您防止对齐元素使内容变得不可访问。
3.2 子属性(flex子元素)
3.2.1 order
默认情况下,flex项按源顺序排列。但是,order属性控制它们在flex容器中出现的顺序。
.item {
order: 5; /* 默认是 0 */
}
3.2.2 flex-grow
这定义了flex项在必要时增长的能力。它接受一个作为比例的无单位值。它规定项目应该在伸缩容器中占用多少可用空间。
如果所有项目都将flex-grow设置为1,那么容器中的剩余空间将平均分配给所有子元素。如果其中一个子节点的值为2,那么剩余的空间将占其他节点空间的两倍(或者至少会尝试这样做)。
.item {
flex-grow: 4; /* default 0 */
}
负数是无效的。
3.2.3 flex-shrink
这定义了伸缩项目在必要时收缩的能力。
.item {
flex-shrink: 3; /* default 1 */
}
负数是无效的。
3.2.4 flex-basis
这定义了在分配剩余空间之前元素的默认大小。它可以是一个长度(例如20%,5rem,等等)或一个关键字。auto关键字的意思是“看看我的宽度或高度属性”(这是临时做的主大小关键字,直到不赞成)。content关键字的意思是“根据条目的内容来确定大小”——这个关键字还没有得到很好的支持,所以很难测试,也很难知道它的兄弟——最大内容、最小内容和适配内容是做什么的。
.item {
flex-basis: | auto; /* default auto */
}
如果设置为0,则不会考虑内容周围的额外空间。如果设置为auto,额外的空间将根据其flex-grow值分布。看到这个图形。
3.2.5 flex
这是flex-grow、flex-shrink和flex- base组合的简写。第二个和第三个参数(flex-shrink和flex- base)是可选的。默认值是0 1 auto,但如果您使用单个数字值设置它,它就像10。
.item {
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}
建议您使用这个快捷的属性,而不是设置单独的属性。速记法巧妙地设置了其他值。
3.2.6 align-self
这允许为单个flex项覆盖默认对齐(或由对齐项指定的对齐)。
.item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
注意,浮动、清除和垂直对齐对伸缩项目没有影响。
4.flex布局小案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
html,
body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
/* 定义flex布局 */
display: flex;
/* 这是flex-direction和flex-wrap属性的简写,它们一起定义了flex容器的主轴和交叉轴。默认值是row nowrap。 */
flex-flow: column wrap;
}
header {
width: 100%;
height: 20%;
/* 定义flex布局 */
display: flex;
/* x轴居中对齐 */
justify-content: center;
/* y轴底端对齐 */
align-items: flex-end;
background-color: blue;
}
header nav {
/* 定义flex布局 */
display: flex;
}
header nav div {
color: #fff;
margin: 0 15px;
padding: 10px 0;
}
section {
width: 100%;
height: 70%;
/* 定义flex布局 */
display: flex;
}
section div {
/* 这是flex-grow、flex-shrink和flex- base组合的简写,占比重值为1 */
flex: 1;
/* 定义flex布局 */
display: flex;
/* x轴居中对齐 */
justify-content: center;
/* y轴垂直对齐 */
align-items: center;
}
section div:nth-child(1) {
background-color: red;
}
section div:nth-child(2) {
/* 这是flex-grow、flex-shrink和flex- base组合的简写,占比重值为2 */
flex: 2;
background-color: rgb(207, 5, 5);
}
section div:nth-child(3) {
background-color: red;
}
footer {
width: 100%;
height: 10%;
background-color: yellow;
/* 定义flex布局 */
display: flex;
/* x轴居中对齐 */
justify-content: center;
/* y轴垂直对齐 */
align-items: center;
}
</style>
</head>
<body>
<header>
<nav>
<div>主页</div>
<div>公司产品</div>
<div>关注我们</div>
<div>加入我们</div>
<div>关于我们</div>
</nav>
</header>
<section>
<div>1</div>
<div>2</div>
<div>1</div>
</section>
<footer>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</footer>
</body>
</html>