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(反之亦然),视觉上会发生什么变化? 如果我将两者都设置为不同的值会怎样?如果它们具有相同的值会怎样? 在某些特殊情况下,使用 width 或 flex-basis 会与使用另一个产生显着差异? width 和 flex-basis 在与其他 flexbox 样式结合使用时有何不同,例如 flex-wrap、 flex-grow 和 flex-shrink? 还有其他显着差异吗?编辑/澄清:这个问题已经在What exactly flex-basis property sets? 中以不同的格式提出,但我觉得对flex-basis的差异进行了更直接的比较或总结和 width(或 height)会很好。
【问题讨论】:
Best article 解释弹性基础,弹性增长和收缩一起 【参考方案1】:考虑flex-direction
阅读您的问题时首先想到的是flex-basis
并不总是适用于width
。
当flex-direction
为row
时,flex-basis
控制宽度。
但是当flex-direction
是column
时,flex-basis
控制高度。
主要区别
以下是flex-basis
和width
/ height
之间的一些重要区别:
flex-basis
仅适用于弹性项目。 Flex 容器(也不是 flex 项)将忽略 flex-basis
,但可以使用 width
和 height
。
flex-basis
仅适用于主轴。例如,如果您在 flex-direction: column
中,则需要 width
属性来水平调整弹性项目的大小。
flex-basis
对绝对定位的弹性项目没有影响。 width
和 height
属性是必需的。 Absolutely-positioned flex items do not participate in flex layout.
通过使用flex
属性,可以将三个属性——flex-grow
、flex-shrink
和flex-basis
——巧妙地组合成一个声明。使用width
,同样的规则需要多行代码。
浏览器行为
就它们的渲染方式而言,flex-basis
和width
之间应该没有区别,除非flex-basis
是auto
或content
。
来自规范:
7.2.3. The
flex-basis
property对于除
auto
和content
之外的所有值,flex-basis
在水平书写模式下的解析方式与width
相同。
但auto
或content
的影响可能很小或根本没有影响。更多来自规范:
auto
当在弹性项目上指定时,
auto
关键字检索值 的主要尺寸属性作为使用的flex-basis
。如果该值为 本身auto
,则使用值为content
。
content
表示根据弹性项目的内容自动调整大小。
注意:该值在 Flexible 的初始版本中不存在 Box Layout,因此一些较旧的实现将不支持它。 使用
auto
和一个auto
的主要尺寸(width
或height
)。
因此,根据规范,flex-basis
和 width
解析相同,除非 flex-basis
是 auto
或 content
。在这种情况下,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: 100px
或width: 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-basis
和white-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
,使用float
和inline-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-grow
、flex-shrink
和flex-basis
进行实验
(或简写 flex :fg fs fb
)...可以产生一些有趣的结果。
【讨论】:
我发现通常在 flex 上下文中,flex-basis
和 width / height
都设置元素的初始/起始大小。例如flex-basis: 200px
基本上与flex-basis: auto; width: 200px;
工作方式相同。看起来当flex-basis
未设置为auto
时,它只是覆盖width / height
值。我看到的唯一区别是处理内容溢出的方式。【参考方案3】:
如果我们忽略灵活大小方面 (flex-grow: 0; flex-shrink: 0;
),似乎没有人提到 flex-basis
和 width
(或 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-height
或min-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 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章