Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【CSS】flex 布局 #18

Closed
Tracked by #6
swiftwind0405 opened this issue Mar 1, 2020 · 0 comments
Closed
Tracked by #6

【CSS】flex 布局 #18

swiftwind0405 opened this issue Mar 1, 2020 · 0 comments
Labels

Comments

@swiftwind0405
Copy link
Owner

swiftwind0405 commented Mar 1, 2020

image

container容器的属性

  • flex-direction:决定主轴的方向(即项目的排列方向)
  • flex-wrap:决定容器内项目是否可换行
  • flex-flow:以上两个属性的简写形式
  • justify-content:指定主轴方向项目的对齐方式
  • align-items:指定交叉轴上项目的对齐方式
  • align-content:多根轴线指定对齐方式

item项目的属性

  • flex-grow:指定当前项如何扩展
  • flex-shrink:指定当前项如何收缩
  • flex-basis:指定分配剩余空间之前当前项的初始大小
  • flex:以上三个属性的简写形式
  • order:指定当前项在容器中出现的次序

最高优先级:flex-basic

在分配多余空间前,指定项目占据的主轴空间。浏览器根据这个属性,计算主轴是否有多余空间,默认值为auto,即项目的本来大小。 flex-items的width属性和flex-basis属性都在的情况下,容器的换行以flex-basis的值为标准

flex-basis 规定的是子元素的基准值。所以是否溢出的计算与此属性息息相关。flex-basis 规定的范围取决于 box-sizing。这里主要讨论以下 flex-basis 的取值情况:

  • auto:首先检索该子元素的主尺寸,如果主尺寸不为 auto,则使用值采取主尺寸之值;如果也是 auto,则使用值为 content。

  • content:指根据该子元素的内容自动布局。有的用户代理没有实现取 content 值,等效的替代方案是 flex-basis 和主尺寸都取 auto。

  • 百分比:根据其包含块(即伸缩父容器)的主尺寸计算。如果包含块的主尺寸未定义(即父容器的主尺寸取决于子元素),则计算结果和设为 auto 一样。

特例:flex-basis: 0

假设把所有可伸缩项的flex-basis都设置为0,那就意味着这些项不会参与第一次容器空间的分配。

什么意思呢?如前所述,flex-basis值决定了CSS如何确定各伸缩项在容器中的初始宽度。确定各项初始宽度是对容器空间的首次分配。

如果初次分配各项初始宽度为0( flex-basis: 0; ),那就是说容器的全部宽度都会进入二次分配环节。利用这一点,可以实现各伸缩项宽度的绝对平均化

flex-basis: 0flex-basis: 0% 的视觉效果和最终计算值是一样的,只不过是计算过程不同。百分比的计算值是以父类容器的宽度为基数计算的,而长度值 0 直接取值不用再计算,但是 0% 和 0 的最终计算值都是 0px。

项目最终宽度的计算方式

计算公式:
image

扩展:flex-grow

当前项可分得的剩余空间 = ( 当前项flex-grow值/所有项flex-grow值之和 ) * 剩余总宽度

计算demo可以看这个:flex-grow-calc-demo1

还有一种情况:
当所有元素的 flex-grow 之和小于 1 的时候(注意是 1,也就是说每个元素的 flex-grow 都是一个小数如 0.2 这样的),上面式子中的 sum 将会使用 1 来参与计算,而不论它们的和是多少。也就是说,当所有的元素的 flex-grow 之和小于 1 的时候,剩余空间不会全部分配给各个元素。

实际上用来分配的空间是 sum(flex-grow) / 1 * 剩余空间 ,这些用来分配的空间依然是按 flex-grow 的比例来分配。

计算demo可以看这个:flex-grow-calc-demo2

另外,flex-grow 还会受到 max-width 的影响。如果最终 grow 后的结果大于 max-width 指定的值,max-width 的值将会优先使用。同样会导致父元素有部分剩余空间没有分配。

收缩:flex-shrink

当前项收缩的宽度 = ( 当前项flex-shrink * 当前项flex-basic / 所有项flex-shrink  与各自flex-basic乘积之和 ) * 需收缩的总宽度

这里需要注意当前项的flex-basic的取值,可见上方的flex-basic内容,最后收缩完该项的width就是原本的width减去上面计算出来需要收缩的宽度。

计算demo可以看这个:flex-shrink-calc-demo1

同样,当所有元素的 flex-shrink 之和小于 1 时,计算方式也会有所不同:

此时,并不会收缩所有的空间,而只会收缩 flex-shrink 之和相对于 1 的比例的空间。

计算demo可以看这个:flex-shrink-calc-demo2

当然,类似 flex-grow,flex-shrink 也会受到 min-width 的影响。

总结:
虽然上面的公式看起来很复杂,其实计算过程还是比较简单的:如果所有元素的 flex-grow/shrink 之和大于等于 1,则所有子元素的尺寸一定会被调整到适应父元素的尺寸(在不考虑 max/min-width/height 的前提下),而如果 flex-grow/shrink 之和小于 1,则只会 grow 或 shrink 所有元素 flex-grow/shrink 之和相对于 1 的比例。grow 时的每个元素的权重即为元素的 flex-grow 的值;shrink 时每个元素的权重则为元素 flex-shrink 乘以 width 后的值。

那么为什么 grow 只用管各个项的 grow 值按比例分配,而 shrink 却额外还要考虑 flex-basic 的值呢?

侧轴:align-self

弹性布局默认不改变项目的宽度,但是它默认改变项目的高度。如果项目没有显式指定高度,就将占据容器的所有高度。而 align-self 属性可以改变这种行为。

align-self 属性可以取四个值:

  • flex-start:顶边对齐,高度不拉伸
  • flex-end:底边对齐,高度不拉伸
  • center:居中,高度不拉伸
  • stretch:默认值,高度自动拉伸

如果项目很多,一个个地设置 align-self 属性就很麻烦。这时,可以在容器元素(本例为表单)设置 align-items 属性,它的值被所有子项目的 align-self 属性继承。

关于 flex 的其它相关问题

  • flex 上下文中垂直 margin 不会合并
  • flex 主轴方面上子元素的 margin 如果设置为 auto,其该方向上的 margin 是会尽量大的,可以利用这个特性来做对齐
  • 设置了 flex 布局之后,子元素的 floatclearvertical-align 的属性将失效

工具

参考资料

  1. Flexbox,终于可以承认自己明白了
  2. Flex 布局教程:语法篇
  3. Flexbox 布局的最简单表单
  4. 重点来了,flex-shrink到底是如何计算的呢?
  5. 详解 flex-grow 与 flex-shrink
@swiftwind0405 swiftwind0405 changed the title 【Day08】flex 布局 【CSS】flex 布局 Apr 29, 2020
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant