flex-grow不按预期调整flex项目的大小

The*_*ith 36 html css css3 flexbox

似乎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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

https://jsfiddle.net/0r4hemdu/

Mic*_*l_B 31

简短分析

问题是第1-3行有两个水平边距,第四行只有一个.

在此输入图像描述

水平边距为10px,第4行的可用空间比其他行多10px.这会抛弃列的对齐.

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

试试吧flex-basis.将其添加到您的代码中:

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

.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; }
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)


扩展分析

你写了:

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

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

你写了:

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

是.您对该flex-grow物业的解释不正确.flex-grow不用于定义Flex项的大小.它的工作是在项目中的Flex容器中分配可用空间.

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

当您申请时flex-grow: 2,您告诉弹性项目消耗的可用空间是项目的两倍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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)


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

它被两个弹性物品吸收.

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

  • 左侧的Flex项目(内容为"0")具有flex-grow: 2.(.button#number0在你的代码中.)
  • Flex项目权限(内容为":")具有flex-grow: 1.(.button#colon在你的代码中.)
  • 第二个项目间边距仅出现在具有三个弹性项目的行上,宽度为10px.(代码说每个项目周围5px,但在CSS 水平边距永远不会崩溃.而且,在flexbox中,没有边距崩溃.)
  • flex-grow值的总和为3.所以让我们将10px除以3.现在我们知道1的比例是3.33px.
  • 因此,flex项左侧获得额外空间6.66px,弹性项右侧获得3.33px.
  • 让我们说左边的flex项目已经flex-grow: 3改为了.然后flex项目左边会得到7.5px,而flex项目右边会得到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; }
Run Code Online (Sandbox Code Playgroud)

.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; }
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)


LGS*_*Son 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);
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

flexdisplay: table不支持新的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);
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)


更新2:

除了Michael_B的答案,顺便提一下,这是一个非常好的解释,这里是一个更新版本,实际上确实给出了所需的对齐,在这种情况下,没有1-2 px关闭.

这是一个小提琴样本,以及我和Michael_B版本的图像,其中边框已经增加了一点,以便更容易看到错位.

这一切都归结为flexbox如何计算出现border/ padding出现时的大小,您可以在这篇文章中详细了解,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);
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)


更新:

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%;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)


flex版本,使用伪元素对现有html结构进行微小更改,并且display: table对不支持新Flexbox模型的浏览器(如IE8/9)具有后备.

.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;
  }  
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)


yun*_*zen 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%;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)