Flex 补充属性与实战
一、补充:Flex 容器属性
1.1 row-gap、column-gap、gap 设置 flex 子项间隔
| 属性名 | 说明 |
|---|---|
| row-gap | 用于设置 flex 项目行之间的间隔大小(默认主轴为水平方向时) |
| column-gap | 用于设置 flex 项目列之间的间隔大小(默认主轴为水平方向时) |
| gap | gap 为 row-gap 与 column-gap 的复合写法,即 gap: row-gap column-gap |
案例演示
<style>
.flex {
display: flex;
width: 430px;
border: 1px solid red;
flex-wrap: wrap;
row-gap: 10px; /* 行间距 */
column-gap: 10px; /* 列间距 */
}
.item {
width: 100px;
height: 100px;
background-color: khaki;
}
</style>
<div class="flex">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
</div>1.2 单行宽自适应两端对齐
<style>
.flex {
display: flex;
border: 1px solid red;
column-gap: 10px;
}
.item {
background-color: khaki;
min-height: 100px;
flex: 1;
/* flex: 1 相当于
flex-basis: 0; 最开始元素在主轴占据尺寸为 0
flex-grow: 1; 所有元素平分剩余空间
flex-shrink: 1; 当空间不足时所有元素同步收缩
*/
}
</style>
<div class="flex">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>1.3 多行宽自适应两端对齐
<style>
.flex {
display: flex;
border: 1px solid red;
column-gap: 10px;
row-gap: 10px;
flex-wrap: wrap;
}
.item {
background-color: khaki;
min-height: 100px;
flex: calc(25% - 10px);
/*
相当于
flex-basis: calc(25% - 10px); 最开始元素在主轴占据尺寸
flex-grow: 1; 所有元素平分剩余空间
flex-shrink: 1; 当空间不足时所有元素同步收缩
*/
}
</style>
<div class="flex">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>二、Flex 实战案例
2.1 元素水平垂直居中
<style>
.flex-container {
width: 200px;
height: 200px;
background-color: skyblue;
display: flex;
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
}
.flex-item {
width: 100px;
height: 100px;
background-color: khaki;
}
</style>
<div class="flex-container">
<div class="flex-item"></div>
</div>2.2 画 3 点色子
<style>
.dice {
width: 95px;
height: 95px;
border: 1px solid #666;
border-radius: 5px;
display: flex;
justify-content: space-between; /* 两端对齐 */
padding: 5px;
}
.dice span {
width: 20px;
height: 20px;
background-color: #000;
border-radius: 50%;
}
/* 色子 2 */
.dice span:nth-child(2) {
align-self: center;
}
/* 色子 3 */
.dice span:last-child {
align-self: flex-end;
}
</style>
<div class="dice">
<span></span>
<span></span>
<span></span>
</div>关于 1 点色子到 6 点色子,如何用弹性布局来实现:
详细可以参考博客地址:https://www.arryblog.com/
2.3 双飞翼布局
需求: 左右固定,中间自适应,最中间的内容放在第一位,有利于 SEO 搜索引擎优化。
<style>
html,
body {
width: 100%;
height: 100%;
margin: 0;
}
.container {
display: flex;
height: 100%;
}
.middle {
flex-grow: 1;
background-color: khaki;
order: 1;
}
.left {
width: 200px;
background-color: skyblue;
order: 0;
}
.right {
width: 200px;
background-color: tomato;
order: 2;
}
</style>
<div class="container">
<div class="middle">中间</div>
<div class="left">左边</div>
<div class="right">右边</div>
</div>2.4 Flex 实现盒子 1 在最左边,2、3 在最右边
<style>
html,
body {
margin: 0;
padding: 0;
}
.container {
height: 200px;
border: 2px solid #000;
display: flex;
justify-content: space-between; /* 两端对齐 */
}
.container .left {
width: 300px;
background-color: tomato;
}
.container .right {
display: flex; /* 弹性布局,这样子元素没有添加高度时,会和父元素一样高 */
}
.container .right .item1 {
width: 200px;
background-color: pink;
}
.container .right .item2 {
width: 100px;
background-color: skyblue;
}
</style>
<div class="container">
<div class="left"></div>
<div class="right">
<div class="item1"></div>
<div class="item2"></div>
</div>
</div>2.5 左右布局,左侧文字支持溢出显示省略号
<style>
.box {
width: 500px;
height: 50px;
display: flex;
align-items: center;
}
.box .title {
flex: 1; /* 等价 1 1 0,支持弹性缩放 */
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
line-height: 50px;
margin-right: 10px;
}
.box .mark {
width: 30px;
height: 30px;
text-align: center;
line-height: 30px;
color: #fff;
border-radius: 5px;
background-color: pink;
flex-shrink: 0; /* 相当于将 flex 默认值 0 1 auto 修改为 0 0 auto */
}
</style>
<div class="box">
<div class="title">
我是标题内容,我希望占据剩余的空间。如果内容放不下,我不换行,要显示省略号
</div>
<div class="mark">新</div>
</div>
<div class="box">
<div class="title">我是标题内容,我希望占据剩余的空间</div>
<div class="mark">新</div>
</div>2.6 星级评估
<style>
.rating {
display: flex;
align-items: center;
justify-content: center;
flex-direction: row-reverse; /* 从右往左排列,关键性代码 */
}
.rating-star {
position: relative;
margin: 0 2px;
font-size: 42px;
color: #ddd;
}
.rating-star::before {
/* \2605 是 Unicode 转义序列 表示实心五角星 ★ */
content: "\2605";
left: 0px;
position: absolute;
}
/* 鼠标滑动到星上时,星后面对应的星都变红 */
.rating-star:hover::before,
.rating-star:hover ~ .rating-star::before {
color: red;
}
</style>
<div class="rating">
<span class="rating-star">☆</span>
<span class="rating-star">☆</span>
<span class="rating-star">☆</span>
<span class="rating-star">☆</span>
<span class="rating-star">☆</span>
</div>2.7 阶梯式布局
<style>
p {
margin: 0;
padding: 0;
}
.container {
width: 1000px;
height: 400px;
display: flex;
align-items: flex-end; /* 子元素在交叉轴上对齐方式为底部 */
}
.container .flex-item {
flex: 1; /* 相当于 1 1 0,子元素宽为 0,然后在此基础上自动伸缩 */
margin: 0px 10px;
background-color: skyblue;
}
.h100 {
height: 100px;
}
.h200 {
height: 200px;
}
.h250 {
height: 250px;
}
.h300 {
height: 300px;
}
.h350 {
height: 350px;
}
.flex-item p {
line-height: 50px;
text-align: center;
font-size: 20px;
color: #fff;
}
</style>
<div class="container">
<div class="flex-item h100">
<p>第一阶段</p>
</div>
<div class="flex-item h200">
<p>第二阶段</p>
</div>
<div class="flex-item h250">
<p>第三阶段</p>
</div>
<div class="flex-item h300">
<p>第三阶段</p>
</div>
<div class="flex-item h350">
<p>第四阶段</p>
</div>
</div>2.8 时间轴布局
<style>
.flex-container {
width: 600px;
margin: 50px auto;
display: flex;
flex-direction: column;
}
.flex-item:nth-child(2n + 1) {
width: calc(50% - 1px);
height: 200px;
border-right: 2px solid skyblue;
position: relative;
padding-top: 20px;
}
.flex-item:nth-child(2n) {
width: calc(50% - 1px);
height: 200px;
padding-top: 20px;
align-self: flex-end; /* 交叉轴结束位置 */
border-left: 2px solid skyblue;
position: relative;
}
.flex-item:nth-child(2n + 1)::before,
.flex-item:nth-child(2n)::before {
content: "";
display: block;
width: 0;
height: 0;
border: 10px solid transparent;
position: absolute;
top: 50%;
transform: translateY(-50%);
}
.flex-item:nth-child(2n + 1)::before {
border-left-color: skyblue;
right: -10px;
}
.flex-item:nth-child(2n)::before {
border-right-color: skyblue;
left: -10px;
}
.flex-item:nth-child(2n + 1) .content {
margin-right: 10px;
min-height: 200px;
background-color: skyblue;
border-radius: 5px;
}
.flex-item:nth-child(2n) .content {
margin-left: 10px;
min-height: 200px;
background-color: skyblue;
border-radius: 5px;
}
</style>
<div class="flex-container">
<div class="flex-item">
<div class="content"></div>
</div>
<div class="flex-item">
<div class="content"></div>
</div>
<div class="flex-item">
<div class="content"></div>
</div>
<div class="flex-item">
<div class="content"></div>
</div>
</div>2.9 解决 Flex 布局最后一行两边分布的问题
问题描述
当我们使用 space-between 两端对齐时,最后一行元素不足时,会出现元素靠左分布,而不是两端对齐的问题。
解决方案
如果我们每一行显示的个数为 n,那可以在最后一行子项的后面加上 n-2 个 span 元素,span 元素的宽度和其它子项元素宽度一样,但不用设置高度。
为什么是添加 n-2 个 span 元素呢?
- 当最后一行只有 1 个子元素时,它会默认靠左,不用处理
- 当最后一行子元素正好时,我们就不用关心这个问题
- 所以要去掉这两种情况,只需要加 n-2 个 span 元素就好
案例演示
没有添加 span 元素前的效果:
<style>
.container {
width: 500px;
display: flex;
justify-content: space-between; /* 两端对齐 */
flex-wrap: wrap; /* 超出部分换行 */
}
.item {
width: 120px;
height: 100px;
background-color: pink;
margin-top: 10px;
}
</style>
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
</div>添加了 n-2 个 span 元素后效果(这里每行 4 个,4-2=2,所以只需要加 2 个 span 就可以了):
<style>
.container span {
width: 120px; /* span 宽和子项宽一样 */
}
</style>
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<span></span>
<span></span>
</div>