Flex 补充属性与实战

学习

Flex 补充属性与实战

2026-02-23/0/ 编辑


Flex 补充属性与实战


一、补充:Flex 容器属性

1.1 row-gap、column-gap、gap 设置 flex 子项间隔

属性名说明
row-gap用于设置 flex 项目行之间的间隔大小(默认主轴为水平方向时)
column-gap用于设置 flex 项目列之间的间隔大小(默认主轴为水平方向时)
gapgap 为 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>