【问题标题】:Flex direction and flex wrap on a container results in an extra space in a flex-item容器上的 Flex 方向和 flex wrap 会在 flex-item 中产生额外的空间
【发布时间】:2020-05-07 06:45:12
【问题描述】:

我有以下代码:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <style>
      *,
      *:before,
      *:after {
        box-sizing: border-box;
      }

      .list {
        line-height: 22px;
      }

      .list:before,
      list:after {
        display: table;
        content: "";
      }

      .list:after {
        clear: both;
      }

      .right-item {
        float: left;
        width: 50px;
        height: 50px;
        display: table;
        background-color: blue;
        border: 1px solid green;
        display: table;
        float: left;
        width: 50px;
        height: 50px;
        margin-right: 8px;
        margin-bottom: 8px;
        text-align: center;
        vertical-align: top;
      }

      .wrapper {
        display: inline-block;
        width: 100%;
      }

      .wrapper:before,
      .wrapper:after {
        content: "";
        display: table;
      }

      .wrapper:after {
        clear: both;
      }

      .floated-item {
        float: left;
        width: 50px;
        height: 50px;
        background-color: red;
        border: 1px solid black;
        margin: 0 8px 8px 0;
      }

      .flex-item {
        flex: auto;
        max-width: 100%;
      }

      .flex-container {
        display: flex;
        align-items: center;
        min-height: 15px;
        position: relative;
        align-items: center;
      }

      .flex-column {
        display: flex;
        flex-direction: column;
        flex-grow: 1;
        min-height: 1px;
        position: relative;
        max-width: 100%;
      }

      .outer-wrapper {
        display: flex;
        flex-flow: column wrap;
        margin-bottom: 24px;
        vertical-align: top;
      }

      .label {
        flex-grow: 0;
        overflow: hidden;
        display: inline-block;
        position: relative;
        max-width: 100%;
        min-height: 1px;
      }

      .label-inner {
        height: auto;
        position: relative;
        display: inline-flex;
        align-items: center;
        margin: 0;
      }
    </style>
  </head>
  <body>
    <form>
      <div class="outer-wrapper">
        <div class="label"><label class="label-inner">Label</label></div>
        <div class="flex-column">
          <div class="flex-container">
            <div class="flex-item">
              <span class="wrapper">
                <div class="list">
                  <div class="floated-item">
                    <span><div class="floated-item"></div></span>
                  </div>
                  <div class="floated-item">
                    <span><div class="floated-item"></div></span>
                  </div>
                  <div class="floated-item">
                    <span><div class="floated-item"></div></span>
                  </div>
                  <div class="floated-item">
                    <span><div class="floated-item"></div></span>
                  </div>
                  <div class="floated-item">
                    <span><div class="floated-item"></div></span>
                  </div>
                </div>
                <div class="right-item"></div>
              </span>
            </div>
          </div>
        </div>
      </div>
    </form>
    <div>content</div>
  </body>
</html>

起初,我不知道添加的额外空间会发生什么。经过长时间的调试,问题是(至少看起来是,它修复了额外的空间,但可能是其他原因导致它,我不知道)flex-wrap: wrap 用于.outer-wrapper。当我将其设置为 flex-wrap: nowrap 时,它会修复额外的空间。

我浏览了 Flexbox 规范,也浏览了 CSS 规范的 Visual Formatting Model,关于浮点使用、格式化上下文等,但我仍然不知道可能是什么问题。

【问题讨论】:

  • 问题似乎是由浮动项引起的。如果从.right-item 中删除float: leftdisplay: table,问题就会消失。我不确定 float 和 flex 规范是如何协同工作的,但浏览器似乎将额外的空白解释为浮动项目的高度。
  • 所需的布局是底部没有多余的空间。我想了解不同的布局机制是如何根据规范相互工作的,我无法向自己解释为什么这不起作用。如果有人根据规范解释所有内容如何组合在一起,我将不胜感激。
  • 在这种情况下,我不会对规格过于重视。 column wrap 仍然充满了所有浏览器的错误。 stackoverflow.com/a/61172784/3597276
  • 是的,我同意。你知道这是什么特定的错误吗?在这种情况下,它似乎增加了项目的高度。我想它不会使弹性容器成为多行容器,只会增加项目的高度。你有什么想法?
  • 我不确定您遇到的是哪个错误,但也许您可以解决它。这是你需要的吗? jsfiddle.net/r73tvhjg

标签: html css flexbox


【解决方案1】:

这首先连接到flex-columnflex-direction 使下一个 div (.flex-item) 占据整个宽度。如果您在代码中删除 flex-direction:column,最后一个 div (right-item) 将自动落在下一行。

另外,如果你在 flex-column 中指定width:100%,空格会消失,因为容器确信他可以将所有内容放在一行中。

然后你给你的.flex-itemflex:auto 女巫是flex-basis 属性,根据css-tricks 意味着额外的空间是根据它的 flex-grow 值分配的。 (如果你从你的代码中删除它,你的right-item 也将在下一行,因为他只会为你的包装器占用所需的空间并且不会改变)。

之后,您指定 wrapper* 的宽度为 100%(如果您只是从 .wrapper 类中删除 width:100%,而不触及 flex-direction 或 flex:auto,则会发生同样的事情( right-item 将在下一行)。

底线是弹性容器有很多理由认为您需要 2 行来容纳所有元素。但是由于flex-directionflex:autowidth:100%,您将它们全部集中在一行中。

所以这可能看起来很奇怪,但是当您结合多种显示类型(flex、inline 和 table)并且您过于依赖容器来计算它们的大小时,就会发生这种情况。

【讨论】:

    【解决方案2】:

    额外的空间是由于display: inline-block 分配给.wrapper 类。

    display: inline-block 更改为display: flex,这应该可以解决问题。

    *,
    *:before,
    *:after {
      box-sizing: border-box;
    }
    
    .list {
      line-height: 22px;
    }
    
    .list:before,
    list:after {
      display: table;
      content: "";
    }
    
    .list:after {
      clear: both;
    }
    
    .right-item {
      float: left;
      width: 50px;
      height: 50px;
      display: table;
      background-color: blue;
      border: 1px solid green;
      display: table;
      float: left;
    }
    
    /* changed here */
    .wrapper {
      display: flex;
      width: 100%;
    }
    
    .wrapper:before,
    .wrapper:after {
      content: "";
      display: table;
    }
    
    .wrapper:after {
      clear: both;
    }
    
    .floated-item {
      float: left;
      width: 50px;
      height: 50px;
      background-color: red;
      border: 1px solid black;
      margin: 0 8px 8px 0;
    }
    
    .flex-item {
      flex: auto;
      max-width: 100%;
    }
    
    .flex-container {
      display: flex;
      align-items: center;
      min-height: 15px;
      position: relative;
      align-items: center;
    }
    
    .flex-column {
      display: flex;
      flex-direction: column;
      flex-grow: 1;
      min-height: 1px;
      position: relative;
      max-width: 100%;
    }
    
    .outer-wrapper {
      display: flex;
      flex-flow: column wrap;
      margin-bottom: 24px;
      vertical-align: top;
    }
    
    .label {
      flex-grow: 0;
      overflow: hidden;
      display: inline-block;
      position: relative;
      max-width: 100%;
      min-height: 1px;
    }
    
    .label-inner {
      height: auto;
      position: relative;
      display: inline-flex;
      align-items: center;
      margin: 0;
    }
    <div class="outer-wrapper">
      <div class="label"><label class="label-inner">Label</label></di <div class="flex-column">
        <div class="flex-container">
          <div class="flex-item">
            <span class="wrapper">
                    <div class="list">
                      <div class="floated-item">
                        <span><div class="floated-item"></div></span>
          </div>
          <div class="floated-item">
            <span><div class="floated-item"></div></span>
          </div>
          <div class="floated-item">
            <span><div class="floated-item"></div></span>
          </div>
          <div class="floated-item">
            <span><div class="floated-item"></div></span>
          </div>
          <div class="floated-item">
            <span><div class="floated-item"></div></span>
          </div>
        </div>
        <div class="right-item"></div>
        </span>
      </div>
    </div>
    </div>
    </div>
    <div>content</div>

    注意:inline-block 应用于 .wrapper 时,.outer-wrapper 的高度会发生变化。

    【讨论】:

      【解决方案3】:

      作为容器元素&lt;span class="wrapper"&gt;,如果设置为display:flex,它会以某种方式将其高度计算为class="list"class="right-item" 的高度之和。它以某种方式考虑如果class="list" 元素中没有浮动元素(或者应用了clearfix hack),它会占用多少高度。我很确定这件事,好像我将蓝色框的高度更改为 20 px,底部的高度也会降低(它并不总是其实际内容高度的两倍)。

      class='list' div 中带有浮点元素的代码 sn-p

      .right-item {
        animation: myfirst 5s linear infinite alternate;
      }
      
      @keyframes myfirst {
        0% {
          height: 50px;
        }
        100% {
          height: 10px;
        }
      }
      <!DOCTYPE html>
      <html lang="en">
      
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <style>
          *,
          *:before,
          *:after {
            box-sizing: border-box;
          }
          
          .list {
            line-height: 22px;
          }
          
          .list:before,
          list:after {
            display: table;
            content: "";
          }
          
          .list:after {
            clear: both;
          }
          
          .right-item {
            float: left;
            width: 50px;
            height: 50px;
            display: table;
            background-color: blue;
            border: 1px solid green;
            display: table;
            float: left;
            width: 50px;
            height: 50px;
            margin-right: 8px;
            margin-bottom: 8px;
            text-align: center;
            vertical-align: top;
          }
          
          .wrapper {
            display: inline-block;
            width: 100%;
          }
          
          .wrapper:before,
          .wrapper:after {
            content: "";
            display: table;
          }
          
          .wrapper:after {
            clear: both;
          }
          
          .floated-item {
            float: left;
            width: 50px;
            height: 50px;
            background-color: red;
            border: 1px solid black;
            margin: 0 8px 8px 0;
          }
          
          .flex-item {
            flex: auto;
            max-width: 100%;
          }
          
          .flex-container {
            display: flex;
            align-items: center;
            min-height: 15px;
            position: relative;
            align-items: center;
          }
          
          .flex-column {
            display: flex;
            flex-direction: column;
            flex-grow: 1;
            min-height: 1px;
            position: relative;
            max-width: 100%;
          }
          
          .outer-wrapper {
            display: flex;
            flex-flow: column wrap;
            margin-bottom: 24px;
            vertical-align: top;
          }
          
          .label {
            flex-grow: 0;
            overflow: hidden;
            display: inline-block;
            position: relative;
            max-width: 100%;
            min-height: 1px;
          }
          
          .label-inner {
            height: auto;
            position: relative;
            display: inline-flex;
            align-items: center;
            margin: 0;
          }
        </style>
      </head>
      
      <body>
        <form>
          <div class="outer-wrapper">
            <div class="label"><label class="label-inner">Label</label></div>
            <div class="flex-column">
              <div class="flex-container">
                <div class="flex-item">
                  <span class="wrapper">
                      <div class="list">
                        <div class="floated-item">
                          <span><div class="floated-item"></div></span>
                </div>
                <div class="floated-item">
                  <span><div class="floated-item"></div></span>
                </div>
                <div class="floated-item">
                  <span><div class="floated-item"></div></span>
                </div>
                <div class="floated-item">
                  <span><div class="floated-item"></div></span>
                </div>
                <div class="floated-item">
                  <span><div class="floated-item"></div></span>
                </div>
              </div>
              <div class="right-item"></div>
              </span>
            </div>
          </div>
          </div>
          </div>
        </form>
        <div>content</div>
      </body>
      
      </html>

      代码 sn-p 的元素在 class="list" div 中浮动,但也应用了 clearfix hack。(显示它实际应该采用的高度,这似乎导致上述 sn 中的额外空间-p)

      .clearfix::after {
        content: "";
        clear: both;
        display: table;
      }
      <!DOCTYPE html>
      <html lang="en">
      
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <style>
          *,
          *:before,
          *:after {
            box-sizing: border-box;
          }
          
          .list {
            line-height: 22px;
          }
          
          .list:before,
          list:after {
            display: table;
            content: "";
          }
          
          .list:after {
            clear: both;
          }
          
          .right-item {
            float: left;
            width: 50px;
            height: 50px;
            display: table;
            background-color: blue;
            border: 1px solid green;
            display: table;
            float: left;
            width: 50px;
            height: 50px;
            margin-right: 8px;
            margin-bottom: 8px;
            text-align: center;
            vertical-align: top;
          }
          
          .wrapper {
            display: inline-block;
            width: 100%;
          }
          
          .wrapper:before,
          .wrapper:after {
            content: "";
            display: table;
          }
          
          .wrapper:after {
            clear: both;
          }
          
          .floated-item {
            float: left;
            width: 50px;
            height: 50px;
            background-color: red;
            border: 1px solid black;
            margin: 0 8px 8px 0;
          }
          
          .flex-item {
            flex: auto;
            max-width: 100%;
          }
          
          .flex-container {
            display: flex;
            align-items: center;
            min-height: 15px;
            position: relative;
            align-items: center;
          }
          
          .flex-column {
            display: flex;
            flex-direction: column;
            flex-grow: 1;
            min-height: 1px;
            position: relative;
            max-width: 100%;
          }
          
          .outer-wrapper {
            display: flex;
            flex-flow: column wrap;
            margin-bottom: 24px;
            vertical-align: top;
          }
          
          .label {
            flex-grow: 0;
            overflow: hidden;
            display: inline-block;
            position: relative;
            max-width: 100%;
            min-height: 1px;
          }
          
          .label-inner {
            height: auto;
            position: relative;
            display: inline-flex;
            align-items: center;
            margin: 0;
          }
        </style>
      </head>
      
      <body>
        <form>
          <div class="outer-wrapper">
            <div class="label"><label class="label-inner">Label</label></div>
            <div class="flex-column">
              <div class="flex-container">
                <div class="flex-item">
                  <span class="wrapper">
                      <div class="list clearfix">
                        <div class="floated-item">
                          <span><div class="floated-item"></div></span>
                </div>
                <div class="floated-item">
                  <span><div class="floated-item"></div></span>
                </div>
                <div class="floated-item">
                  <span><div class="floated-item"></div></span>
                </div>
                <div class="floated-item">
                  <span><div class="floated-item"></div></span>
                </div>
                <div class="floated-item">
                  <span><div class="floated-item"></div></span>
                </div>
              </div>
              <div class="right-item"></div>
              </span>
            </div>
          </div>
          </div>
          </div>
        </form>
        <div>content</div>
      </body>
      
      </html>

      我会尝试找到一些关于为什么会发生这种情况的参考,并编辑这篇文章以防万一我找到它。但是,在我的理解中,flex 和 float 在它们的行为方式上是非常矛盾的。如果您一定要一起使用它们,那么您必须详细了解它们的原因、内容、方式等。或者不要同时使用它们。

      另外,关于您上面的代码的一件重要的事情是您使用display: flex,然后在outer-wrapper div 上使用flex-flow: column wrap;,其中只有一个子元素。我看不出添加这些样式的意义。由于outer-wrapper div 内只有 1 个元素,因此如果没有这些样式,它的行为方式也会相同。尝试使用 display: flex 仅在需要时使用。

      【讨论】:

      • 赏金说明指出:“我想要一个清楚的说明是什么导致了这个错误,如果它是一个错误,或者是什么规范规则使它表现得像它一样。”你的回答说 "...它以某种方式计算...""它以某种方式考虑...""我会尝试找到一些参考。 ..” 你没有达到要求的标准。如果你能改进你的答案,我很乐意推翻我的反对意见。
      • @MichaelBenjamin 感谢您澄清这一点。我不介意投反对票。当我发布这个答案时,我知道我在做什么并且知道这一定会发生:)。我一定会努力寻找答案。但有时最好将想法公开,以便其他人可以从另一个方向研究这个问题。我并不仅仅是为了赏金而发帖。在任何情况下,赏金与否都是 OP 的决定 :) 因此,如果他/她对任何答案不完全满意,我不介意他/她不给任何人。
      猜你喜欢
      • 2023-01-11
      • 1970-01-01
      • 2021-09-10
      • 2017-07-16
      • 1970-01-01
      • 2017-12-03
      • 2019-09-08
      • 2021-08-27
      • 2020-07-08
      相关资源
      最近更新 更多