似乎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>
&#13;
答案 0 :(得分:31)
问题是第1-3行有两个水平边距而第4行只有一个。
水平边距为10px时,第4行的可用空间比其他行多10px。这会抛弃列的对齐。
由于flex-grow
仅适用于可用空间,并且受内容和边距的影响很大,因此它不是调整弹性项目大小的最安全方法。
请尝试使用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
属性的计算大小。难道我做错了什么?
问题的根源不是弹性项目内的内容。
您写道:
在下面提供的小提琴中,你会看到一个数字键盘。除底行外,所有行都包含3个数字。那行应该是'0'是2个数字的宽度,因此
flex-grow: 2
和':'是1个数字的大小,因此flex-grow: 1
。我在这里错过了什么吗?
是。您对flex-grow
属性的解释是不正确的。 flex-grow
不用于定义弹性项的大小。它的工作是在flex容器中分配项目中的可用空间。
通过将flex-grow: 1
应用于一组弹性项目,您告诉他们在自己之间平均分配可用空间。这就是为什么在您的演示中,第1,2和3行具有相同大小的弹性项目。
当您应用flex-grow: 2
时,您告诉Flex项目的可用空间是flex-grow: 1
项目的两倍。
但是从上面的行中的第二个10px边距到第4行的布局是什么?
第4行关闭对齐的原因是第4行的边距比其他行少一个,这意味着第4行的空闲空间比其他行多10px。
你会注意到,如果你remove the margin rule得到了你想要的对齐方式。
.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
。)- 第二个项目间边距仅出现在具有三个弹性项目的行上,宽度为10px。 (代码说每个项目周围5px,但在 CSS horizontal margins never collapse。 此外,在flexbox中,no margins collapse。)
flex-grow
值的总和为3。所以让我们将10px除以3.现在我们知道1的比例是3.33px。- 因此,flex项左侧获得额外空间6.66px,弹性项右侧获得3.33px。
- 假设左侧的弹性项目改为
flex-grow: 3
。然后,左侧的弹性项目将获得7.5px,右侧的弹性项目将获得2.5px。
你问题的最后一部分说:
'0'的右侧应与其上方的8,5和2对齐。有点过了。
由于flex-grow
仅适用于可用空间,并且受内容和边距的影响很大,因此它不是调整弹性项目大小的最安全方法。
请尝试使用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>
参考文献:
随着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>
答案 1 :(得分:10)
更新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);
}
&#13;
<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>
&#13;
flex
版本,对于不支持新Flexbox模型的浏览器具有display: table
备用。
.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);
}
&#13;
<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>
&#13;
更新2:
除了Michael_B的答案,顺便提一下,这里有一个非常好的解释,这里有一个更新版本,实际上确实给出了所需的对齐方式,在这种情况下,不需要1-2 px。< / p>
以下是我的和Michael_B版本中的fiddle sample和an image,其中边框已经增加了一点,以便更容易看到错位。
这一切都归结为当border
/ padding
出现时,flexbox如何计算尺寸,您可以read more about in this post,需要设置box-sizing: border-box
以及更多调整,在代码中注释。
以下是my fiddle和摘要
.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);
}
&#13;
<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>
&#13;
<强> 更新 强>
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%;
}
&#13;
<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>
&#13;
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;
}
}
&#13;
<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>
&#13;
答案 2 :(得分:7)
我认为Michael_B所说的一切都是正确的。只有解决方案有点尴尬。我个人不喜欢计算。这感觉不对。
你遇到的问题更为普遍。你把太多的责任放在一个元素上。在这种情况下,它是.button
类。灵活增长的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>
答案 3 :(得分:4)
flexbox对边距的反应不好。
我更喜欢的更好的方法/解决方法是确保所有flex子节点都有0个边距,将flex容器设置为justify-content: space-between;
,然后让子节点的总宽度小于100%。剩余部分将是您的保证金。
换句话说,如果您想要每行两个元素,请将每个元素设置为49%宽,并且它们之间的间距为2%。三个元素,每个元素的宽度为32%,它们之间的比例为2%。在计算器示例中,0
单元格应为66%宽,其余为32%。
修改:请注意,由于原因(即content-box
非常糟糕),如果您的孩子有任何边框,您需要使用box-sizing: border-box
才能使我的建议正常运作。
答案 4 :(得分:1)
使用速记来支持跨浏览器支持非常重要:
.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%;
}