首页 文章

Flex-Basis:0%会导致IE11中出现错误的溢出

提问于
浏览
3

我遇到的问题是 flex-basis: 0%; 以及当用户缩小窗口宽度时IE11如何处理它 . 可能与box-sizing的错误有关 .

我有一个可变数量的flex-children,每个孩子的宽度都不明 . 每个孩子都有任意动态生成的内容 . 但是,其中一些内容必须能够包装文本 .

flex-container本身必须具有100%的宽度,并且必须能够包裹其子节点(即 flex-wrap: wrap ) .

假设有三个flex-children,最后一个需要文本换行:

<div class="flex-container">
  <div class="flex-child">
    <div>This text should not overlay other flex-children.</div>
  </div>
  <div class="flex-child">
    <div>This text should not overlay other flex-children.</div>
  </div>
  <div class="flex-child">
    <div class="text-break">This text should break on new lines when the container shrinks down</div>
  </div>
</div>

CSS可以定义如下:

.flex-container {
  display: flex;
  flex-wrap: wrap;
  width: 100%;
}

.flex-child {
  flex-grow: 1;
  flex-shrink: 0;
  flex-basis: 0%;
  white-space: nowrap;
  padding: 5px;
}

.text-break {
  white-space: pre-wrap;
}

当窗口足够宽时,每个flex-child应该是并排的,文本不会崩溃:
Correct display - Max-width Window

当窗口水平缩小时,最右边框中的文本应该开始变为新行:
Correct Display - Mid-width Window

当文本不再分成更多行时,弹性框本身应该开始断行:
Correct Display - Min-width Window

这在大多数现代浏览器中都很有用,但不是我们的朋友IE11 . 在IE11中,当更改屏幕大小时,文本包装正常,但flex-children根本不包装 . 因为flex-children不会换行,所以它们的内容会相互溢出:
Incorrect IE11 Display - flex-basis: 0%

将flex基础更改为 flex-basis: auto; 具有相反的效果:文本不会换行但flex-children会做,但没有内容溢出(在此屏幕截图中,绿色框中的文本应该是断行而不是弹性框分成新行):
Incorrect IE11 Display - flex-basis: auto

我见过的大多数解决方案都需要固定长度的flex-children,因为它们是动态生成的,所以我在这里无法承受 . 我故意不使用 flex 快捷方式属性,因为它有一些其他非相关问题 . This answer建议使用 _:-ms-fullscreen, :root .IE11-only-class { /* IE11 specific properties */ } ,如果我可以解决文本包装问题,这可能会有效,但我无法弄明白 .

我还应该说,我只需要在最新的浏览器上工作(技术上只适用于某些版本的Chrome和IE11,但其他浏览器和版本也可以使用) .

这是code pen完整显示问题(在IE11和Chrome中查看以查看差异) .

有没有人对如何解决这个问题有任何想法?

请记住,要求是:

  • 未知数量的未指定宽度的flex-children

  • 某些文本必须在弹性框包装之前换行

  • flex-children必须在文本无法再换行时换行

  • Chrome(我使用的是59.0.3071.109)和IE11(我使用的是11.0.9600.18816CO)应该以相同的方式运行 .

  • 仅限CSS的解决方案

谢谢 .

Update:

我的同事建议为不包含可包装文本的flex-children使用单独的类 . 他使用了以下HTML和CSS:

<!--HTML-->
<div class="flex-container">
  <div class="flex-child child-1">
    <div>This text should not overlay other flex-children.</div>
  </div>
  <div class="flex-child flex-child-without-textwrap child-2">
    <div>This text should not overlay other flex-children.</div>
  </div>
  <div class="flex-child flex-child-with-textwrap child-3">
    <div class="text-break">This text should break on new lines when the container shrinks down</div>
  </div>
</div>

/*CSS*/
.flex-container {
  display: flex;
  flex-wrap: wrap;
}

.flex-child {
  flex-grow: 1;
  flex-shrink: 1;
  padding: 5px;
  white-space: nowrap;
}

.flex-child-without-textwrap {
  flex-basis: auto;
}

.flex-child-with-textwrap {
  min-width: 200px;
  flex-basis: 0%;
}

.text-break {
  white-space: pre-wrap;
}

他的解决方案在技术上解决了我在这里提出的问题,但我忘了提到另一个要求:

  • 在flex-child中,可以存在可包装文本和不可包装文本的任意组合

将第三个flex-child更改为:

<div class="flex-child flex-child-with-textwrap child-3">
  <div class="text-break">This text should break on new lines when the container shrinks down</div>
  <div>This text should not break on new lines</div>
</div>

在这种情况下,第三个flex-child中第二个div中的文本流出其容器,文本开始包装得太早 .

可以看到显示这个几乎正常工作的解决方案的codepen here(请注意 min-width 已被删除,因为它在Chrome上引起了进一步的问题) .

Update 2: 我认为我之前不够清楚:任何,所有或没有一个弹性儿童可能有可装文本 . 这一切都取决于动态生成的内容 . 在我给出的示例中,只有第三个flex-child具有可包装的文本,但情况可能并非总是如此 .

2 回答

  • 3

    请注意,这个答案是在问题2的更新之前发布的,这使得它部分无效,但我现在暂时离开,有人可能需要它 .

    经过大量的反复试验后,我想出了这个设置,我的目标是让IE尽可能地模仿其余的浏览器行为 .

    在元素换行之前,IE需要在可破坏的's parent, so the text won' t折叠为0宽度的最小宽度,并且因为flex-basis通常需要 auto 但是在可破坏的父级上是 0px ,flex-grow需要在某处5 .

    我使用仅IE11选择器(我在this answer of mine中显示)添加了以下规则 .

    _:-ms-fullscreen, :root .flex-child {
      flex-basis: auto;
    }
    _:-ms-fullscreen, :root .child-3 {
      flex: 5 0 0px;
      min-width: 80px;
    }
    

    Updated codepen

    堆栈代码段

    .wrapper {
      width: 80%;
    }
    
    .flex-container {
      display: flex;
      flex-wrap: wrap;
      width: 100%;
    }
    
    .flex-child {
      flex: 1 0 0%;
      white-space: nowrap;
      padding: 5px;
    }
    
    _:-ms-fullscreen, :root .flex-child {
      flex-basis: auto;
    }
    _:-ms-fullscreen, :root .child-3 {
      flex: 5 0 0px;
      min-width: 80px;
    }
    
    .text-break {
      white-space: pre-wrap;
    }
    
    /*Add backgrounds for display*/
    .child-1 {
      background-color: pink;
    }
    .child-2 {
      background-color: lightblue;
    }
    .child-3 {
      background-color: lightgreen;
    }
    
    <div class="wrapper">
      <div class="flex-container">
        <div class="flex-child child-1">
          <div>This text should not overlay other flex-children.</div>
        </div>
        <div class="flex-child child-2">
          <div>This text should not overlay other flex-children.</div>
        </div>
        <div class="flex-child child-3">
          <div class="text-break">This text should break on new lines when the container shrinks down</div>
        </div>
      </div>
    </div>
    
  • 1

    这是 NOT a首选解决方案,因为它使用Javascript . 但是,它的工作原理 .

    在创建所有flex-children之后,每当屏幕大小发生变化时,检查每个flex-child的宽度是否小于其内容的宽度(为了使其工作,内容必须用 display: table-cell 包装) . 如果是这样,请为flex-child添加一个等于其内容宽度的最小宽度 . 添加最小宽度后,无需再次进行计算,因此不再检查屏幕大小何时更改 . 只在IE11上执行此操作 .

    我使用jquery来实现这个解决方案 .

    HTML:

    <div class="flex-container">
        <div id="1" class="flex-child child-1">
            <div class="content-container">This text should not overlay other flex-children.</div>
        </div>
        <div id="2" class="flex-child child-2">
            <div class="content-container">This text should not overlay other flex-children.</div>
        </div>
        <div id="3" class="flex-child child-3">
            <div class="content-container">
                <div class="text-break">This text should break on new lines when the container shrinks down</div>
                <div>This text should not break on new lines</div>
            </div>
        </div>
    </div>
    

    CSS:

    .flex-container {
        display: flex;
        flex-wrap: wrap;
        width: 100%;
    }
    
    .flex-child {
        flex-grow: 1;
        flex-shrink: 0;
        flex-basis: 0%;
        white-space: nowrap;
        padding: 5px;
    }
    
    .text-break {
        white-space: pre-wrap;
    }
    
    .content-container {
        display: table-cell;
    }
    

    jQuery的:

    if (!!window.MSInputMethodContext && !!document.documentMode) {//if IE11
        $(".flex-child").each(function (i, elem) {
            var $flex_child = $(elem);
            var child_id = $flex_child.attr("id");
    
            //add resize event to window
            $(window).on("resize." + child_id, function () {
                var width_of_flex_child = $flex_child.outerWidth();
                var content_width = $flex_child.children(".content-container").outerWidth();
    
                if (width_of_flex_child < content_width) {
                    $flex_child.css("min-width", content_width + "px");
    
                    //remove event
                    $(window).off("resize." + child_id);
                }
            }).trigger("resize." + child_id);
        });
    }
    

    可以在here找到查看此解决方案的codepen .

    不幸的是,由于窗口事件,此解决方案在管理资源时需要额外的开销 .

相关问题