L
L
i
i
r
r
o
o
u
u
s
s
c
c
o
o
d
d
i
i
n
n
g
g
介绍一下css中的弹性盒子常用属性

弹性盒子

弹性盒子是前端开发十分常用的一种布局,即简单又实用,下文将介绍常用的弹性盒子的属性

flex容器

文档中采用了 flex-box 的区域就叫做 flex 容器。为了创建 flex 容器,我们把一个容器的 display 属性值改为 flex 或者 inline-flex
完成这一步之后,容器中的直系子元素就会变为 flex 元素

由于所有 CSS 属性都会有一个初始值,所以 flex 容器中的所有 flex 元素都会有下列行为:

元素排列为一行(flex-direction 属性的初始值是 row)
元素从主轴的起始线开始
元素不会在主维度方向拉伸,但是可以缩小
元素被拉伸来填充交叉轴大小

主轴和交叉轴

主轴和交叉轴示意图

图中的main axis就是主轴的意思,cross axis就是交叉轴的意思

由上图我们可以知道,弹性盒子的基本结构,就是两个轴,一个是主轴,一个是交叉轴
弹性盒子解决的问题也就是设计盒子在这两个轴上的对齐方式和元素大小

flex-direction

这个属性决定了弹性盒子主轴的对齐方式,默认为 row(水平方向)

css 复制代码
.box{
  display: flex;
  flex-direction: row;
}

可选值还有 column(竖直方向)

对齐方式

对齐方式决定不同轴元素排列方式,即主轴和交叉轴上的元素如何排列
决定主轴排列方式的csss属性是 justify-content
决定交叉轴排列方式的csss属性是 align-items

我们给几个例子演示一下,就可以很好理解了

<style> .flex-box { height: 300px; display: flex; flex-direction: column; justify-content: start; align-items: center; background-color: rebeccapurple; } .flex-box div { background-color: pink; width: 50px; height: 50px; margin: 10px; } </style>

主轴start,交叉轴center

html 复制代码
  <body>
    <div class="flex-box">
      <div>item 1</div>
      <div>item 2</div>
      <div>item 3</div>
    </div>
  </body>

<style>
  .flex-box {
    height: 300px;
    display: flex;
    flex-direction: column;
    justify-content: start;
    align-items: center;
    background-color: rebeccapurple;
  }
  .flex-box div {
    background-color: red;
    width: 50px;
    height: 50px;
    margin-top: 10px;
  }
</style>

我们设置的主轴方向flex-directioncolumn,然后它的对齐方式是start,也就是从头开始排列,然后我们的交叉轴现在就是row(水平方向),元素对齐方式是center,也就是水平方向的元素居中对齐

tip:如果div盒子宽度不够,是无法实现水平居中的,所以当元素对齐出现了问题,建议打开f12看看最外层盒子的大小是否合适
其余属性参考官方文档
justify-content
align-items

flex中justify导致的元素溢出问题

问题引入

我们先看两个例子

例一

<style> .over-box { display: flex; justify-content: center; align-items: center; background-color: blue; width: 200px; } .over-box div { background-color: pink; width: 80px; height: 80px; margin: 5px; flex-shrink:0; } </style>

例二:

html 复制代码
  <body>
    <div class="over-box">
      <div></div>
      <div></div>
      <div></div>
      <!-- 例二比例一多一个div -->
    </div>
  </body>

<style>
  .over-box {
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: blue;
    width: 200px;
    /* overflow: auto; */
  }
  .over-box div {
    background-color: pink;
    width: 80px;
    height: 80px;
    flex-shrink: 0; 
   /* 设置flex-shrink防止子元素缩小以适应盒子大小 */
  }
</style>

我们发现例二的盒子溢出了,我们为其设置overflow试试看能不能解决这个问题

解决了溢出问题,但是左半边被截断了

针对这个问题有几种解决方式

1.设置safe模式

item 1
item 2
item 3
<style> .over-box2 { display: flex; justify-content: safe center; align-items: center; background-color: blue; width: 200px; overflow: auto; } .over-box2 div { background-color: pink; width: 80px; height: 80px; flex-shrink: 0; } </style>
html 复制代码
  <body>
    <div class="over-box2">
      <div>item 1</div>
      <div>item 2</div>
      <div>item 3</div>
    </div>
  </body>

<style>
  .over-box2 {
    display: flex;
    justify-content: safe center;
    align-items: center;
    background-color: blue;
    width: 200px;
    overflow: auto;
  }
  .over-box2 div {
    background-color: pink;
    width: 80px;
    height: 80px;
    flex-shrink: 0;
  }
</style>

2.使用 justify-content:start;

item 1
item 2
item 3
<style> .over-box3 { display: flex; justify-content: start; align-items: center; background-color: blue; width: 200px; overflow: auto; } .over-box3 div { background-color: pink; width: 80px; height: 80px; margin: auto; flex-shrink: 0; } </style>
html 复制代码
  <body>
    <div class="over-box3">
      <div>item 1</div>
      <div>item 2</div>
      <div>item 3</div>
    </div>
  </body>

<style>
  .over-box3 {
    display: flex;
    justify-content: start;
    align-items: center;
    background-color: blue;
    width: 200px;
    overflow: auto;
  }
  .over-box3 div {
    background-color: pink;
    width: 80px;
    height: 80px;
    margin: auto;
    flex-shrink: 0;
  }
</style>

解决了由justify-content: center;导致的溢出问题,但是缺点就是无法实现居中对齐了

3.使用margin:auto

item 1
item 2
item 1
item 2
item 3
<style> .over-box4 { display: flex; align-items: center; background-color: blue; width: 200px; overflow: auto; } .over-box4 div { background-color: pink; width: 80px; height: 80px; margin: auto; flex-shrink: 0; } </style>

这个方法的好处就是可以实现宽度不足时居中

以上参考chokcoco大佬的文章
Flex 布局下居中溢出滚动截断问题

flex-basis

当一个元素同时被设置了 flex-basis (除值为 auto 外) 和 width (或者在 flex-direction: column 情况下设置了height) , flex-basis 具有更高的优先级

定义:
flex-basis 设置 flex 项目的初始主尺寸。对于行方向的 flex 容器,它定义宽度;对于列方向的 flex 容器,它定义高度

可能的值:

  1. <length>:如 100px, 5em 等具体的长度值
  2. <percentage>:相对于其父 flex 容器主尺寸的百分比
  3. auto:基于 flex 项目的内容自动调整大小
  4. content:基于 flex 项目的内容设置大小(这与 auto 略有不同,但支持不太广泛)
    默认值:
    flex-basis 的默认值是 auto。

优先级:
当同时设置了 width(或 height)和 flex-basis 时,flex-basis 优先级更高

与 flex-grow 和 flex-shrink 的关系:
flex-basis 定义了项目的基本大小,而 flex-grow 和 flex-shrink 则决定了项目如何增大或缩小

特殊值 0:
flex-basis: 0 会导致项目完全依赖 flex-grow 来决定大小,忽略内容大小。

与主轴方向的关系:
flex-basis 总是参照主轴。如果更改 flex-direction,flex-basis 的作用方向也会改变。

flex-grow

flex-grow:这个属性规定了 flex-grow 项在 flex 容器中分配剩余空间的相对比例。 主尺寸是项的宽度或高度,这取决于flex-direction值

剩余空间是 flex 容器的大小减去所有 flex 项的大小加起来的大小。

如果所有的兄弟项目都有相同的 flex-grow 系数,那么所有的项目将剩余空间按相同比例分配;否则将根据不同的 flex-grow 定义的比例进行分配。

flex-grow 与其他的 flex 属性 flex-shrink 和 flex-basis 一起使用,通常使用 flex 简写来定义,以确保所有的值都被设置。

关于flex-grow的详细

当所有 flex 子元素的 flex-grow 值之和小于 1 时:
剩余空间不会被完全分配
每个子元素获得的额外空间 = 剩余空间 * 该元素的 flex-grow 值

当所有 flex 子元素的 flex-grow 值之和大于或等于 1 时:
剩余空间会被完全分配
每个子元素获得的额外空间 = 剩余空间 * (该元素的 flex-grow 值 / 所有 flex-grow 值的总和)

下面是一个分配剩余全部空间的例子

box1
box1
<style> .container1{ height: 400px; background-color: yellow; display: flex; flex-direction: column; } </style>
html 复制代码
<body>
    <div class="container1">
        <div>box1</div>
        <div style="flex:1;background-color: blueviolet;">box1</div>
    </div>
</body>
<style>
    .container1 {
        height: 400px;
        background-color: yellow;
        display: flex;
        flex-direction: column;
    }
</style>

flex-shrink

CSS flex-shrink 属性指定了 flex 元素的收缩规则。flex 元素仅在默认宽度之和大于容器的时候才会发生收缩,其收缩的大小是依据 flex-shrink 的值。

box1
box2
box3
box4
<style> .container2 { height: 400px; background-color: red; display: flex; flex-direction: column; } .container2 div { height: 200px; } .container2 .box1 { flex-shrink: 1; background-color: gray; } .container2 .box2 { flex-shrink: 2; background-color: pink; } .container2 .box3 { flex-shrink: 3; background-color: yellow; } .container2 .box4 { flex-shrink: 4; background-color: green; } </style>
html 复制代码
<body>
    <div class="container">
        <div class="box1">box1</div>
        <div class="box2">box2</div>
        <div class="box3">box3</div>
        <div class="box4">box4</div>
    </div>
</body>
<style>
  .container2 {
        height: 400px;
        background-color: red;
        display: flex;
        flex-direction: column;
    }

    .container2 div {
        height: 200px;
    }

    .container2 .box1 {
        flex-shrink: 1;
        background-color: gray;
    }

    .container2 .box2 {
        flex-shrink: 2;
        background-color: pink;
    }

    .container2 .box3 {
        flex-shrink: 3;
        background-color: yellow;
    }

    .container2 .box4 {
        flex-shrink: 4;
        background-color: green;
    }
</style>

该情况下子元素的高度总和大于弹性盒子 弹性盒子会伸缩

伸缩之后对应的每个子元素的具体高度计算方法如下

先计算出溢出部分的总和totalOver 然后将子元素的flex-shrink相加得到totalShrink 再得到单位flex-shrink对应的缩小尺寸 preShrink = totalOver / totalOver

totalOver 400px totalShrink : 10
preShrink: 400px /10 = 40px

每个盒子实际占用空间
box1: 200px-40px = 160px;
box2: 200px-80px = 120px;
box3: 200px-120px = 80px;
box4: 200px-160px = 40px ;

注意 : 如果有某个盒子计算得到的最终结果尺寸过小,结果会不尽人意,会存在一定偏差

如果计算得到的最终结果尺寸小于项目的最小内容尺寸或明确设置的最小尺寸,浏览器会尊重这个最小尺寸限制。这可能导致实际布局与严格按 flex-shrink 计算的结果有所偏差。剩余的收缩压力会重新分配到其他项目上。浏览器会尽力平衡 flex-shrink 的计算结果、内容的可用性和整体布局的合理性。

这种行为确保了即使在极端情况下,flex 容器中的内容也能保持可读和可用

flex简写

  1. 单值,宽度/高度:flex-basis
css 复制代码
flex: 10em;
  1. 双值:flex-grow | flex-basis
css 复制代码
flex: 1 30px;
  1. 双值:flex-grow | flex-shrink
css 复制代码
flex: 2 2;
  1. 三值:flex-grow | flex-shrink | flex-basis
css 复制代码
flex: 2 2 10%;

参考资料
flex盒子的基本概念
justify-content
Flex 布局下居中溢出滚动截断问题
align-items
flex简写