Skip to content
本页目录

写给自己看的flex布局

如何创建 flex 布局?

  • div这类块状元素元素设置display:flex
  • span这类内联元素设置display:inline-flex

其中,直接设置 display:flex | inline-flex 的元素称为flex容器,里面的子元素称为flex子项。

flexinline-flex的区别

inline-flex容器为inline特性,因此可以和图片文字一行显示flex 容器保持块状特性,宽度默认100%,不和内联元素一行显示

  • stretch
    A
    B
    C
  • space-between
    A
    B
    C
  • space-around
    A
    B
    C
  • space-evenly
    A
    B
    C
  • center
    A
    B
    C
  • flex-end
    A
    B
    C
  • flex-start
    A
    B
    C
<template>
  <div class="flexbBox">
    <ul>
      <li>
        <h5>
          stretch
        </h5>
        <div>
          <div class="flex " style="justify-content: stretch; height: 82px; width: 100%;">
            <div class="item not-tall super-wide">
              A
            </div>
            <div class="item not-tall super-wide">
              B
            </div>
            <div class="item not-tall super-wide">
              C
            </div>
          </div>
        </div>
      </li>

      <li>
        <h5>space-between</h5>
        <div>
          <div class="flex " style="justify-content: space-between; height: 82px; width: 100%;">
            <div class="item not-tall">
              A
            </div>
            <div class="item not-tall">
              B
            </div>
            <div class="item not-tall">
              C
            </div>
          </div>
        </div>
      </li>

      <li>
        <div>
          <h5>space-around</h5>
        </div>
        <div>
          <div class="flex " style="justify-content: space-around; height: 82px; width: 100%;">
            <div class="item not-tall">
              A
            </div>
            <div class="item not-tall">
              B
            </div>
            <div class="item not-tall">
              C
            </div>
          </div>
        </div>
      </li>

      <li>
        <h5>space-evenly</h5>
        <div>
          <div class="flex not-tall " style="justify-content: space-evenly; height: 82px; width: 100%;">
            <div class="item not-tall">
              A
            </div>
            <div class="item not-tall">
              B
            </div>
            <div class="item not-tall">
              C
            </div>
          </div>
        </div>
      </li>

      <li>
        <h5>center</h5>
        <div>
          <div class="flex not-tall " style="justify-content: center; height: 82px; width: 100%;">
            <div class="item not-tall">
              A
            </div>
            <div class="item not-tall">
              B
            </div>
            <div class="item not-tall">
              C
            </div>
          </div>
        </div>
      </li>

      <li>
        <h5>flex-end</h5>
        <div>
          <div class="flex not-tall " style="justify-content: flex-end; height: 82px; width: 100%;">
            <div class="item not-tall">
              A
            </div>
            <div class="item not-tall">
              B
            </div>
            <div class="item not-tall">
              C
            </div>
          </div>
        </div>
      </li>

      <li>
        <h5>flex-start</h5>
        <div>
          <div class="flex not-tall " style="justify-content: flex-start; height: 82px; width: 100%;">
            <div class="item not-tall">
              A
            </div>
            <div class="item not-tall">
              B
            </div>
            <div class="item not-tall">
              C
            </div>
          </div>
        </div>
      </li>
    </ul>
  </div>
</template>

<style lang="scss" scoped>
.flexbBox{
  > ul {
  list-style: none !important;
  padding: 0;
  margin: 0 !important;

  h5 {
    min-width: 200px;
    margin-bottom: 12px;
  }
}
}

.flex {
  display: flex;
  background: #9369ff !important;
  border-radius: 8px;
  padding: 8px;
}

.not-tall {
  height: 50px;
  line-height: 50px;
}

.super-wide {
  width: 100%;
}

.item {
  font-size: 28px;
  font-weight: bold;
  border-radius: 8px;
  min-width: 100px;
  text-align: center;
  background: #fbe404;
  box-shadow: inset 8px 8px 10px #ffffff, inset -3px -3px 10px #ff8e19;
  color: var(--flex-item-color);
  margin: 8px;
}

.write-for-us {
  padding: 14px;
  margin: 14px;
  background: #007fff;
  border: 2px solid transparent;
  font-weight: bold;
  color: #ffffff;
}

.write-for-us:hover {
  color: #007fff !important;
  background-color: transparent !important;
  border-color: #007fff !important;
}

.pointer {
  cursor: pointer;
}
</style>

flex 相关属性分类

flex布局相关属性正好分为两拨,一拨作用在flex容器上,还有一拨作用在flex子项上。

具体参见下表,点击可快速索引。

点我跳转:基础功能

作用在flex容器上

作用在flex子项上

作用在 flex 容器上的CSS属性

flex-direction

Details

flex-direction 用来控制子项整体布局方向,是从左往右还是从右往左,是从上往下还是从下往上。

语法如下:

css
flex-direction: row | row-reverse | column | column-reverse;
  • row: 默认值,显示为行。方向为当前文档水平流方向,默认情况下是从左往右。
  • row-reverse: 显示为行。但方向和row属性值是反的。
  • column: 显示为列。
  • column-reverse: 显示为列。但方向和column属性值是反的。
<script lang="ts" setup>
import { ref } from 'vue'

const flex_direction = ref('row')
</script>

<template>
  <div class="flex-dome">
    <el-radio-group v-model="flex_direction">
      <el-radio label="row">
        row
      </el-radio>
      <el-radio label="row-reverse">
        row-reverse
      </el-radio>
      <el-radio label="column">
        column
      </el-radio>
      <el-radio label="column-reverse">
        column-reverse
      </el-radio>
    </el-radio-group>

    <div class="box">
      <div class="_item bg-img" data-index="1" />
      <div class="_item bg-img" data-index="2" />
      <div class="_item bg-img" data-index="3" />
    </div>
  </div>
</template>

<style lang="scss" scoped>
.box {
  display: flex;
  flex-direction: v-bind(flex_direction);
}

._item {
  height: 80px;
  width: 80px;
  margin: 12px;
}
</style>

flex-wrap

Details

flex-wrap 用与控制子项整体单行显示还是换行显示,如果换行,则下面一行是否反方向显示。

在CSS世界中,只要看到单词 wrap 一定是与换行显示相关的,如: word-wrapwhite-space: nowrappre-wrap

语法如下:

css
flex-wrap: nowrap | wrap | wrap-reverse;
  • nowrap: 默认值,表示单行显示,不换行。很容易出现宽度溢出的场景
  • wrap: 宽度不足换行显示。
  • wrap-reverse: 宽度不足换行显示,但是是从下往上开始,也就是原本换行在下面的子项现在跑到上面。
<script lang="ts" setup>
import { ref } from 'vue'

const flex_wrap = ref('nowrap')
</script>

<template>
  <div class="flex-dome">
    <el-radio-group v-model="flex_wrap">
      <el-radio label="nowrap">
        nowrap
      </el-radio>
      <el-radio label="wrap">
        wrap
      </el-radio>
      <el-radio label="wrap-reverse">
        wrap-reverse
      </el-radio>
    </el-radio-group>

    <div class="box">
      <div class="item_1" data-index="1" />
      <div class="item_1" data-index="2" />
      <div class="item_1" data-index="3" />
      <div class="item_1" data-index="4" />
      <div class="item_1" data-index="5" />
      <div class="item_1" data-index="6" />
    </div>
  </div>
</template>

<style lang="scss" scoped>
.box {
  display: flex;
  flex-wrap: v-bind(flex_wrap);
}

.item_1 {
  height: 80px;
  width: 80px;
  margin: 12px;
}
</style>

flex-flow

Details

flex-flow属性是flex-directionflex-wrap的缩写,表示flex布局的flow流动特性,语法如下:

css
flex-flow: <‘flex-direction> || <‘flex-wrap>

/** 举个例子,容器元素如下设置 */
.container {
    display: flex;
    flex-flow: row-reverse wrap-reverse;
}
<template>
  <div class="flex-dome">
    <div class="box">
      <div class="item_1" data-index="1" />
      <div class="item_1" data-index="2" />
      <div class="item_1" data-index="3" />
      <div class="item_1" data-index="4" />
      <div class="item_1" data-index="5" />
      <div class="item_1" data-index="6" />
    </div>
  </div>
</template>

<style lang="scss" scoped>
.box {
  display: flex;
  flex-flow: row-reverse wrap-reverse;
}

.item_1 {
  height: 80px;
  width: 80px;
  margin: 12px;
}
</style>

justify-content

Details

justify-content属性决定了水平方向子项的对齐和分布方式。

CSS text-align 有个属性值为 justify,可实现两端对齐,所以,当我们想要控制 flex 元素的水平对齐方式的时候,记住 justify 这个单词,justify-content属性也就记住了。

语法如下:

css
justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
  • flex-start: 默认值。逻辑CSS属性值,与文档流方向相关。默认表现为左对齐。
  • flex-end: 逻辑CSS属性值,与文档流方向相关。默认表现为右对齐。
  • center: 表现为居中对齐。
  • space-between: 表现为两端对齐。between是中间的意思,意思是多余的空白间距只在元素中间区域分配。
  • space-around: around是环绕的意思,意思是每个flex子项两侧都环绕互不干扰的等宽的空白间距,最终视觉上边缘两侧的空白只有中间空白宽度一半。
  • space-evenly: evenly是匀称、平等的意思。也就是视觉上,每个 flex子项 两侧空白间距完全相等。
<script lang="ts" setup>
import { ref } from 'vue'

const justify_content = ref('flex-start')
</script>

<template>
  <div class="flex-dome">
    <el-radio-group v-model="justify_content">
      <el-radio label="flex-start">
        flex-start
      </el-radio>
      <el-radio label="flex-end">
        flex-end
      </el-radio>
      <el-radio label="center">
        center
      </el-radio>
      <el-radio label="space-between">
        space-between
      </el-radio>
      <el-radio label="space-around">
        space-around
      </el-radio>
      <el-radio label="space-evenly">
        space-evenly
      </el-radio>
    </el-radio-group>
    <div class="box">
      <div class="_item bg-img" data-index="1" />
      <div class="_item bg-img" data-index="2" />
      <div class="_item bg-img" data-index="3" />
    </div>
  </div>
</template>

<style lang="scss" scoped>
.box {
  display: flex;
  justify-content: v-bind(justify_content);
}

._item {
  height: 80px;
  width: 80px;
  margin: 12px;
}
</style>

align-items

Details

align-items中的items指的就是flex子项们,因此align-items指的就是flex子项们相对于flex容器在垂直方向上的对齐方式。

语法如下:

css
align-items: stretch | flex-start | flex-end | center | baseline;
  • stretch: 默认值。flex子项拉伸。 如果flex子项设置了高度,则按照设置的高度值渲染,而非拉伸
  • flex-start: 容器顶部对齐。
  • flex-end: 容器底部对齐。
  • center: 垂直居中对齐。
  • baseline: 表现为所有flex子项都相对于flex容器的基线(字母x的下边缘)对齐。
<script lang="ts" setup>
import { ref } from 'vue'

const align_items = ref('stretch')
</script>

<template>
  <div class="flex-dome">
    <el-radio-group v-model="align_items">
      <el-radio label="stretch">
        stretch
      </el-radio>
      <el-radio label="flex-start">
        flex-start
      </el-radio>
      <el-radio label="flex-end">
        flex-end
      </el-radio>
      <el-radio label="center">
        center
      </el-radio>
      <el-radio label="baseline">
        baseline
      </el-radio>
    </el-radio-group>
    <div class="box">
      <div class="item" data-index="1">
        <img src="https://cdn.jsdelivr.net/gh/liaoyio/imgHosting/wk/2023/user/12nvi.jpg">
      </div>
      <div class="item" data-index="2">
        <img src="https://cdn.jsdelivr.net/gh/liaoyio/imgHosting/wk/2023/user/13nvi.jpg">
      </div>
      <div class="item" data-index="3">
        <img src="https://cdn.jsdelivr.net/gh/liaoyio/imgHosting/wk/2023/user/14nvi.jpg">
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.box {
  display: flex;
  gap: 3rem;
  align-items: v-bind(align_items);
  .item {
    background: orangered;
    min-width: 160px;
    img{
      border-radius: 8px;
    }
  }
}
</style>

align-content

Details

align-content可以看成和justify-content是相似且对立的属性,justify-content指明水平方向flex子项的对齐和分布方式,而align-content则是指明垂直方向每一行flex元素的对齐和分布方式。注意: 如果所有flex子项只有一行,align-content 没有任何效果

语法如下:

css
align-content: stretch | flex-start | flex-end | center | space-between | space-around | space-evenly;

stretch: 默认值。每一行flex子元素都等比例拉伸。例如,如果共两行flex子元素,则每一行拉伸高度是50%。 flex-start: 表现为顶部堆砌flex-end: 表现为底部堆放center: 表现为整体垂直居中对齐。 space-between: 表现为上下两行两端对齐。剩下每一行元素等分剩余空间。 space-around: 每一行元素上下都享有独立不重叠的空白空间。 space-evenly: 每一行元素都完全上下等分。

给flex容器设置高度500像素,点击下面对应单选框,可以看到实时的布局效果.
<script lang="ts" setup>
import { ref } from 'vue'

const align_content = ref('stretch')
</script>

<template>
  <div class="flex-dome">
    <el-radio-group v-model="align_content">
      <el-radio label="stretch">
        stretch
      </el-radio>
      <el-radio label="flex-start">
        flex-start
      </el-radio>
      <el-radio label="flex-end">
        flex-end
      </el-radio>
      <el-radio label="center">
        center
      </el-radio>
      <el-radio label="baseline">
        baseline
      </el-radio>
    </el-radio-group>

    <div class="box">
      <div class="item_1" data-index="1" />
      <div class="item_1" data-index="2" />
      <div class="item_1" data-index="3" />
      <div class="item_1" data-index="4" />
      <div class="item_1" data-index="5" />
      <div class="item_1" data-index="6" />
    </div>
  </div>
</template>

<style lang="scss" scoped>
.box {
  height: 300px;
  flex-wrap: wrap;
  border-radius: 8px;
  outline: 1px dotted;
  display: flex;
  align-content: v-bind(align_content);
}

.item_1 {
  height: 80px;
  width: 80px;
  margin: 12px;
}
</style>

作用在flex子项上的CSS属性

order

Details

我们可以通过设置order改变某一个flex子项的排序位置。

css
order: <integer>; /* 整数值,默认值是 0 */

所有flex子项的默认order属性值是0,因此,如果我们想要某一个flex子项在最前面显示,可以设置比0小的整数,如-1就可以了。

下面flex容器有5个子元素,现在,我们给第3个子元素设置order属性值,看看其排列位置有何变化。点击下面的单选框,可以看到实时的交互效果:
<script lang="ts" setup>
import { ref } from 'vue'

const order_num = ref(-1)
</script>

<template>
  <div class="flex-dome">
    <el-radio-group v-model="order_num">
      <el-radio :label="-1">
        order:-1
      </el-radio>
      <el-radio :label="0">
        order:0
      </el-radio>
      <el-radio :label="1">
        order:1
      </el-radio>
    </el-radio-group>

    <div class="box">
      <div class="child" data-index="1" />
      <div class="child" data-index="2" />
      <div class="child" data-index="3" :style="{ order: order_num }" />
      <div class="child" data-index="4" />
      <div class="child" data-index="5" />
    </div>
  </div>
</template>

<style lang="scss" scoped>
.box {
  display: flex;
  justify-content: space-between;
}

.child {
  height: 80px;
  width: 80px;
}
</style>

flex-grow

Details

flex-grow属性中的grow是扩展的意思,扩展的就是flex子项所占据的宽度,扩展所侵占的空间就是除去元素外的剩余的空白间隙。

css
flex-grow: <number>; /* 数值,可以是小数,默认值是 0 */

flex-grow 不支持负值,默认值是0,表示不占用剩余的空白间隙扩展自己的宽度。如果flex-grow大于0,则flex容器剩余空间的分配就会发生。

flex容器3 个子元素, 给第2个子元素设置flex-grow: 1
01
02
03
flex容器3个子元素,第一个和最后一个子元素设置为 flex-grow: 1 , 第2个子元素设置 flex-grow: 0
01
02
03
<template>
  <div>
    <div class="ls">
      <div class="pb-2">
        <code>flex容器</code><code>3</code> 个子元素, 给第2个子元素设置<code>flex-grow: 1</code>
      </div>
      <div class="bg-stripes-indigo">
        <div class="it">
          01
        </div>
        <div class="light-nth" style="flex-grow: 1;">
          02
        </div>
        <div class="it">
          03
        </div>
      </div>
      <div class="pt-8 pb-2">
        <code>flex容器</code><code>3</code>个子元素,第一个和最后一个子元素设置为 <code>flex-grow: 1</code> , 第2个子元素设置 <code>flex-grow: 0</code>
      </div>
      <div class="bg-stripes-indigo">
        <div class="light-nth" style="flex-grow: 1;">
          01
        </div>
        <div class="it" style="flex-grow: 0;">
          02
        </div>
        <div class="light-nth" style="flex-grow: 1;">
          03
        </div>
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.ls {
  border-radius: 0.5rem;
  padding: 2rem;
  .bg-stripes-indigo {
    background-color: #818cf81a;
    background-image: linear-gradient(135deg, #6366f180 10%, #0000 0, #0000 50%, #6366f180 0, #6366f180 60%, #0000 0, #0000);
    background-size: 7.07px 7.07px;
    display: flex;
    gap: 1rem;
    color: #fff;
    font-size: 0.875rem;
    line-height: 1.25rem;
    font-weight: 700;
    border-radius: 0.5rem;
  }

  .light-nth {
    padding: 1rem;
    border-radius: 0.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: #6466e9;
    box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
  }
}
.it {
  padding: 1rem;
  width: 3.5rem;
  height: 3.5rem;
  flex: none;
  border-radius: 0.5rem;
  display: flex;
  justify-content: center;
  align-items: center;
  background: #a8b4f6;
}
</style>
flex容器有3个子元素,现在,我们仅给第2个子元素设置flex-grow属性值,看看其占据尺寸有何变化。点击下面的单选框,可以看到实时的交互效果:
<script lang="ts" setup>
import { ref } from 'vue'

const flex_grow = ref(0)
</script>

<template>
  <div class="flex-dome">
    <el-radio-group v-model="flex_grow">
      <el-radio :label="0">
        flex-grow:0
      </el-radio>
      <el-radio :label="0.5">
        flex-grow:0.5
      </el-radio>
      <el-radio :label="1">
        flex-grow:1
      </el-radio>
      <el-radio :label="2">
        flex-grow:2
      </el-radio>
    </el-radio-group>
    <div class="box">
      <div class="it" data-index="1">
        <img src="https://cdn.jsdelivr.net/gh/liaoyio/imgHosting/wk/2023/user/7nvi.jpg">
      </div>
      <div class="it" data-index="2" :style="{ flexGrow: flex_grow }">
        <img src="https://cdn.jsdelivr.net/gh/liaoyio/imgHosting/wk/2023/user/6nvi.jpg">
      </div>
      <div class="it" data-index="3">
        <img src="https://cdn.jsdelivr.net/gh/liaoyio/imgHosting/wk/2023/user/9nvi.jpg">
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.box {
  display: flex;
}

.it {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 80px;
  width: 80px;
  margin: 12px;
  background-color: #818cf81a;
  background-image: linear-gradient(135deg, #6366f180 10%, #0000 0, #0000 50%, #6366f180 0, #6366f180 60%, #0000 0, #0000);
  background-size: 7.07px 7.07px;

  img{
    border-radius: 8px;
    height: 100%;
  }
}
</style>
flex容器有3个子元素,默认所有子项都设置了flex-grow:0.25,现在我们点击下面的单选框,改变第2个子元素的flex-grow属性值,看看其占据尺寸有何变化:
<script lang="ts" setup>
import { ref } from 'vue'

const flex_grow = ref(0.25)
</script>

<template>
  <div class="flex-dome">
    <el-radio-group v-model="flex_grow">
      <el-radio :label="0">
        flex-grow:0
      </el-radio>
      <el-radio :label="0.25">
        flex-grow:0.25
      </el-radio>
      <el-radio :label="0.5">
        flex-grow:0.5
      </el-radio>
      <el-radio :label="1">
        flex-grow:1
      </el-radio>
    </el-radio-group>
    <div class="box">
      <div class="it" data-index="1" style="flex-grow:0.25">
        <img src="https://cdn.jsdelivr.net/gh/liaoyio/imgHosting/wk/2023/user/7nvi.jpg">
      </div>
      <div class="it" data-index="2" :style="{ flexGrow: flex_grow }">
        <img src="https://cdn.jsdelivr.net/gh/liaoyio/imgHosting/wk/2023/user/6nvi.jpg">
      </div>
      <div class="it" data-index="3" style="flex-grow:0.25">
        <img src="https://cdn.jsdelivr.net/gh/liaoyio/imgHosting/wk/2023/user/9nvi.jpg">
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.box {
  display: flex;
}

.it {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 80px;
  width: 80px;
  margin: 12px;
  background-color: #818cf81a;
  background-image: linear-gradient(135deg, #6366f180 10%, #0000 0, #0000 50%, #6366f180 0, #6366f180 60%, #0000 0, #0000);
  background-size: 7.07px 7.07px;

  img{
    border-radius: 8px;
    height: 100%;
  }
}
</style>

TIP

此实例演示中,因为3个子项都是0.25,因此默认还剩余25%的剩余空间;如果我们选择flex-grow:0,则加起来的flex-grow0.5,因此剩余50%空间;如果我们选择flex-grow:0.5,则加起来的flex-grow1,因此没有剩余空间,同时空间占用比例为1:2:1,最终效果符合此预期;如果我们选择flex-grow:1,则加起来的flex-grow大于1,剩余空间按比例分配,为1:4:1,最终效果也确实如此。

flex-shrink

Details

shrink收缩的意思,flex-shrink主要处理当flex容器空间不足时候,单个元素的收缩比例。

flex-shrinkflex-grow很神似:

  • flex-grow 是空间足够时候如何利用空间;
  • flex-shrink 则是空间不足时候如何收缩腾出空间.
css
flex-shrink: <number>; /* 数值,默认值是 1 */

flex-shrink 不支持负值,默认值是1,也就是默认所有的flex子项都会收缩。如果设置为0,则表示不收缩,保持原始的fit-content宽度。

<script lang="ts" setup>
import { ref } from 'vue'

const flex_shrink = ref(1)
</script>

<template>
  <div class="flex flex-col">
    <el-radio-group v-model="flex_shrink">
      <el-radio :label="0">
        flex-shrink:0
      </el-radio>
      <el-radio :label="0.5">
        flex-shrink:0.5
      </el-radio>
      <el-radio :label="1">
        flex-shrink:1
      </el-radio>
      <el-radio :label="2">
        flex-shrink:2
      </el-radio>
    </el-radio-group>
    <div class="flex" style="width: 400px;">
      <div class="it">
        <img src="https://cdn.jsdelivr.net/gh/liaoyio/imgHosting/wk/2023/user/7nvi.jpg">
      </div>
      <div class="it" :style="{ flexShrink: flex_shrink }">
        <img src="https://cdn.jsdelivr.net/gh/liaoyio/imgHosting/wk/2023/user/6nvi.jpg">
      </div>
      <div class="it">
        <img src="https://cdn.jsdelivr.net/gh/liaoyio/imgHosting/wk/2023/user/9nvi.jpg">
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.box {
  display: flex;
}

.it {
  height: 80px;
  min-width: 80px;
  width: 160px;
  margin-right: 20px;
  border-radius: 8px;
  padding: 0;
  background-color: #818cf81a;
  background-image: linear-gradient(135deg, #6366f180 10%, #0000 0, #0000 50%, #6366f180 0, #6366f180 60%, #0000 0, #0000);
  background-size: 7.07px 7.07px;

  img{
    height: 80px;
    width: 80px;
    border-radius: 8px;
  }
}
</style>

flex-basis

Details

flex-basis定义了在分配剩余空间之前元素的默认大小。相当于对浏览器提前告知:浏览器兄,我要占据这么大的空间,提前帮我预留好。

css
flex-basis: <length> | auto; /* 默认值是 auto */

默认值是auto,就是自动。有设置width则占据空间就是width,没有设置就按内容宽度来。

  • 如果同时设置widthflex-basis,会忽略width
  • flex顾名思义就是弹性的意思,因此,实际上不建议对flex子项使用width属性,因为不够弹性。
  • 当剩余空间不足的时候,flex子项的实际宽度并通常不是设置的flex-basis尺寸,因为flex布局剩余空间不足的时候默认会收缩。

实例一则:

flex容器有3个子元素,现在,我们给第2个子元素设置不同的`flex-basis`属性值,看看其占据尺寸有何变化。点击下面的单选框,可以看到实时的交互效果:
<script lang="ts" setup>
import { ref } from 'vue'

const flex_basis = ref('128px')
</script>

<template>
  <div class="flex-dome">
    <el-radio-group v-model="flex_basis">
      <el-radio label="80px">
        flex-basis:80px
      </el-radio>
      <el-radio label="128px">
        flex-basis:128px
      </el-radio>
      <el-radio label="256px">
        flex-basis:256px
      </el-radio>
      <el-radio label="512px">
        flex-basis:512px
      </el-radio>
    </el-radio-group>
    <div class="box">
      <div class="it" data-index="1">
        <img src="https://cdn.jsdelivr.net/gh/liaoyio/imgHosting/wk/2023/user/7nvi.jpg">
      </div>
      <div class="it" data-index="2" :style="{ flexBasis: flex_basis }">
        <img src="https://cdn.jsdelivr.net/gh/liaoyio/imgHosting/wk/2023/user/6nvi.jpg">
      </div>
      <div class="it" data-index="3">
        <img src="https://cdn.jsdelivr.net/gh/liaoyio/imgHosting/wk/2023/user/9nvi.jpg">
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.box {
  display: flex;
  justify-content: space-between;
}

.it {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 80px;
  width: 80px;
  margin: 12px;
  background-color: #818cf81a;
  background-image: linear-gradient(135deg, #6366f180 10%, #0000 0, #0000 50%, #6366f180 0, #6366f180 60%, #0000 0, #0000);
  background-size: 7.07px 7.07px;

  img{
    border-radius: 8px;
    height: 100%;
  }
}
</style>

flex

Details

flex属性是flex-growflex-shrinkflex-basis的缩写。

css
flex: none | auto | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
  • 其中第2第3个参数(flex-shrink和flex-basis)是可选的。默认值为0 1 auto
flex 默认值为 flex: 0 1 auto;
01
02
03
给第2、3个子元素设置flex: 1 等同于 flex: 1 1 0%;
01
02
03
给第1、2个子元素设置flex: none; 等同于 flex:0 0 auto
01
02
03
<script setup lang="ts">
import { ref } from 'vue'

const flex = ref('row')
</script>

<template>
  <div>
    <div class="ls">
      <div class="pb-2">
        flex 默认值为 <code> flex: 0 1 auto; </code>
      </div>
      <div class="bg-stripes-indigo" style="flex: 0 1 auto">
        <div class="light-nth">
          01
        </div>
        <div class="light-nth" style="flex: 0 1 auto">
          02
        </div>
        <div class="light-nth" style="flex: 0 1 auto">
          03
        </div>
      </div>
      <div class="pt-8 pb-2">
        给第2、3个子元素设置<code>flex: 1</code> 等同于 <code>flex: 1 1 0%;</code>
      </div>
      <div class="bg-stripes-indigo flex">
        <div class="it">
          01
        </div>
        <div class="light-nth" style="flex: 1;">
          02
        </div>
        <div class="light-nth" style="flex: 1;">
          03
        </div>
      </div>

      <div class="pt-8 pb-2">
        给第1、2个子元素设置<code>flex: none;</code> 等同于 <code>flex:0 0 auto</code>
      </div>
      <div class="bg-stripes-indigo">
        <div class="light-nth" style="flex: none; width: 100px;">
          01
        </div>
        <div class="light-nth" style="flex: none;">
          02
        </div>
        <div class="it" style="flex: 1;">
          03
        </div>
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.ls {

  border-radius: 0.5rem;
  padding: 2rem;
  .bg-stripes-indigo {
    background-color: #818cf81a;
    background-image: linear-gradient(135deg, #6366f180 10%, #0000 0, #0000 50%, #6366f180 0, #6366f180 60%, #0000 0, #0000);
    background-size: 7.07px 7.07px;
    display: flex;
    gap: 1rem;
    color: #fff;
    font-size: 0.875rem;
    line-height: 1.25rem;
    font-weight: 700;
    border-radius: 0.5rem;
  }

  .light-nth {
    padding: 1rem;
    border-radius: 0.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: #6466e9;
    box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
  }
}
.it {
  padding: 1rem;
  width: 3.5rem;
  height: 3.5rem;
  flex: none;
  border-radius: 0.5rem;
  display: flex;
  justify-content: center;
  align-items: center;
  background: #a8b4f6;
}
</style>

align-self

Details

align-self指控制单独某一个flex子项的垂直对齐方式。

写在flex容器上的这个align-items属性,后面是items,有个s表示子项们是全体;这里是self,单独一个个体。其他区别不大,语法几乎一样:

css
align-self: auto | flex-start | flex-end | center | baseline | stretch;

唯一区别: align-self多了个auto(默认值),表示继承自flex容器的align-items属性值。

首先我们设置flex容器baseline对齐,然后点击下面的单选框,给第2个flex子项设置不同align-self属性值,观察其表现:
<script lang="ts" setup>
import { ref } from 'vue'

const align_self = ref('auto')
</script>

<template>
  <div class="flex-dome">
    <el-radio-group v-model="align_self">
      <el-radio label="auto">
        auto
      </el-radio>
      <el-radio label="flex-start">
        flex-start
      </el-radio>
      <el-radio label="flex-end">
        flex-end
      </el-radio>
      <el-radio label="center">
        center
      </el-radio>
      <el-radio label="baseline">
        baseline
      </el-radio>
      <el-radio label="stretch">
        stretch
      </el-radio>
    </el-radio-group>
    <div class="box">
      <div class="item" data-index="1">
        <img src="https://cdn.jsdelivr.net/gh/liaoyio/imgHosting/wk/2023/user/12nvi.jpg">
      </div>
      <div class="item" data-index="2" :style="{ alignSelf: align_self }">
        <img src="https://cdn.jsdelivr.net/gh/liaoyio/imgHosting/wk/2023/user/13nvi.jpg">
      </div>
      <div class="item" data-index="3">
        <img src="https://cdn.jsdelivr.net/gh/liaoyio/imgHosting/wk/2023/user/14nvi.jpg">
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.box {
  gap: 2rem;
  display: flex;
  align-items: baseline;
  border-radius: 8px;
  height: 240px;
  outline: dashed 1px;
  .item {
    border-radius: 0 !important;
    padding-bottom: 10px;
    background: orangered;
    width: 100px;
  }
}
</style>