flex-basis 和 width 有啥区别?

Posted

技术标签:

【中文标题】flex-basis 和 width 有啥区别?【英文标题】:What are the differences between flex-basis and width?flex-basis 和 width 有什么区别? 【发布时间】:2016-03-24 22:58:42 【问题描述】:

有关于此的问题和文章,但据我所知没有任何结论。我能找到的最好的总结是

flex-basis 允许您在计算其他任何内容之前指定元素的初始/起始大小。它可以是百分比或绝对值。

...它本身并没有说明设置了 flex-basis 的元素的行为。以我目前对 flexbox 的了解,我不明白为什么它也不能描述 width

我想知道 flex-basis 在实践中与 width 到底有什么不同:

如果我将 width 替换为 flex-basis(反之亦然),视觉上会发生什么变化? 如果我将两者都设置为不同的值会怎样?如果它们具有相同的值会怎样? 在某些特殊情况下,使用 widthflex-basis 会与使用另一个产生显着差异? widthflex-basis 在与其他 flexbox 样式结合使用时有何不同,例如 flex-wrap flex-growflex-shrink? 还有其他显着差异吗?

编辑/澄清:这个问题已经在What exactly flex-basis property sets? 中以不同的格式提出,但我觉得对flex-basis的差异进行了更直接的比较或总结和 width(或 height)会很好。

【问题讨论】:

Best article 解释弹性基础,弹性增长和收缩一起 【参考方案1】:

考虑flex-direction

阅读您的问题时首先想到的是flex-basis 并不总是适用于width

flex-directionrow 时,flex-basis 控制宽度。

但是当flex-directioncolumn 时,flex-basis 控制高度。


主要区别

以下是flex-basiswidth / height 之间的一些重要区别:

flex-basis 仅适用于弹性项目。 Flex 容器(也不是 flex 项)将忽略 flex-basis,但可以使用 widthheight

flex-basis 仅适用于主轴。例如,如果您在 flex-direction: column 中,则需要 width 属性来水平调整弹性项目的大小。

flex-basis 对绝对定位的弹性项目没有影响。 widthheight 属性是必需的。 Absolutely-positioned flex items do not participate in flex layout.

通过使用flex 属性,可以将三个属性——flex-growflex-shrinkflex-basis——巧妙地组合成一个声明。使用width,同样的规则需要多行代码。


浏览器行为

就它们的渲染方式而言,flex-basiswidth 之间应该没有区别,除非flex-basisautocontent

来自规范:

7.2.3. The flex-basis property

对于除autocontent 之外的所有值,flex-basis 在水平书写模式下的解析方式与width 相同。

autocontent 的影响可能很小或根本没有影响。更多来自规范:

auto

当在弹性项目上指定时,auto 关键字检索值 的主要尺寸属性作为使用的flex-basis。如果该值为 本身auto,则使用值为content

content

表示根据弹性项目的内容自动调整大小。

注意:该值在 Flexible 的初始版本中不存在 Box Layout,因此一些较旧的实现将不支持它。 使用auto 和一个 auto 的主要尺寸(widthheight)。

因此,根据规范,flex-basiswidth 解析相同,除非 flex-basisautocontent。在这种情况下,flex-basis 可能会使用内容宽度(据推测,width 属性也会使用)。


flex-shrink 因素

记住弹性容器的初始设置很重要。其中一些设置包括:

flex-direction: row - 弹性项目将水平对齐 justify-content: flex-start - 弹性项目将堆叠在主轴线的开头 align-items: stretch - 弹性项目将扩展以覆盖容器的交叉大小 flex-wrap: nowrap - 弹性项目被强制保留在一行中 flex-shrink: 1 - 允许收缩的弹性项目

注意最后的设置。

因为弹性项目默认允许收缩(防止它们溢出容器),所以指定的flex-basis / width / height 可能会被覆盖。

例如flex-basis: 100pxwidth: 100px,加上flex-shrink: 1,不一定是100px。

要渲染指定的宽度——并保持固定——你需要禁用收缩:

div 
   width: 100px;
   flex-shrink: 0;
  

div 
  flex-basis: 100px;
  flex-shrink: 0;

或者,按照规范的建议:

flex: 0 0 100px;    /* don't grow, don't shrink, stay fixed at 100px */

7.2. Components of Flexibility

鼓励作者使用flex 简写来控制灵活性 而不是直接使用它的速记属性,作为速记 正确重置任何未指定的组件以适应 common uses。


浏览器错误

某些浏览器在调整嵌套弹性容器中弹性项目的大小时遇到​​问题。

flex-basis 在嵌套的弹性容器中被忽略。 width 有效。

使用flex-basis 时,容器会忽略其子级的大小,子级会溢出容器。但是使用width 属性,容器会尊重其子级的大小并相应地扩展。

参考资料:

Chrome does not expand flex parent according to children's content Flex item overflowing when using flex-basis Difference between width and flex-basis Flex-basis is being ignored when sizing nested flex containers. flex-basis:100px does something different from width:100px+flex-basis:auto

例子:

https://jsfiddle.net/t419zhra/(来源:@Dremora) https://codepen.io/anon/pen/NVxaoy(来源@Daniel) https://jsfiddle.net/voc9grx6/(来源:Chromium Bugs) https://jsfiddle.net/qjpat9zk/(来源:Chromium Bugs)

使用flex-basiswhite-space: nowrap 的弹性项目溢出inline-flex 容器。 width 有效。

似乎设置为inline-flex 的弹性容器在使用white-space: nowrap 渲染同级时无法识别子级上的flex-basis(尽管它可能只是宽度未定义的项目)。容器不会扩展以容纳项目。

但是当使用width 属性而不是flex-basis 时,容器会尊重其子级的大小并相应地扩展。这在 IE11 和 Edge 中不是问题。

参考资料:

inline flex container width not growing Inline flex container (display: inline-flex) is expanding the full width of parent container

例子:

https://jsfiddle.net/p18h0jxt/1/(来自上面的第一篇文章)

flex-basis(和flex-grow)不适用于表格元素

参考资料:

Why does flex-box work with a div, but not a table? Why doesn't flex-grow: 1 work for a table in Safari?(和 Edge)

当祖父容器是收缩以适应元素时,flex-basis 在 Chrome 和 Firefox 中失败。该设置在 Edge 中运行良好。

Absolutely positioned container not expanding width to fit flexbox content

就像上面链接中的示例一样,涉及position: absolute,使用floatinline-block,也会呈现相同的有缺陷的输出(jsfiddle demo)。


影响 IE 10 和 11 的错误:

flex shorthand declarations with unitless flex-basis values are ignored flex-basis doesn't account for box-sizing: border-box flex-basis doesn't support calc() Importance is ignored on flex-basis when using flex shorthand

【讨论】:

min-width:100px; 怎么样?可以选择禁用收缩吗? @Mori,是的,flex-shrink 停在min-width。等效的 flex 规则是 flex: 1 0 100px flex: 1 0 100px 导致相同的结果,但我不确定您所说的“等效”是什么意思。 我的意思是我们为什么不认为它等于flex: 0 0 100px,例如? @Mori,因为那样它就等于 width。它需要 flex-grow: 1 组件来允许元素从 flex-basis 设置的最小宽度开始增长。【参考方案2】:

除了 Michael_B 的出色总结之外,值得重复一下:

flex-basis 允许您在计算其他任何内容之前指定元素的 初始/起始 大小。它可以是百分比或绝对值。

这里的重要部分是初始

就其本身而言,这确实会解析为宽度/高度直到其他 flex 增长/收缩属性开始发挥作用。

所以。一个孩子

.child 
 flex-basis:25%;
 flex-grow:1;

最初将是 25% 宽,但随后会立即尽可能扩大,直到考虑到其他元素。如果没有..它将是 100% 宽/高。

快速演示:

.flex 
  width: 80%;
  margin: 1em auto;
  height: 25px;
  display: flex;
  background: rebeccapurple;

.child 
  flex-basis: auto;
  /* default */
  background: plum;

.value 
  flex-basis: 25%;

.grow 
  flex-grow: 1;
<div class="flex">
  <div class="child auto">Some Content</div>
</div>
<div class="flex">
  <div class="child value">Some Content</div>
</div>
<div class="flex">
  <div class="child grow">Some Content</div>
</div>

flex-growflex-shrinkflex-basis 进行实验 (或简写 flex :fg fs fb)...可以产生一些有趣的结果。

【讨论】:

我发现通常在 flex 上下文中,flex-basiswidth / height 都设置元素的初始/起始大小。例如flex-basis: 200px 基本上与flex-basis: auto; width: 200px; 工作方式相同。看起来当flex-basis 未设置为auto 时,它只是覆盖width / height 值。我看到的唯一区别是处理内容溢出的方式。【参考方案3】:

如果我们忽略灵活大小方面 (flex-grow: 0; flex-shrink: 0;),似乎没有人提到 flex-basiswidth(或 height,取决于当前的写作模式)之间存在一个关键区别。

这源于 Flex Layout 中的异常,即 flex 项的自动最小尺寸默认为 min-content 而不是通常的零。换句话说,默认的min-width: auto 计算为min-content 而不是0

结果是,flex-basis(默认情况下)被min-content 绑定在下面。如果您指定的值小于min-content,例如flex-basis: 0,它将计算为min-content。这实质上意味着(默认情况下)您不能使框的内容溢出,因为框至少具有内容的大小。

这是与width 的关键区别,因为min-width 默认为0,它可以任意缩小框(默认情况下)。如果width的值小于min-content,内容会溢出框。

规范中提到了此行为,但仅在7.1.1. Basic Values of flex末尾错误位置的以下注释中隐含。

默认情况下,弹性项目不会缩小到其最小内容大小(最长单词或固定大小元素的长度)以下。要更改此设置,请设置 min-width 或 min-height 属性。 (参见 §4.5 弹性项目的自动最小尺寸。)

正如评论中提到的,设置最小尺寸会降低界限,将其设置为零会有效地禁用它,使flex-basis 再次按预期运行。

但也有缺点。首先,主轴没有最小尺寸属性。您必须为当前的flex-direction 使用正确的min-width/min-heightmin-block-size/min-inline-size 属性。如果您更改了flex-direction,则需要再次找到正确的最小尺寸属性。

其次,flex-basis 不能再用于将空间分配给按比例大小的框,而不是简单地增加它们的初始大小。更多详情请参阅规范中的Figure 7。

这是一个最小的例子。设置 min-width: 0 以使 flex-basis 再次按预期运行。

.container 
  display: flex;


.container div 
  background-color: lightgrey;
  border: 1px solid black;
  margin: 0 10px;
  /* disable any flexible sizing */
  flex-grow: 0;
  flex-shrink: 0;
  /* TOGGLE ME */
  /* min-width: 0; */


.mincontent 
  width: min-content;


.smallerflexbasis 
  flex-basis: 3ex;


.smallerwidth 
  width: 3ex;
<div class="container">
  <div class="mincontent">Lorem ipsum</div>
  <div class="smallerflexbasis">Lorem ipsum</div>
  <div class="smallerwidth">Lorem ipsum</div>
</div>

【讨论】:

【参考方案4】:

可能是最重要的一点要补充:

如果浏览器不支持flex怎么办?在这种情况下,width/height 接管并应用它们的值。

在元素上定义width/height 是一个非常好的想法——几乎是必不可少的,即使你对flex-basis 有一个完全不同的值。记得通过禁用 display:flex 进行测试,然后看看你会得到什么。

【讨论】:

在各大浏览器中,唯一不支持flex属性的是IEcaniuse.com/#search=flex @Michael_B 当然,也许只有我一个人,但我也必须支持移动浏览器,包括 Nintendo 3DS 浏览器,它绝对不支持flex【参考方案5】:

如果你在包装,它会有所不同。

说,你将一个孩子设置为width:0 并期望它自动换行,这不会发生。但是使用flex-basis:0 它会自动换行。 (前提是溢出没有隐藏)

【讨论】:

【参考方案6】:

如果你设置了一个div的min-width:600px,如果窗口大小低于600px,你会看到一个水平滚动条,这不是一个好的用户体验设计。

如果您设置它的flex-basis:600px,如果窗口大小低于 600 像素,则该框将缩小,您将看不到水平条。

请注意,flex-basis 仅适用于弹性项目。

【讨论】:

以上是关于flex-basis 和 width 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

flex-basis和width的关系

究竟啥是 flex-basis 属性集?

互斥锁和临界区有啥区别?

width、naturalWidth 和 clientWidth 有啥区别?

关于flex的三属性2--flex-basis

uc/os进中断与进临界区有啥区别?