Flex的成长预期不施胶弯曲项目

问题描述 投票:35回答:5

看来,柔性DIV里面的内容会影响其关于flex-grow属性计算的大小。难道我做错了什么?

在下面提供的小提琴,你会看到一个数字键盘。所有行包含不同的是底部排3号。该行应该有“0”为2号的宽度,因此flex-grow: 2和“:”(冒号)是1号的大小,因此flex-grow: 1

我失去了一些东西在这里?

“0”的右侧应与8,5 2上面对齐,和。这是一个有点过。

enter image description here

.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/

html css css3 flexbox
5个回答
31
投票

短期分析

的问题是,行1-3具有两个水平边缘和行4只有一个。

enter image description here

在每个水平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>

扩展分析

你写了:

看来,柔性DIV里面的内容会影响其关于flex-grow属性计算的大小。难道我做错了什么?

你的问题的根源是不是Flex项目里面的内容。

你写了:

在下面提供的小提琴,你会看到一个数字键盘。所有行包含不同的是底部排3号。该行应该有“0”为2号的宽度,因此flex-grow: 2和“:”是1号的大小,因此flex-grow: 1。我失去了一些东西在这里?

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

通过应用flex-grow: 1一组柔性的项目,你告诉他们均匀地分布在它们之间的自由空间。这就是为什么,在您的演示,行1,2和3有同样大小的柔性物品。

当你申请flex-grow: 2,你告诉柔性项消耗两倍的自由空间与flex-grow: 1项目。

但是,在不从上述因子行的第二10px的余量为4行的布局?

enter image description here

究其原因,对准是关闭上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值是三。因此,让我们鸿沟10px的通过3.现在我们知道,1比例3.33px。
  • 因此,弯曲左项目获得额外的空间6.66px,和Flex项目的权利得到3.33px。
  • 比方说,左挠项目有flex-grow: 3代替。然后弯曲左项目将获得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; }

.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 demo


参考文献:


EXTRA:CSS电网解决方案

随着CSS网格的出现,为在整个布局中的代码可以大大简化。

.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>

10
投票

更新3:

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

这个版本,与2一起:次更新,工作原理与原始的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>

flex版采用了display: 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);
}
<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关闭。

这里是一个fiddle samplean image,无论矿山和Michael_B版本,其中的边界已经略有增加,使其更容易看到错位的。

这一切都归结到时border / padding存在,你可以read more about in this post,哪里box-sizing: border-box需要设置与几更多的调整,这是在代码注释Flexbox的是如何计算的大小。

这里是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);
}
<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结构的微小变化,使用伪元件,并具有用于浏览器中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;
  }  
}
<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>

7
投票

我觉得一切Michael_B说是正确的。只有解决方案是一个有点尴尬。我personsally不喜欢计算。它只是感觉不对。

你的问题是更普遍的一个。你把太多的责任到一个元素。在这种情况下,它的.button类。 Flex和裕度柔性成长是太多的责任。尝试打破分开。这意味着更多的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>

4
投票

Flexbox,就没有很好地应对利润,在我看来。

更好的办法/解决方法我宁愿是确保所有Flex孩子有0边距,设置柔性容器justify-content: space-between;,然后给孩子们总宽度小于100%。其余的将是你的保证金。

换句话说,如果你想每行有两个元素,每个设置为49%,宽,你就会有他们之间的2%的空间。三个要素,各为32%宽,你就会有他们之间的2%。在计算器示例中,0细胞应该是66%宽,其余32%。

编辑:请注意,由于原因(即content-box是可怕的),如果有你的孩子有你需要使用box-sizing: border-box边框我的建议才能正常工作。

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


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%;
}
© www.soinside.com 2019 - 2024. All rights reserved.