繁体   English   中英

flex-grow 没有按预期调整弹性项目的大小

[英]flex-grow not sizing flex items as expected

似乎 flex div 中的内容会影响其关于flex-grow属性的计算大小。 难道我做错了什么?

在下面提供的小提琴中,您会看到一个数字键盘。 除底行外,所有行都包含 3 个数字。 该行的 '0' 应该是 2 个数字的宽度,因此flex-grow: 2和 ':' (冒号)是 1 个数字的大小,因此flex-grow: 1

我在这里错过了什么吗?

“0”的右侧应与其上方的 8、5 和 2 对齐。 有点过时了

在此处输入图片说明

 .numbers { display: flex; flex-direction: column; } .row { display: flex; flex-direction: row; flex-grow: 1; justify-content: space-between; } .button { display: flex; flex-grow: 1; justify-content: center; align-items: center; margin: 5px; border-radius: 5px; border: 1px solid gray; background: rgba(255, 255, 255, 0.2); cursor: pointer; } .button#number0 { flex-grow: 2; } .button#colon { flex-grow: 1; }
 <div class="numbers"> <div class="row"> <div class="button number" id="number1">1</div> <div class="button number" id="number2">2</div> <div class="button number" id="number3">3</div> </div> <div class="row"> <div class="button number" id="number4">4</div> <div class="button number" id="number5">5</div> <div class="button number" id="number6">6</div> </div> <div class="row"> <div class="button number" id="number7">7</div> <div class="button number" id="number8">8</div> <div class="button number" id="number9">9</div> </div> <div class="row"> <div class="button number" id="number0">0</div> <div class="button" id="colon">:</div> </div> </div>

https://jsfiddle.net/0r4hemdu/

简短分析

问题是第 1-3 行有两个水平边距,而第 4 行只有一个。

在此处输入图片说明

每个水平边距为 10 像素,第 4 行的可用空间比其他行多 10 像素。 这会破坏列的对齐方式。

因为flex-grow仅适用于可用空间,并且受内容和边距的影响很大,所以它不是调整 flex 项目大小的最安全方法。

试试flex-basis 将此添加到您的代码中:

.button    { flex-basis: 33.33%; }
#number0   { flex-basis: calc(66.67% + 10px); }
*          { box-sizing: border-box; }

 .numbers { display: flex; flex-direction: column; } .row { display: flex; flex-direction: row; flex-grow: 1; justify-content: space-between; } .button { display: flex; flex-basis: 33.33%; justify-content: center; align-items: center; margin: 5px; border-radius: 5px; border: 1px solid gray; background: rgba(255, 255, 255, 0.2); cursor: pointer; } #number0 { flex-basis: calc(66.67% + 10px); } * { box-sizing: border-box; }
 <div class="numbers"> <div class="row"> <div class="button number" id="number1">1</div> <div class="button number" id="number2">2</div> <div class="button number" id="number3">3</div> </div> <div class="row"> <div class="button number" id="number4">4</div> <div class="button number" id="number5">5</div> <div class="button number" id="number6">6</div> </div> <div class="row"> <div class="button number" id="number7">7</div> <div class="button number" id="number8">8</div> <div class="button number" id="number9">9</div> </div> <div class="row"> <div class="button number" id="number0">0</div> <div class="button" id="colon">:</div> </div> </div>


扩展分析

你写了:

似乎 flex div 中的内容会影响其关于flex-grow属性的计算大小。 难道我做错了什么?

问题的根源不是 flex 项目内的内容。

你写了:

在下面提供的小提琴中,您会看到一个数字键盘。 除底行外,所有行都包含 3 个数字。 该行应该有 '0' 是 2 个数字的宽度,因此flex-grow: 2和 ':' 是 1 个数字的大小,因此flex-grow: 1 我在这里错过了什么吗?

是的。 您对flex-grow属性的解释不正确。 flex-grow不用于定义弹性项目的大小。 它的工作是在项目之间分配 flex 容器中的可用空间。

通过将flex-grow: 1应用于一组 flex 项目,您是在告诉他们在它们之间均匀分配可用空间。 这就是为什么在您的演示中,第 1、2 和 3 行具有相同大小的弹性项目。

当您应用flex-grow: 2 ,您是在告诉 flex 项目消耗的可用空间是使用flex-grow: 1项目的两倍。

但是上面行的第二个 10px 边距在哪里影响第 4 行的布局?

在此处输入图片说明

第 4 行的对齐关闭的原因是第 4 行的边距比其他行少一个,这意味着第 4 行的可用空间比其他行多 10px。

您会注意到,如果您删除边距规则,您将获得所需的对齐方式。

 .numbers { display: flex; flex-direction: column; } .row { display: flex; flex-direction: row; flex-grow: 1; justify-content: space-between; } .button { display: flex; flex-grow: 1; justify-content: center; align-items: center; /* margin: 5px; */ border-radius: 5px; border: 1px solid gray; background: rgba(255, 255, 255, 0.2); cursor: pointer; } .button#number0 { flex-grow: 2; } .button#colon { flex-grow: 1; }
 <div class="numbers"> <div class="row"> <div class="button number" id="number1">1</div> <div class="button number" id="number2">2</div> <div class="button number" id="number3">3</div> </div> <div class="row"> <div class="button number" id="number4">4</div> <div class="button number" id="number5">5</div> <div class="button number" id="number6">6</div> </div> <div class="row"> <div class="button number" id="number7">7</div> <div class="button number" id="number8">8</div> <div class="button number" id="number9">9</div> </div> <div class="row"> <div class="button number" id="number0">0</div> <div class="button" id="colon">:</div> </div> </div>


那么第四行到第二个 10px 边距会发生什么?

它被两个弹性项目吸收。

以下是flex-grow如何分配第四行的额外空间:

  • 左侧的 Flex 项目(内容为“0”)具有flex-grow: 2 .button#number0在您的代码中。)
  • Flex 项目右侧(内容为“:”)具有flex-grow: 1 .button#colon在您的代码中。)
  • 第二个项目间边距仅出现在包含三个 flex 项目的行上,宽度为 10px。 (代码说每个项目周围有 5px,但在 CSS 中水平边距永远不会折叠。此外,在 flexbox 中,没有边距折叠。)
  • flex-grow值的总和是三个。 那么让我们将 10px 除以 3。现在我们知道 1 的比例是 3.33px。
  • 因此,flex item left 获得 6.66px 的额外空间,flex item right 获得 3.33px。
  • 假设左边的 flex item 有flex-grow: 3 然后 flex item left 将获得 7.5px,flex item right 将获得 2.5px。

你问题的最后一部分说:

“0”的右侧应与其上方的 8、5 和 2 对齐。 有点过时了

因为flex-grow仅适用于可用空间,并且受内容和边距的影响很大,所以它不是调整 flex 项目大小的最安全方法。

试试flex-basis 将此添加到您的代码中:

.button    { flex-basis: 33.33%; }
#number0   { flex-basis: calc(66.67% + 10px); }
*          { box-sizing: border-box; }

 .numbers { display: flex; flex-direction: column; } .row { display: flex; flex-direction: row; flex-grow: 1; justify-content: space-between; } .button { display: flex; flex-basis: 33.33%; justify-content: center; align-items: center; margin: 5px; border-radius: 5px; border: 1px solid gray; background: rgba(255, 255, 255, 0.2); cursor: pointer; } #number0 { flex-basis: calc(66.67% + 10px); } * { box-sizing: border-box; }
 <div class="numbers"> <div class="row"> <div class="button number" id="number1">1</div> <div class="button number" id="number2">2</div> <div class="button number" id="number3">3</div> </div> <div class="row"> <div class="button number" id="number4">4</div> <div class="button number" id="number5">5</div> <div class="button number" id="number6">6</div> </div> <div class="row"> <div class="button number" id="number7">7</div> <div class="button number" id="number8">8</div> <div class="button number" id="number9">9</div> </div> <div class="row"> <div class="button number" id="number0">0</div> <div class="button" id="colon">:</div> </div> </div>

jsFiddle 演示


参考:


额外:CSS 网格解决方案

随着 CSS Grid 的出现,整个布局的代码可以大大简化。

 .numbers { display: grid; grid-template-columns: repeat(auto-fill, minmax(26%, 1fr)); grid-gap: 10px; } #number0 { grid-column: span 2; } /* non-essential decorative styles */ .button { display: flex; justify-content: center; align-items: center; border-radius: 5px; border: 1px solid gray; }
 <div class="numbers"> <div class="button number" id="number1">1</div> <div class="button number" id="number2">2</div> <div class="button number" id="number3">3</div> <div class="button number" id="number4">4</div> <div class="button number" id="number5">5</div> <div class="button number" id="number6">6</div> <div class="button number" id="number7">7</div> <div class="button number" id="number8">8</div> <div class="button number" id="number9">9</div> <div class="button number" id="number0">0</div> <div class="button" id="colon">:</div> </div>

更新 3:

我想出了另一种方法来摆脱错位。

此版本与 2:nd 更新一起使用原始 html 不变,并使用伪元素创建按钮,包括按钮悬停/点击效果。

flex版本

 .row { width: 60%; margin: auto; display: flex; } .button { flex: 0 0 33.3%; text-align: center; position: relative; padding: 10px 5px; box-sizing: border-box; pointer-events: none; } .button#number0 { flex: 0 0 66.6%; } .button:before, .button:after { content: " "; border-radius: 5px; border: 1px solid gray; cursor: pointer; position: absolute; left: 5px; top: 5px; right: 5px; bottom: 5px; pointer-events: auto; } .button:before { background: rgba(255, 255, 255, 0.9); z-index: -1 } .button:hover:before { background: rgba(0, 0, 0, 0.1); } .button:hover:after { border: 2px solid red; } .button:active:before { background: rgba(255, 0, 0, 0.5); }
 <div class="numbers"> <div class="row"> <div class="button number" id="number1">1</div> <div class="button number" id="number2">2</div> <div class="button number" id="number3">3</div> </div> <div class="row"> <div class="button number" id="number4">4</div> <div class="button number" id="number5">5</div> <div class="button number" id="number6">6</div> </div> <div class="row"> <div class="button number" id="number7">7</div> <div class="button number" id="number8">8</div> <div class="button number" id="number9">9</div> </div> <div class="row"> <div class="button number" id="number0">0</div> <div class="button" id="colon">:</div> </div> </div>

带有display: table flex版本,适用于不支持新 flexbox 模型的浏览器。

 .row { display: table; /* remove for flex only */ width: 60%; margin: auto; display: flex; } .button { display:table-cell; /* remove for flex only */ width: 33.3%; /* remove for flex only */ flex: 0 0 33.3%; text-align: center; position: relative; padding: 10px 5px; box-sizing: border-box; pointer-events: none; } .button#number0 { width: 66.6%; /* remove for flex only */ flex: 0 0 66.6%; } .button:before, .button:after { content: " "; border-radius: 5px; border: 1px solid gray; cursor: pointer; position: absolute; left: 5px; top: 5px; right: 5px; bottom: 5px; pointer-events: auto; } .button:before { background: rgba(255, 255, 255, 0.9); z-index: -1 } .button:hover:before { background: rgba(0, 0, 0, 0.1); } .button:hover:after { border: 2px solid red; } .button:active:before { background: rgba(255, 0, 0, 0.5); }
 <div class="numbers"> <div class="row"> <div class="button number" id="number1">1</div> <div class="button number" id="number2">2</div> <div class="button number" id="number3">3</div> </div> <div class="row"> <div class="button number" id="number4">4</div> <div class="button number" id="number5">5</div> <div class="button number" id="number6">6</div> </div> <div class="row"> <div class="button number" id="number7">7</div> <div class="button number" id="number8">8</div> <div class="button number" id="number9">9</div> </div> <div class="row"> <div class="button number" id="number0">0</div> <div class="button" id="colon">:</div> </div> </div>


更新 2:

除了 Michael_B 的答案,顺便说一下,它有一个很好的解释,这里是一个更新版本,它实际上确实提供了所需的对齐方式,在这种情况下,没有 1-2 px 关闭。

这是我的和 Michael_B 版本的小提琴样本图像,其中边框增加了一点以使其更容易看到未对齐。

这一切都归结于当存在border / padding时 flexbox 如何计算大小,您可以在这篇文章中阅读更多信息,其中box-sizing: border-box需要设置以及更多的调整,这在代码。

这是我的小提琴和片段

 .row { display: flex; width: calc(100% - 30px); /* 30px = the sum of the buttons margin: 5px to avoid horizontal scroll */ } .button { display: flex; flex-basis: 33.33%; flex-shrink: 0; /* we need flex-grow/shrink to be 1/0 to make it calculate the size properly */ box-sizing: border-box; /* to take out the borders when calculate the flex shrink/grow factor */ justify-content: center; align-items: center; margin: 5px; border-radius: 5px; border: 1px solid gray; background: rgba(0, 0, 0, 0.1); cursor: pointer; } #number0 { flex-basis: calc(66.66% + 10px); }
 <div class="numbers"> <div class="row"> <div class="button number" id="number1">1</div> <div class="button number" id="number2">2</div> <div class="button number" id="number3">3</div> </div> <div class="row"> <div class="button number" id="number4">4</div> <div class="button number" id="number5">5</div> <div class="button number" id="number6">6</div> </div> <div class="row"> <div class="button number" id="number7">7</div> <div class="button number" id="number8">8</div> <div class="button number" id="number9">9</div> </div> <div class="row"> <div class="button number" id="number0">0</div> <div class="button" id="colon">:</div> </div> </div>


更新:

flex版本,使用伪元素对现有 html 结构进行了微小更改。

 .row { display: flex; } .button { flex: 0 0 33.3%; } .button:after { content: attr(data-nr); display: block; border-radius: 5px; border: 1px solid gray; background: rgba(255, 255, 255, 0.9); text-align: center; padding: 3px; margin: 5px; cursor: pointer; } .button#number0 { flex: 0 0 66.6%; }
 <div class="numbers"> <div class="row"> <div class="button number" id="number1" data-nr="1"></div> <div class="button number" id="number2" data-nr="2"></div> <div class="button number" id="number3" data-nr="3"></div> </div> <div class="row"> <div class="button number" id="number4" data-nr="4"></div> <div class="button number" id="number5" data-nr="5"></div> <div class="button number" id="number6" data-nr="6"></div> </div> <div class="row"> <div class="button number" id="number7" data-nr="7"></div> <div class="button number" id="number8" data-nr="8"></div> <div class="button number" id="number9" data-nr="9"></div> </div> <div class="row"> <div class="button number" id="number0" data-nr="0"></div> <div class="button" id="colon" data-nr=":"></div> </div> </div>


flex版本,对现有的 html 结构略有改动,使用伪元素,并为不支持新 flexbox 模型(如 IE8/9)的浏览器提供display: table回退。

 .row { display: table; width: 100%; } .button { display: table-cell; width: 33.3%; padding: 5px; } .button:after { content: attr(data-nr); display: block; border-radius: 5px; border: 1px solid gray; background: rgba(255, 255, 255, 0.9); text-align: center; padding: 3px; cursor: pointer; } .button#number0 { width: 66.6%; } @supports (display: flex) { .row { display: flex; } .button { display: block; width: auto; flex: 0 0 33.3%; padding: 0; } .button#number0 { flex: 0 0 66.6%; } .button:after { margin: 5px; } }
 <div class="numbers"> <div class="row"> <div class="button number" id="number1" data-nr="1"></div> <div class="button number" id="number2" data-nr="2"></div> <div class="button number" id="number3" data-nr="3"></div> </div> <div class="row"> <div class="button number" id="number4" data-nr="4"></div> <div class="button number" id="number5" data-nr="5"></div> <div class="button number" id="number6" data-nr="6"></div> </div> <div class="row"> <div class="button number" id="number7" data-nr="7"></div> <div class="button number" id="number8" data-nr="8"></div> <div class="button number" id="number9" data-nr="9"></div> </div> <div class="row"> <div class="button number" id="number0" data-nr="0"></div> <div class="button" id="colon" data-nr=":"></div> </div> </div>

我认为 Michael_B 所说的一切都是正确的。 只有解决方案有点尴尬。 我个人不喜欢 calc。 只是感觉不太对。

你遇到的问题是一个更普遍的问题。 你把太多的责任放在一个元素上。 在这种情况下,它是.button类。 使用 flex-grow 的 Flex 和 Margin 责任太大。 试着把它分开。 这意味着更多的 DOM 元素,但它为您节省了很多痛苦。

 .numbers { display: flex; flex-direction: column; max-width: 200px; margin: 0 auto; } .row { display: flex; flex-direction: row; flex-grow: 1; justify-content: space-between; } .row > .box { display: flex; flex-basis: 33.3333%; justify-content: center; align-items: center; } .row > .box.box-2 { flex-basis: 66.6667%; } .button { border-radius: 5px; border: 1px solid gray; background: rgba(255, 255, 255, 0.2); cursor: pointer; width: auto; text-align: center; margin: 5px; width: 100%; }
 <div class="numbers"> <div class="row"> <div class="box"><div class="button number" id="number1">1</div></div> <div class="box"><div class="button number" id="number2">2</div></div> <div class="box"><div class="button number" id="number3">3</div></div> </div> <div class="row"> <div class="box"><div class="button number" id="number4">4</div></div> <div class="box"><div class="button number" id="number5">5</div></div> <div class="box"><div class="button number" id="number6">6</div></div> </div> <div class="row"> <div class="box"><div class="button number" id="number7">7</div></div> <div class="box"><div class="button number" id="number8">8</div></div> <div class="box"><div class="button number" id="number9">9</div></div> </div> <div class="row"> <div class="box box-2"><div class="button number" id="number0">0</div></div> <div class="box"><div class="button" id="colon">:</div></div> </div> </div>

在我看来,flexbox 对边距反应不佳。

我更喜欢的更好的方法/解决方法是确保所有 flex 子项的边距为 0,将 flex 容器设置为justify-content: space-between; ,然后给孩子一个小于 100% 的总宽度。 剩余部分将是您的保证金。

换句话说,如果您希望每行有两个元素,请将每个元素设置为 49% 宽,并且它们之间将有 2% 的空间。 三个元素,每个元素的宽度为 32%,它们之间的宽度为 2%。 在计算器示例中, 0单元格应为 66% 宽,其余为 32%。

编辑:请注意,由于原因(即content-box很糟糕),如果您的任何孩子有边框,您将需要使用box-sizing: border-box以使我的建议正常工作。

https://jsfiddle.net/r3L1mtbe/2/

使用简写来适应跨浏览器支持很重要:

.row {
    display: flex;
    flex-direction: row; /* <-- this is the default so unnecessary to state */
    flex-grow: 1;
    justify-content: space-between;
}

.button {
    display: flex;
   /* flex-grow: 1; replace with shorthand */ 
   flex:1 0 100%; /* probably making the "width: 100%;" unnecessary */
    justify-content: center;
}

.button#number0 {
    /* flex-grow: 2; replace with shorthand */ 
   flex:2 0 100%;
}

.button#colon {
    /* flex-grow: 1; replace with shorthand */ 
    flex:1 0 100%;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM