Web/02-CSS基础/13-CSS3属性:Flex布局图文详解.md
2019-10-13 14:05:52 +08:00

628 lines
15 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 前言
CSS3中的 flex 属性在布局方面做了非常大的改进使得我们对**多个元素之间**的布局排列变得十分灵活适应性非常强其强大的伸缩性和自适应性在网页开中可以发挥极大的作用
### flex 初体验
我们先来看看下面这个最简单的布局
![](http://img.smyhvae.com/20191009_1555.png)
上面这张图中的布局是我们都熟悉的默认文档流中在一个父容器里放置多个块级的子元素那么这些子元素会默认从上往下排列
在此基础之上如果我给父容器仅仅加一个 `display: flex`属性此时这些子元素的布局会摇身一变
![](http://img.smyhvae.com/20191009_1600.png)
没错子元素们会**在水平方向上从左至右排列**就是这么神奇到此为止你已经掌握了关于 flex 的一半的知识
### flex 布局的优势
1**flex 布局的子元素不会脱离文档流**很好地遵从了流的特性
但你如果用 float 来做布局float 属性的元素会脱离文档流而且会涉及到各种 BFC清除浮动的问题浮动相关的问题比较麻烦所以也成了面试必问的经典题目但有了 flex 布局之后这些问题都不存在的
2**flex 是一种现代的布局方式 W3C 第一次提供真正用于布局的 CSS 规范** flex 非常提供了丰富的属性非常灵活让布局的实现更佳多样化且方便易用
flex 唯一的缺点就在于它不支持低版本的 IE 浏览器
### flex 的兼容性问题
![](http://img.smyhvae.com/20191005_1200.png)
上图中可以看到 flex 布局不支持 IE9 及以下的版本IE10及以上也只是部分支持如果你的页面不需要处理 IE浏览器的兼容性问题则可以放心大胆地使用 flex 布局
但是比如网易新闻淘宝这样的大型网站面对的是海量用户即便使用低版本浏览器的用户比例很少但绝对基数仍然是很庞大的因此这些网站为了兼容低版本的 IE 浏览器暂时还不敢尝试使用 flex 布局
### 概念弹性盒子子元素
在讲 flex 的知识点之前我们事先约定两个概念
- **弹性盒子**指的是使用 `display:flex` `display:inline-flex` 声明的**父容器**
- **子元素/弹性元素**指的是父容器里面的子元素们父容器被声明为 flex 盒子的情况下
### 概念主轴和侧轴
在上面的初体验例子中我们发现弹性盒子里面的子元素们默认是从左至右排列的这个方向代表的就是主轴的方向
在此我们引入主轴和侧轴的概念
![](http://img.smyhvae.com/20191009_1701.png)
如上图所示
- 主轴flex容器的主轴默认是水平方向从左向右
- 侧轴与主轴垂直的轴称作侧轴默认是垂直方向从上往下
PS主轴和侧轴并不是固定不变的可以通过 `flex-direction` 更换方向我们在后面会讲到
## 弹性盒子
### 声明定义
使用 `display:flex` `display:inline-flex` 声明一个**父容器**为弹性盒子此时这个父容器里的子元素们会遵循弹性布局
备注一般是用 `display:flex`这个属性`display:inline-flex`用得较少
### flex-direction 属性
`flex-direction`用于设置盒子中**子元素**的排列方向属性值可以是
| 属性值 | 描述 |
|:-------------|:-------------|
| row | 从左到右水平排列子元素默认值 |
|column|从上到下垂直排列子元素|
| row-reverse |从右向左排列子元素 |
|column-reverse|从下到上垂直排列子元素|
备注如果我们不给父容器写`flex-direction`这个属性那么子元素默认就是从左到右排列的
代码演示
```html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
*{
margin: 0;
padding: 0;
list-style: none;
}
body{
background-color: #eee;
font-family: "Microsoft Yahei";
font-size:22px;
}
h3{
font-weight: normal;
}
section{
width: 1000px;
margin:40px auto;
}
ul{
background-color: #fff;
border: 1px solid #ccc;
}
ul li{
width: 200px;
height: 200px;
background-color: pink;
margin:10px;
}
section:nth-child(1) ul{
overflow: hidden; /* 清除浮动 */
}
section:nth-child(1) ul li{
float: left;
}
/* 设置伸缩盒子*/
section:nth-child(2) ul{
display: flex;
}
section:nth-child(3) ul{
/* 设置伸缩布局*/
display: flex;
/* 设置主轴方向*/
flex-direction: row;
}
section:nth-child(4) ul{
/* 设置伸缩布局*/
display: flex;
/* 设置主轴方向 :水平翻转*/
flex-direction: row-reverse;
}
section:nth-child(5) ul{
/* 设置伸缩布局*/
display: flex;
/* 设置主轴方向 :垂直*/
flex-direction: column;
}
section:nth-child(6) ul{
/* 设置伸缩布局*/
display: flex;
/* 设置主轴方向 :垂直*/
flex-direction: column-reverse;
}
</style>
</head>
<body>
<section>
<h3>传统布局</h3>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</section>
<section>
<h3>伸缩布局 display:flex</h3>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</section>
<section>
<h3>主轴方向 flex-direction:row</h3>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</section>
<section>
<h3>主轴方向 flex-direction:row-reverse</h3>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</section>
<section>
<h3>主轴方向 flex-direction:column</h3>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</section>
<section>
<h3>主轴方向 flex-direction:column-reverse</h3>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</section>
</body>
</html>
```
### flex-wrap 属性
`flex-wrap`控制子元素溢出时的换行处理
### justify-content 属性
`justify-content`控制子元素在主轴上的排列方式
## 弹性元素
### justify-content 属性
- `justify-content: flex-start;` 设置子元素在**主轴上的对齐方式**属性值可以是
- `flex-start` 从主轴的起点对齐默认值
- `flex-end` 从主轴的终点对齐
- `center` 居中对齐
- `space-around` 在父盒子里平分
- `space-between` 两端对齐 平分
代码演示在浏览器中打开看效果
```html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
*{
margin: 0;
padding: 0;
list-style:none;}
body{
background-color: #eee;
font-family: "Microsoft Yahei";
}
section{
width: 1000px;
margin:50px auto;
}
section h3{
font-size:22px;
font-weight: normal;
}
ul{
border: 1px solid #999;
background-color: #fff;
display: flex;
}
ul li{
width: 200px;
height: 200px;
background: pink;
margin:10px;
}
section:nth-child(1) ul{
/* 主轴对齐方式:从主轴开始的方向对齐*/
justify-content: flex-start;
}
section:nth-child(2) ul{
/* 主轴对齐方式:从主轴结束的方向对齐*/
justify-content: flex-end;
}
section:nth-child(3) ul{
/* 主轴对齐方式:居中对齐*/
justify-content: center;
}
section:nth-child(4) ul{
/* 主轴对齐方式:在父盒子中平分*/
justify-content: space-around;
}
section:nth-child(5) ul{
/* 主轴对齐方式:两端对齐 平分*/
justify-content: space-between;
}
</style>
</head>
<body>
<section>
<h3>主轴的对齐方式justify-content:flex-start</h3>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</section>
<section>
<h3>主轴的对齐方式justify-content:flex-end</h3>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</section>
<section>
<h3>主轴的对齐方式justify-content:center</h3>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</section>
<section>
<h3>主轴的对齐方式justify-content:space-round</h3>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</section>
<section>
<h3>主轴的对齐方式justify-content:space-bettwen</h3>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
</section>
</body>
</html>
```
### align-items 属性
`align-items`设置子元素在**侧轴上的对齐方式**属性值可以是
- `flex-start` 从侧轴开始的方向对齐
- `flex-end` 从侧轴结束的方向对齐
- `baseline` 基线 默认同flex-start
- `center` 中间对齐
- `stretch` 拉伸
代码演示
```html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
*{
margin: 0;
padding: 0;
list-style:none;
}
body{
background-color: #eee;
font-family: "Microsoft Yahei";
}
section{
width: 1000px;
margin:50px auto;
}
section h3{
font-size:22px;
font-weight: normal;
}
ul{
border: 1px solid #999;
background-color: #fff;
display: flex;
height:500px;
}
ul li{
width: 200px;
height: 200px;
background: pink;
margin:10px;
}
section:nth-child(1) ul{
/* 侧轴对齐方式 :从侧轴开始的方向对齐*/
align-items:flex-start;
}
section:nth-child(2) ul{
/* 侧轴对齐方式 :从侧轴结束的方向对齐*/
align-items:flex-end;
}
section:nth-child(3) ul{
/* 侧轴对齐方式 :居中*/
align-items:center;
}
section:nth-child(4) ul{
/* 侧轴对齐方式 :基线 默认同flex-start*/
align-items:baseline;
}
section:nth-child(5) ul{
/* 侧轴对齐方式 :拉伸*/
align-items:stretch;
}
section:nth-child(5) ul li{
height:auto;
}
</style>
</head>
<body>
<section>
<h3>侧轴的对齐方式:align-items flex-start</h3>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</section>
<section>
<h3>侧轴的对齐方式align-items:flex-end</h3>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</section>
<section>
<h3>侧轴的对齐方式align-items:center</h3>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</section>
<section>
<h3>侧轴的对齐方式align-itmes:baseline</h3>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</section>
<section>
<h3>侧轴的对齐方式align-itmes: stretch</h3>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</section>
</body>
</html>
```
### `flex`属性设置子盒子的权重
代码演示
```html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
*{
margin: 0;
padding: 0;
list-style:none;
}
body{
background-color: #eee;
font-family: "Microsoft Yahei";
}
section{
width: 1000px;
margin:50px auto;
}
section h3{
font-size:22px;
font-weight: normal;
}
ul{
border: 1px solid #999;
background-color: #fff;
display: flex;
}
ul li{
width: 200px;
height: 200px;
background: pink;
margin:10px;
}
section:nth-child(1) ul li:nth-child(1){
flex:1;
}
section:nth-child(1) ul li:nth-child(2){
flex:1;
}
section:nth-child(1) ul li:nth-child(3){
flex:8;
}
section:nth-child(2) ul li:nth-child(1){
}
section:nth-child(2) ul li:nth-child(2){
flex:1;
}
section:nth-child(2) ul li:nth-child(3){
flex:4;
}
</style>
</head>
<body>
<section>
<h3>伸缩比例:flex</h3>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</section>
<section>
<h3>伸缩比例:flex</h3>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</section>
</body>
</html>
```
## 相关链接
### CSS Flexbox 可视化手册
可视化的截图如下请点开链接查看大图
<http://img.smyhvae.com/20190821_2101.png>
相关文章
- 英文原版 CSS Flexbox Fundamentals Visual Guide<https://medium.com/swlh/css-flexbox-fundamentals-visual-guide-1c467f480dac>
- 中文翻译CSS Flexbox 可视化手册<https://zhuanlan.zhihu.com/p/56046851>
### flex 相关的推荐文章
- flex 效果在线演示<https://demos.scotch.io/visual-guide-to-css3-flexbox-flexbox-playground/demos/>
- A Complete Guide to Flexbox | 英文原版<https://css-tricks.com/snippets/css/a-guide-to-flexbox/>
- CSS3 Flexbox 布局完全指南 | 中文翻译<https://www.html.cn/archives/8629>
### flex 相关的教程
- [后盾人 flex 教程](http://houdunren.gitee.io/note/css/10%20%E5%BC%B9%E6%80%A7%E5%B8%83%E5%B1%80.html)
## 技巧使用 margin 自动撑满剩余空间