弹性布局
了解弹性
flex是flexible box的缩写,意思是弹性布局,可以轻松控制元素排列、对齐和顺序的控制。
现在的终端类型非常多,使用弹性盒模型可以让元素在不同尺寸终端控制尺寸。
display:flex
响应体验
<style>
* {
padding: 0;
margin: 0;
}
div.container {
display: flex;
height: 100vh;
justify-content: space-evenly;
}
div.container div {
border: solid 1px #ddd;
}
div.container div:nth-of-type(1) {
min-width: 80px;
background: #4E9166;
}
div.container div:nth-of-type(2) {
flex: 1;
background: #ddd;
}
</style>
...
<div class="container">
<div></div>
<div></div>
</div>
布局对比
传统布局
<style>
* {
padding: 0;
margin: 0;
}
main,
footer {
border: solid 1px #ddd;
box-sizing: border-box;
}
main {
background: #ddd;
height: 100vh;
padding-bottom: 55px;
background-clip: content-box;
}
footer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 50px;
}
footer div {
width: 33%;
float: left;
text-align: center;
line-height: 3em;
height: 100%;
background: linear-gradient(to bottom, #f3f3f3, #eee, #f3f3f3);
cursor: pointer;
}
footer div:nth-child(n+2) {
border-left: solid 1px #ddd;
}
</style>
...
<body>
<main></main>
<footer>
<div>1</div>
<div>2</div>
<div>3</div>
</footer>
</body>
弹性布局
<style>
* {
padding: 0;
margin: 0;
}
body {
display: flex;
flex-direction: column;
height: 100vh;
}
main {
border: solid 1px #ddd;
background: #ddd;
background-clip: content-box;
margin-bottom: 5px;
flex: 1;
}
footer {
flex: 0;
display: flex;
justify-content: space-evenly;
border-top: solid 1px #ddd;
min-height: 50px;
}
footer div {
flex: 1;
text-align: center;
line-height: 3em;
background: linear-gradient(to bottom, #f3f3f3, #eee, #f3f3f3);
cursor: pointer;
}
footer div:nth-child(n+2) {
border-left: solid 1px #ddd;
}
</style>
...
<body>
<main></main>
<footer>
<div>1</div>
<div>2</div>
<div>3</div>
</footer>
</body>
弹性盒子
声明定义
容器盒子里面包含着容器元素,使用display:flex
或者display:inline-flex
声明为弹性盒子。
声明块级弹性盒子
<style>
* {
padding: 0;
margin: 0;
}
article {
height: 150px;
margin-left: 100px;
margin-top: 100px;
outline: solid 5px silver;
display: flex;
padding: 20px;
}
article div {
outline: solid 5px blueviolet;
text-align: center;
font-size: 28px;
line-height: 5em;
width: 300px;
}
</style>
...
<article>
<div>1</div>
<div>2</div>
<div>3</div>
</article>
声明内联级弹性盒子
<style>
...
article {
...
display: inline-flex;
...
}
...
</style>
控制盒子元素排列方向
flex-direction
值 | 描述 |
---|---|
row | 从左到右排列元素(默认值) |
row-reverse | 从右到左排列元素 |
column | 从上到下垂直排列到元素 |
column-reverse | 从下到上垂直排列到元素 |
flex-direction: row
flex-direction:row-reverse
flex-direction: column
flex-direction:column-reverse
规定flex
容器是单行还是多行,同时横轴的方向决定了新行堆叠的方向。
flex-wrap
选项 | 说明 |
---|---|
nowrap | 元素不拆行或不拆列(默认值) |
wrap | 容器元素在必要的时候拆行或拆列 |
wrap-reverse | 容器元素在必要的时候拆行或拆列,但是以相反的顺序。 |
行元素换行
flex-direction:row;
flex-wrap:wrap;
水平排列反向换行
flex-direction:row;
flex-wrap:wrap-reverse;
垂直元素换行
flex-direction: column;
flex-wrap: wrap;
垂直元素反向换行
flex-direction: column;
flex-wrap: wrap-reverse;
flex-flow
flex=flow
是flex-direction
和flex-wrap
的组合简写模式,下买呢是从右到左排列,换行向上拆分行,
flex-flow: row-reverse wrap-reverse;
轴说明
水平排列
flex-flow: row wrap
主轴是从左到右,交叉轴是从上到下。
flex-flow: row-reverse wrap-reverse
主轴是从右到左,交叉轴是从下到上。
垂直排列
flex-flow:column wrap
主轴是下方从左到右,交叉轴是从中间到上到下。
控制元素主轴排列方式
justify-content
选项 | 说明 |
---|---|
flex-start | 元素紧靠主轴起点 |
flex-end | 元素紧靠主轴终点 |
center | 元素从弹性容器中心开始 |
space-between | 第一个元素靠起点,最后一个元素靠终点,余下元素平均分配空间。 |
space-around | 每个元素两侧的间隔相等,所以元素之间的间隔比元素与容器的边距间隔大一倍。 |
space-evenly | 元素间距离平均分配 |
水平排列元素
对齐主轴终点
justify-content:flex-end;
平均分配容器元素
justify-content:space-evenly;
垂直排列
对齐主轴终点
justify-content:flex-end;
交叉轴行
元素在交叉轴上有行的概念。理解这个概念对理解align-items
和align-content
有更好的帮助。
- align-item是控制元素在行上的排列
- Align-content是控制行在交叉轴上的排列
align-items
用于控制容器元素在交叉轴上的排列方式
选项 | 说明 |
---|---|
stretch | 元素被拉伸以适应容器(默认值) |
center | 元素位于容器的中心 |
flex-start | 元素位于容器的交叉轴开头 |
flex-end | 元素位于容器的交叉轴结尾 |
拉伸适应交叉轴
如果设置了width|height|min-height|min-width|max-width|max-height
,将影响stretch
的结果。因为stretch
优先级于宽高设置。
align-items: stretch;
对齐到交叉轴的顶部
flex-direction: row;
align-items: flex-start;
对齐到交叉轴的底部
flex-direction: row;
align-items: flex-end;
对齐到交叉轴中心
flex-direction: row;
align-items: center;
纵向排列时交叉轴排列
display: flex;
flex-direction: column;
align-items: center;
align-content
只适用于多行显示的弹性容器,用于控制行(而不是元素)在交叉轴上的排列方式。
选项 | 说明 |
---|---|
stretch | 将空间平均分配给元素 |
flex-start | 元素紧靠主轴起点 |
flex-end | 元素紧靠主轴终点 |
center | 元素从弹性容器中心开始 |
space-between | 第一个元素靠起点,最后一个元素靠终点,余下元素平均分配空间 |
space-around | 每个元素两侧的间隔相等。所以项目之间的间隔比项目与边框的间隔大一倍 |
space-evenly | 元素间距离平均分配 |
水平排列在交叉轴中居中排列
align-content: center;
垂直排列在交叉轴的排列
display: flex;
flex-direction: column;
flex-wrap: wrap;
align-items: flex-start;
align-content:center;
弹性元素
放在容器盒子中的元素即为容器元素
- 不能使用float与clear规则
- 弹性元素均为块元素
- 绝对定位的弹性元素不参与弹性布局
align-self
用于控制单个元素在交叉轴上的排列方式,align-items
用于控制容器中所有元素的排列。而align-slef
用于控制一个弹性元素的交叉轴排列。
选项 | 说明 |
---|---|
stretch | 将空间平均分配给元素 |
flex-start | 元素紧靠主轴起点 |
flex-end | 元素紧靠主轴终点 |
center | 元素从弹性容器中心开始 |
align-self: stretch;
align-self: flex-start;
align-self: flex-end;
align-self: center;
flex-grow
用于将弹性盒子的可用空间,分配给弹性元素。可以使用整数或小数声明。
flex-grow: 1;
flex-grow: 1.5;
如果弹性元素设置了宽度,将把(弹性盒子-弹性元素宽度和)后按照flex-grow
进行分配。
<style>
* {
padding: 0;
margin: 0;
padding: 10px;
margin: 5px;
}
article {
width: 600px;
position: relative;
height: 200px;
border: solid 5px silver;
display: flex;
}
article div {
min-height: 80px;
border: solid 5px blueviolet;
text-align: center;
font-size: 28px;
}
article div:nth-of-type(1) {
width: 100px;
flex-grow: 1;
}
article div:nth-of-type(2) {
width: 100px;
flex-grow: 3;
}
article div:nth-of-type(3) {
width: 300px;
flex-grow: 6;
}
</style>
...
flex-shrink
与flex-grow
相反flex-shrink
是在弹性盒子装不下元素时定义的缩小值。
<style>
* {
padding: 0;
margin: 0;
}
body {
padding-left: 50px;
padding-top: 15px;
}
article {
border: solid 5px silver;
width: 400px;
height: 120px;
display: flex;
padding: 10px;
box-sizing: content-box;
}
article div:nth-child(1) {
flex-shrink: 0;
}
article div:nth-child(2) {
flex-shrink: 1;
}
article div:nth-child(3) {
flex-shrink: 3;
}
article * {
width: 200px;
height: 100px;
overflow: hidden;
background: blueviolet;
background-clip: content-box;
padding: 10px;
border: solid 1px blueviolet;
box-sizing: border-box;
font-size: 30px;
color: white;
}
</style>
<article>
<div>1</div>
<div>2</div>
<div>3</div>
</article>
flex-basis
flex-basis 属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。
可以是长度单位,也可以是百分比。flex-basis
的优先级高于width、height
属性。
优先级
flex-basis 优先级大于 width、height。
<style>
* {
padding: 0;
margin: 0;
}
article {
width: 600px;
position: relative;
height: 150px;
margin-left: 100px;
margin-top: 100px;
outline: solid 5px silver;
display: flex;
padding: 20px;
}
article div {
outline: solid 5px blueviolet;
text-align: center;
font-size: 28px;
line-height: 5em;
}
article div:nth-of-type(1) {
flex-basis: 100px;
width: 200px;
}
article div:nth-of-type(2) {
flex-basis: 200px;
}
article div:nth-of-type(3) {
flex-basis: 200px;
}
</style>
...
<article>
<div>1</div>
<div>2</div>
<div>3</div>
</article>
flex
flex是flex-grow|lex-shrink|flex-basis
缩写组合
下例定义平均分配剩余空间,并不进行尺寸缩小,基础尺寸为200px
* {
padding: 0;
margin: 0;
}
article {
width: 600px;
position: relative;
height: 150px;
margin-left: 100px;
margin-top: 100px;
outline: solid 5px silver;
display: flex;
padding: 20px;
}
article div {
outline: solid 5px blueviolet;
text-align: center;
font-size: 28px;
line-height: 5em;
flex: 1 0 100px;
}
order
用于控制弹性元素的位置,默认为 order:0
数值越小越在前面,可以负数或整数。
下面是通过 J 动态改变 order 属性产生移动效果,因为本章节是讲 CSS 所以 JS 功能没有完善,只是体验一下 order。
<style>
* {
padding: 0;
margin: 0;
}
body {
padding-left: 50px;
padding-top: 15px;
}
article {
border: solid 5px silver;
width: 400px;
height: 400px;
padding: 10px;
display: flex;
flex-direction: column;
}
article section {
order: 1;
flex: 1 0 100px;
padding: 10px;
background: blueviolet;
background-clip: content-box;
display: flex;
flex-direction: column;
text-align: center;
color: white;
}
article section div {
flex: 1;
}
article section div {
display: flex;
flex-direction: column;
justify-content: center;
}
article section span {
flex: 0;
background: #000;
padding: 20px;
cursor: pointer;
}
</style>
<article>
<section>
<div>theliuwei.com</div>
<span onclick="up(this)">up</span>
</section>
<section>
<div>theliuwei.com</div>
<span onclick="up(this)">up</span>
</section>
</article>
<script>
function up(el) {
el.parentElement.style.order = getOrder(el.parentElement) * 1 - 1;
console.log(getOrder(el.parentElement))
}
function getOrder(el) {
return getComputedStyle(el, null).order;
}
</script>
弹性文本
文本节点也在弹性布局操作范围内
<style>
article {
display: flex;
flex-direction: row;
justify-content: space-between;
height: 100vh;
align-items: center;
font-size: 14px;
}
</style>
<article>
hello
<span>theliuwei</span>
theliuwei
</article>
绝对定位
绝对定位的弹性元素不参与弹性布局
<style>
* {
padding: 0;
margin: 0;
padding: 10px;
margin: 5px;
}
article {
position: relative;
height: 400px;
border: solid 5px silver;
box-sizing: border-box;
display: flex;
justify-content: space-evenly;
align-items: flex-start;
}
article div {
min-width: 50px;
min-height: 80px;
border: solid 5px blueviolet;
text-align: center;
font-size: 28px;
}
article div:nth-of-type(1) {
position: absolute;
top: 0;
}
</style>
...
<article>
<div>1</div>
<div>2</div>
<div>3</div>
</article>
自动空间
在弹性布局中对元素使用margin-right:auto
等形式可以自动撑满空间。
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
* {
padding: 0;
margin: 0;
}
.container {
width: 1200px;
margin: 0 auto;
}
nav {
display: flex;
border: solid 1px green;
margin-top: 20px;
align-items: center;
height: 60px;
box-shadow: 0 0 5px rgba(0, 0, 0, .2);
background: #f3f3f3;
}
ul {
list-style: none;
}
ul:nth-child(1) {
display: flex;
align-items: center;
margin-right: auto;
}
ul:nth-child(1)>li {
margin: 0 10px;
}
ul:nth-child(2)>li {
width: 50px;
height: 50px;
border-radius: 50%;
background: #9b59b6;
}
</style>
</head>
<body>
<div class="container">
<nav>
<ul>
<li>theliuwei</li>
<li>视频</li>
<li>教程</li>
<li>文档</li>
</ul>
<ul>
<li>
</li>
</ul>
</nav>
</div>
</body>