块布局:呈现文档的布局模式。
行内布局:呈现文本的布局模式。
表格布局:用表格呈现2D数据的布局模式。
定位布局:能够直接地定位元素的布局模式,定位元素奴基本与其他元素没有任何关系。
CSS3引入的flex布局,主要思想是让容器有能力控制子项目的高度,宽度(设置顺序)。以最佳方式填充可用空间(主要是为了适应所有类型的显示设备和屏幕大小)。flex容器会使子项目扩展来填满可用空间,或者缩小以防止溢出容器。
最重要的是flex布局方向不可预知,不像常规的布局(块就是从上到下,内联就是从左到右),常规布局适合页面布局,但是对于支持大型或者复杂的应用程序(特别是涉及方向布局方向的改变,缩放或者收缩)就缺乏灵性。
flex的模型规范状态
我们可以使用的具体属性值来判断当前使用的flex的版本。旧版本(Old: 2009)使用display:box或者display:inline-box。
混合版本(Hybrid: 2011)使用display:flexbox或者display:inline-flexbox。
最新版本(Modern 2012) 使用display:flex或者inline-flex。
最新版本的浏览器的兼容性
详情可以访问flex的兼容性
这里兼容性的主要问题是IE,IE10需要使用-ms-。至于IE8和IE9的兼容性,需要使用flex.js。
新版本flex模型的基本使用
本文主要是学习最新版本的flex模型。学习之前还是了解基本知识。
flex模型中的术语
主轴和侧轴
- 主轴(main axis):Flex容器的主轴主要用来配置Flex项目。注意,它不一定是水平,这主要取决于flex-direction属性。
- 主轴开始(main-start) | 主轴结束(main-end):Flex项目的配置从容器的主轴起点边开始,往主轴终点边结束。
- 主轴长度(main size):Flex项目的在主轴方向的宽度或高度就是项目的主轴长度,Flex项目的主轴长度属性是width或height属性,由哪一个对着主轴方向决定。
- 侧轴(cross axis):与主轴垂直的轴称作侧轴,是侧轴方向的延伸。
- 侧轴开始(cross-start) | 策州结束(cross-end):伸缩行的配置从容器的侧轴起点边开始,往侧轴终点边结束。
- 侧轴长度(cross size):Flex项目的在侧轴方向的宽度或高度就是项目的侧轴长度,Flex项目的侧轴长度属性是width或height属性,由哪一个对着侧轴方向决定。
伸缩容器和伸缩项目
- 通过display显示地给一个元素设置为flex或者inline-flex,这个容器就是一个伸缩容器。伸缩容器回为其内容创建新的伸缩格式话上下文,其中设置为flex的容器被渲染为一个块级元素,二设置为inline-flex的容器被渲染为一个行内元素。
- 元素display为inline-flex且元素是一个浮动或者绝对定位,则display的计算值是flex。
- 一个伸缩容器的每一个子元素都会成为一个伸缩项目
flex模型的功能
- 屏幕和浏览器窗口大小发生改变也可以灵活调整布局。
- 指定伸缩项目沿着主轴或者侧轴按比例分配额外空间(伸缩容器额外空间),从而调整伸缩项目的大小。
- 指定伸缩项目沿着主轴或者侧轴将伸缩容器额外空间,分配到伸缩项目之前,之后或者之间。
- 指定如何将垂直于元素布局轴的额外空间分配到该元素的周围。
- 控制元素在页面上的布局方向
- 按照不同与文档对象模型(DOM)所指定排序方式对屏幕上的元素重新排序。
- 设为Flex布局以后,子元素的float、clear和vertical-align属性将失效。
伸缩容器的属性
简单的flex例子<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
div {
border: 2px solid black;
border-radius: 5px;
}
.parent-flex {
width: 800px;
height: 400px;
background-color: rgb(250,234,202);
display: flex;
flex-direction: row;
}
.child-flex {
width: 200px;
height: 200px;
background-color: rgb(203,234,253);
}
</style>
</head>
<body>
<div class="parent-flex">
<div class="child-flex">
flex item1
</div>
<div class="child-flex">
flex item2
</div>
<div class="child-flex">
flex item3
</div>
</div>
</body>
</html>
当在父元素加上display:flex之后,内部子元素变成了如图的样子,自动排列起来。
伸缩流方向flex-direction
伸缩器容器的主轴方向,其决定了伸缩项目放置在伸缩容器的方向。伸缩流方向通过flex-direction属性来设置,其默认值为row。flex-direction: row | row-reverse | column | column-reverse;
- row(默认值):主轴为水平方向,起点在左端。
- row-reverse:主轴为水平方向,起点在右端。
- column:主轴为垂直方向,起点在上沿。
- column-reverse:主轴为垂直方向,起点在下沿。
测试上面的例子:修改为row-reverse
.parent-flex {
width: 800px;
height: 400px;
background-color: rgb(250,234,202);
display: flex;
flex-direction: row-reverse;
}
伸缩行换行flex-wrap
默认情况下,子元素项目都排在一条线。但是许多情况下子元素的排列不仅一行。在伸缩容器中有一个伸缩换行属性,主要用来设置伸缩容器的伸缩项目是当行还是多行显示,以及决定侧轴的方向。flex-wrap: nowrap | wrap | wrap-reverse;
- nowrap(默认):不换行。
- wrap:换行,第一行在上方。
- wrap-reverse:换行,第一行在下方。
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
div {
border: 2px solid black;
border-radius: 5px;
}
.parent-flex {
width: 800px;
height: 400px;
background-color: rgb(250,234,202);
display: flex;
flex-direction: row;
}
.child-flex {
width: 200px;
height: 200px;
background-color: rgb(203,234,253);
}
</style>
</head>
<body>
<div class="parent-flex">
<div class="child-flex">
flex item1
</div>
<div class="child-flex">
flex item2
</div>
<div class="child-flex">
flex item3
</div>
<div class="child-flex">
flex item4
</div>
<div class="child-flex">
flex item5
</div>
</div>
</body>
</html>
上面的例子:我又添加了两个div子元素,这种情况下,父元素的宽度不够渲染所有的子元素。我们先来看一下,当前情况下子元素会如何渲染。
我们可以看到flex将子元素的宽度自适应充满当前父元素的宽度。目前我们可以先不理会这种显示的原因。只需要记得当前的页面展示。然后修改父元素如下:
.parent-flex {
width: 800px;
height: 400px;
background-color: rgb(250,234,202);
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
伸缩方向与换行flex-flow
伸缩流方向与伸缩换行的结合物。也就是说flex-flow同时设定了flex-direction和flex-wrap两个属性,也就是这两个属性的缩写,决定了伸缩容器的主轴和侧轴。
flex-flow: <flex-direction> <flex-wrap>;
测试,使用flex-flow实现上面flex-flow的测试例子效果。.parent-flex {
width: 800px;
height: 400px;
background-color: rgb(250,234,202);
display: flex;
flex-flow:wrap row ;
}
主轴对齐方式justify-content
用来设置伸缩容器内当前伸缩项目在主轴方向的对齐方式,指定如何在伸缩项目之间分布伸缩容器额外空间。当伸缩项目溢出某一行时,这一属性也会在项目的对以上增加一些控制。
justify-content: flex-start | flex-end | center | space-between | space-around;- flex-start(默认值):左对齐
- flex-end:右对齐
- center: 居中
- space-between:两端对齐,项目之间的间隔都相等。
- space-around:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
div {
border: 2px solid black;
border-radius: 5px;
}
.child-flex {
width: 200px;
height: 100px;
background-color: rgb(203,234,253);
}
.parent {
width: 800px;
background-color: rgb(250,234,202);
display: flex;
}
.flex-start {
justify-content: flex-start;
}
.flex-end {
justify-content: flex-end;
}
.flex-center {
justify-content: center;
}
.flex-space-between {
justify-content: space-between;
}
.flex-space-around {
justify-content: space-around;
}
</style>
</head>
<body>
<div class="flex-start parent">
<div class="child-flex">
flex-start
</div>
<div class="child-flex">
flex-start
</div>
<div class="child-flex">
flex-start
</div>
</div>
<br />
<div class="flex-end parent">
<div class="child-flex">
flex-end
</div>
<div class="child-flex">
flex-end
</div>
<div class="child-flex">
flex-end
</div>
</div>
<br />
<div class="flex-center parent">
<div class="child-flex">
center
</div>
<div class="child-flex">
center
</div>
<div class="child-flex">
center
</div>
</div>
<br />
<div class="flex-space-between parent">
<div class="child-flex">
space-between
</div>
<div class="child-flex">
space-between
</div>
<div class="child-flex">
space-between
</div>
</div>
<br />
<div class="flex-space-around parent">
<div class="child-flex">
space-around
</div>
<div class="child-flex">
space-around
</div>
<div class="child-flex">
space-around
</div>
</div>
</body>
</html>
侧轴对齐方式align-items
文章开头说过flex布局的主轴方向和侧轴方向,justify-content说的是主轴,align-items则是侧轴。如文字描述,侧轴对齐方式说的是侧轴方向对齐方式。<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
div {
border: 2px solid black;
border-radius: 5px;
}
.child-flex {
width: 200px;
height: 100px;
background-color: rgb(203,234,253);
}
.parent {
width: 800px;
height: 600px;
background-color: rgb(250,234,202);
display: flex;
}
.flex-space-around {
justify-content: space-around;
}
</style>
</head>
<body>
<div class="flex-space-around parent">
<div class="child-flex">
space-around
</div>
<div class="child-flex">
space-around
</div>
<div class="child-flex">
space-around
</div>
</div>
</body>
</html>
如图,可以看到当前三个div元素按照space-around主轴对齐,但是我们想一下侧轴,此时以侧轴方向来说可以看到div元素位置在上边框位置。我们可以通过align-content来进行侧轴方向的位置布局。
.flex-space-around {
justify-content: space-around;
align-items:center;
}
align-items: flex-start | flex-end | center | baseline | stretch;
- flex-start:交叉轴的起点对齐。
- flex-end:交叉轴的终点对齐。
- center:交叉轴的中点对齐。
- baseline: 项目的第一行文字的基线对齐。
- stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。
堆栈轴对齐align-content
align-content属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。
align-content: flex-start | flex-end | center | space-between | space-around | stretch;- flex-start:与交叉轴的起点对齐。
- flex-end:与交叉轴的终点对齐。
- center:与交叉轴的中点对齐。
- space-between:与交叉轴两端对齐,轴线之间的间隔平均分布。
- space-around:每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。
- stretch(默认值):轴线占满整个交叉轴。
理解这个属性的还是需要flex-wrap。
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
div {
border: 2px solid black;
border-radius: 5px;
}
.child-flex {
width: 200px;
height: 100px;
background-color: rgb(203,234,253);
}
.parent {
width: 800px;
height: 600px;
background-color: rgb(250,234,202);
display: flex;
}
.flex-space-around {
justify-content: space-around;
flex-wrap: wrap;
}
</style>
</head>
<body>
<div class="flex-space-around parent">
<div class="child-flex">
space-around
</div>
<div class="child-flex">
space-around
</div>
<div class="child-flex">
space-around
</div>
<div class="child-flex">
space-around
</div>
<div class="child-flex">
space-around
</div>
</div>
</body>
</html>
现在我们使用align-item和align-content的作用效果。
.flex-space-around {
justify-content: space-around;
flex-wrap: wrap;
align-items: :center;
}
.flex-space-around {
justify-content: space-around;
flex-wrap: wrap;
align-content: center;
}
伸缩项目的属性
一个伸缩容器项目是一个伸缩容器的子元素。伸缩容器的文本也是被认为是一个伸缩项目。伸缩项目中内容与普通流一样。伸缩项目都有一个主轴长度和一个侧轴长度。主轴长度是伸缩项目在主轴上的尺寸,侧轴长度是伸缩项目在侧轴上的尺寸。
默认情况下侧轴长度和父元素的侧轴的长度相同。之前说到的align-items: stretch已经说过。
显示顺序order
伸缩容器中的伸缩项目默认显示顺序是遵守文档在源码中出现的先后顺序。我们可以通过伸缩项目的显示顺序修改伸缩项目在页面中的显示顺序。
order属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。
order: <integer>;
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
div {
border: 2px solid black;
border-radius: 5px;
}
.child-flex {
width: 200px;
background-color: rgb(203,234,253);
display: flex;
justify-content: center;
align-items: center;
}
.parent {
width: 800px;
height: 600px;
background-color: rgb(250,234,202);
display: flex;
}
</style>
</head>
<body>
<div class="flex-space-around parent">
<div class="child-flex">
1
</div>
<div class="child-flex">
2
</div>
<div class="child-flex">
3
</div>
</div>
</body>
</html>
接下来我们使用order将顺序改为213.
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
div {
border: 2px solid black;
border-radius: 5px;
}
.child-flex {
width: 200px;
background-color: rgb(203,234,253);
display: flex;
justify-content: center;
align-items: center;
}
.child-flex:nth-child(1) {
order: 1;
}
.child-flex:nth-child(3) {
order: 2;
}
.parent {
width: 800px;
height: 600px;
background-color: rgb(250,234,202);
display: flex;
}
</style>
</head>
<body>
<div class="flex-space-around parent">
<div class="child-flex">
1
</div>
<div class="child-flex">
2
</div>
<div class="child-flex">
3
</div>
</div>
</body>
</html>
侧轴对齐align-self
align-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。
align-self: auto | flex-start | flex-end | center | baseline | stretch;
- 该属性可能取6个值,除了auto,其他都与align-items属性完全一致。
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
div {
border: 2px solid black;
border-radius: 5px;
}
.child-flex {
width: 200px;
height: 100px;
background-color: rgb(203,234,253);
display: flex;
justify-content: center;
align-items: center;
}
.child-flex:nth-child(3) {
align-self: center;
}
.parent {
width: 800px;
height: 600px;
background-color: rgb(250,234,202);
display: flex;
}
</style>
</head>
<body>
<div class="flex-space-around parent">
<div class="child-flex">
1
</div>
<div class="child-flex">
2
</div>
<div class="child-flex">
3
</div>
</div>
</body>
</html>
放大属性flex-grow
flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。
flex-grow: <number>; /* default 0 */
我们还用上面的例子,只是修改下面的css
.child-flex:nth-child(3) {
flex-grow: 1;
}
如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。
伸缩项目的放大属性是需要根据空余空间来决定的。下面的例子将所有的子元素都扩大一倍。
.child-flex {
width: 200px;
height: 100px;
background-color: rgb(203,234,253);
display: flex;
justify-content: center;
align-items: center;
flex-grow: 1;
}
可以看到大家平分了空余空间。注意这里的放大并不是相对伸缩项目的,而是针对空余空间的。
缩小属性flex-shrink
flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
flex-shrink: <number>; /* default 1 */
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
div {
border: 2px solid black;
border-radius: 5px;
}
.child-flex {
width: 200px;
height: 100px;
background-color: rgb(203,234,253);
display: flex;
justify-content: center;
align-items: center;
}
.child-flex:nth-child(1) {
flex-shrink: 0;
}
.child-flex:nth-child(2) {
flex-shrink: 1;
}
.child-flex:nth-child(3) {
flex-shrink: 1;
}
.parent {
height: 600px;
background-color: rgb(250,234,202);
display: flex;
}
</style>
</head>
<body>
<div class="flex-space-around parent">
<div class="child-flex">
1
</div>
<div class="child-flex">
2
</div>
<div class="child-flex">
3
</div>
</div>
</body>
</html>
如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。负值对该属性无效。
flex-basis属性
flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。
flex-basis: <length> | auto; /* default auto */
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
div {
border: 2px solid black;
border-radius: 5px;
}
.child-flex {
width: 200px;
height: 100px;
background-color: rgb(203,234,253);
display: flex;
justify-content: center;
align-items: center;
}
.child-flex:nth-child(1) {
flex-basis: 300px;
}
.parent {
height: 600px;
background-color: rgb(250,234,202);
display: flex;
}
</style>
</head>
<body>
<div class="flex-space-around parent">
<div class="child-flex">
1
</div>
<div class="child-flex">
2
</div>
<div class="child-flex">
3
</div>
</div>
</body>
</html>
当前例子的第一个子元素宽为200px,flex-basis:300px。可以看到flex-basis的优先级高于width。
flex属性
flex属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。
.item {
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}
理解flex
为什么要理解flex,因为个人认为很有必要。
树立一个概念:flex默认情况一条横轴一条侧轴
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
div {
border: 2px solid black;
border-radius: 5px;
}
.child-flex {
background-color: rgb(203,234,253);
}
.parent {
height: 600px;
background-color: rgb(250,234,202);
display: flex;
}
.flex-space-around {
}
</style>
</head>
<body>
<div class="flex-space-around parent">
<div class="child-flex">
space-around
</div>
<div class="child-flex">
space-around
</div>
<div class="child-flex">
space-around
</div>
<div class="child-flex">
space-around
</div>
<div class="child-flex">
space-around
</div>
<div class="child-flex">
space-around
</div>
</div>
</body>
</html>
如图,子元素没有设置高度和宽度。可以看到,子元素自动充满侧轴的方向,宽度是文字充满的宽度。这里我们需要定义的是默认flex的布局为一条主轴一条侧轴。可能你会说没有两条主轴是因为你横轴的宽度没有超过父元素的宽度。继续看一个例子:
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
div {
border: 2px solid black;
border-radius: 5px;
}
.child-flex {
width: 200px;
background-color: rgb(203,234,253);
}
.parent {
width: 800px;
height: 600px;
background-color: rgb(250,234,202);
display: flex;
}
</style>
</head>
<body>
<div class="flex-space-around parent">
<div class="child-flex">
space-around
</div>
<div class="child-flex">
space-around
</div>
<div class="child-flex">
space-around
</div>
<div class="child-flex">
space-around
</div>
<div class="child-flex">
space-around
</div>
</div>
</body>
</html>
这个例子中我们设置了父元素宽度800px,子元素为200px。我们再看当前的页面展示:
可以看到flex自动将子元素的宽度设置为160px。这也更加说明了默认情况一条横轴一条侧轴。除非是我们加上flex-wrap去定义一条主线排不下,可以换行。我们继续上面的例子:
.parent {
width: 800px;
height: 600px;
background-color: rgb(250,234,202);
display: flex;
flex-wrap: wrap;
}
这是我们设置flex-wrap的情况下看到的结果,可以看到高度也已经felx处理了。
屏幕和浏览器窗口大小发生改变也可以灵活调整布局
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
div {
border: 2px solid black;
border-radius: 5px;
}
.child-flex {
width: 200px;
background-color: rgb(203,234,253);
}
.parent {
width: 800px;
height: 600px;
background-color: rgb(250,234,202);
display: flex;
flex-wrap: wrap;
}
</style>
</head>
<body>
<div class="flex-space-around parent">
<div class="child-flex">
space-around
</div>
<div class="child-flex">
space-around
</div>
<div class="child-flex">
space-around
</div>
<div class="child-flex">
space-around
</div>
<div class="child-flex">
space-around
</div>
</div>
</body>
</html>
灵活的布局指的是什么呢?
我的理解是flex可以我们的设置自动修改子元素的属性去友好的展示在父元素的内部(个人理解)。设为Flex布局以后,子元素的float、clear和vertical-align属性将失效
个人理解:在原先的布局方式中,float的存在是为了可以自由的控制div的位置。但是现在flex可以实现float的效果。举个例子,父元素中需要将三个div,前面两个放在一起靠在左侧,另一个div需要仅靠在右侧。猛一看好像实现不了。但是felx是可以实现的。
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
div {
border: 2px solid black;
border-radius: 5px;
}
.child-flex {
width: 200px;
height: 100px;
background-color: rgb(203,234,253);
display: flex;
justify-content: center;
align-items: center;
}
.parent {
height: 600px;
background-color: rgb(250,234,202);
display: flex;
justify-content: space-between;
}
</style>
</head>
<body>
<div class="flex-space-around parent">
<div class="child-flex">
<div class="child-flex">
1
</div>
<div class="child-flex">
2
</div>
</div>
<div class="child-flex">
3
</div>
</div>
</body>
</html>
第三个vertical-align的属性可以依靠align-items实现。