flex-grow not sizing flex items as expected
似乎flex div中的内容会影响有关
在下面提供的小提琴中,您将看到一个数字键盘。 除底行外,所有行均包含3个数字。 该行的'0'是2个数字的宽度,因此
我在这里想念什么吗?
" 0"的右侧应与其上方的8、5和2对齐。 有点不对劲
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | .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; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 1 2 3 4 5 6 7 8 9 0 : |
https://jsfiddle.net/0r4hemdu/
简短分析
问题在于,第1-3行有两个水平边距,而第4行只有一个水平边距。
如果水平边距各为10px,则第4行的可用空间比其他行多10px。这引发了列的对齐。
由于
请尝试使用
1 2 3 | .button { flex-basis: 33.33%; } #number0 { flex-basis: calc(66.67% + 10px); } * { box-sizing: border-box; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | .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; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 1 2 3 4 5 6 7 8 9 0 : |
扩展分析
你写了:
It seems that the content inside a flex div affects its calculated size concerning the
flex-grow property. Am I doing something wrong?
问题的根源不是弹性项目中的内容。
你写了:
In the fiddle provided below, you'll see a number pad. All the rows contain 3 numbers except the bottom row. That row should have the '0' be the width of 2 numbers, hence
flex-grow: 2 and the ':' be the size of 1 number, henceflex-grow: 1 . Am I missing something here?
是。您对
通过将
应用
但是,以上各行的第二个10px边距在第4行的布局中位于何处?
第4行未对齐的原因是,第4行的边距比其他行少一个,这意味着第4行的可用空间比其他行多10像素。
您会注意到,如果删除边距规则,则会得到所需的对齐方式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | .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; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 1 2 3 4 5 6 7 8 9 0 : |
那么第四行到第二个10px的空白会发生什么呢?
它被两个弹性项目吸收。
Here's how
flex-grow distributes the extra space on row four:
- Flex item left (with content"0") has
flex-grow: 2 . (.button#number0 in your code.)- Flex item right (with content":") has
flex-grow: 1 . (.button#colon in your code.)- The second inter-item margin, which appears only on rows with three flex items, is 10px wide. (The code says 5px around each item, but in
CSS horizontal margins never
collapse.
Moreover, in flexbox, no margins
collapse.)- The sum total of the
flex-grow values is three. So let's divide 10px by 3. Now we know that the proportion of 1 is 3.33px.- Hence, flex item left gets 6.66px of the extra space, and flex item right gets 3.33px.
- Let's say that flex item left had
flex-grow: 3 instead. Then flex item left would get 7.5px, and flex item right would get 2.5px.
您问题的最后一部分说:
The right side of the '0' should be aligned with the 8, 5, and 2 above it. It's a bit off.
由于
请尝试使用
1 2 3 | .button { flex-basis: 33.33%; } #number0 { flex-basis: calc(66.67% + 10px); } * { box-sizing: border-box; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | .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; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 1 2 3 4 5 6 7 8 9 0 : |
jsFiddle演示
参考文献:
-
flex-grow 定义?MDN -
flex-basis 定义?MDN - 7.2灵活性组件?W3C
额外:CSS GRID解决方案
随着CSS Grid的出现,可以大大简化整个布局的代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | .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; } |
1 2 3 4 5 6 7 8 9 10 11 | 1 2 3 4 5 6 7 8 9 0 : |
更新3:
我想出了另一种摆脱不对正的方法。
此版本与2:nd更新一起使用,原始HTML保持不变,并使用伪元素创建按钮,包括按钮悬停/单击效果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | .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); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 1 2 3 4 5 6 7 8 9 0 : |
对于不支持新的flexbox模型的浏览器,带有
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | .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); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 1 2 3 4 5 6 7 8 9 0 : |
更新2:
除了Michael_B的答案(很好地解释了)之外,这里还提供了一个更新版本,该版本实际上给出了所需的对齐方式,而在这种情况下,不偏离1-2 px。
这是我的版本和Michael_B版本的小提琴样本和图像,其中的边界略微增加了一点,以便于查看错位。
一切都取决于存在
这是我的小提琴和摘录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | .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); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 1 2 3 4 5 6 7 8 9 0 : |
更新:
仅限
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | .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%; } |
1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | .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; } } |
1 |
我认为Michael_B所说的一切都是正确的。只有解决方案有点尴尬。我个人不喜欢calc。只是感觉不对。
您遇到的问题是一个更普遍的问题。您将太多的责任放在一个元素上。在这种情况下,它是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | .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%; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 1 2 3 4 5 6 7 8 9 0 : |
我认为,flexbox对利润率的反应不佳。
我更喜欢的更好的方法/解决方法是,确保所有flex子代的边距为0,将flex容器设置为
换句话说,如果您希望每行两个元素,请将每个元素设置为49%宽,并且它们之间将有2%的间距。三个元素,每个元素的宽度为32%,而您之间将有2%。在计算器示例中,
编辑:请注意,由于原因(即
https://jsfiddle.net/r3L1mtbe/2/
使用简写来容纳跨浏览器支持很重要:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | .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%; } |