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

Jon*_*han 6 css css3 word-wrap flexbox internet-explorer-11

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

我有可变数量的flex-children,每个孩子的宽度都未知。每个孩子都有任意动态生成的内容。但是,其中某些内容必须具有包装文字的功能。

伸缩式容器本身必须具有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>
Run Code Online (Sandbox Code Playgroud)

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

当窗口足够宽时,每个flex-child应该并排放置,并且文本不会折叠: 正确显示-最大宽度窗口

当窗口水平缩小时,最右边框中的文本应开始换行: 正确显示-中宽窗口

当文本不能再分成多行时,伸缩框本身应开始换行: 正确显示-最小宽度窗口

这在大多数现代浏览器中都很好用,但不适用于我们的朋友IE11。在IE11中,更改屏幕大小时,文本会自动换行,但是flex-children根本不会换行。因为flex-children不包装,所以它们的内容会彼此溢出: IE11显示不正确-flex-basis:0%

将flex基础更改为flex-basis: auto;具有相反的效果:文本不会自动换行,但是flex-children会自动换行,但是内容不会溢出(在此屏幕截图中,绿色框中的文本应为折行,而不是flex-box分成新队): IE11显示不正确-flex-basis:自动

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

我还应该说,我只需要在最新的浏览器上就可以使用它(从技术上讲,仅在某些版本的Chrome和IE11上有效,但其他浏览器和版本也可以使用)。

这是完整显示问题的代码笔(在IE11和Chrome中查看以了解区别)。

是否有人对如何解决此问题有任何想法?

请记住,要求是:

  • 宽度未知的flex-children数量未知
  • 某些文字必须在flex-box换行之前换行
  • 一旦文本不能再包含更多内容,flex-children必须重新包装
  • Chrome(我正在使用59.0.3071.109)和IE11(我正在使用11.0.9600.18816CO)的行为应相同。
  • 首选纯CSS解决方案

谢谢。

更新:

我的一位同事建议对不包含可包装文本的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>
Run Code Online (Sandbox Code Playgroud)

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

正如我在此处介绍的那样,他的解决方案从技术上解决了这个问题,但是我忘了提到另一个要求:

  • 在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>
Run Code Online (Sandbox Code Playgroud)

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

可以在此处看到显示此几乎可行的解决方案的代码笔(请注意,该代码笔min-width已删除,因为它在Chrome上引起了进一步的问题)。

更新2: 我认为我之前还不够清楚:任何,全部或没有flex-children可能具有可包装的文本。这完全取决于动态生成的内容。在我给出的示例中,只有第三个flex-child具有可包装的文本,但情况并非总是如此。

LGS*_*Son 6

请注意,此答案是在问题的 2 次更新之前发布的,这使其部分无效,尽管我暂时将其保留,但有人可能仍需要它。

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

IE 需要在break-able的父级上有一个最小宽度,因此在元素换行之前文本不会折叠为 0 宽度,并且由于flex-basis需要auto一般但0pxbreak-able的父级上,弹性增长需要在 5 左右。

我使用 IE11 only 选择器添加了以下规则(我在我的这个答案中展示了)。

_:-ms-fullscreen, :root .flex-child {
  flex-basis: auto;
}
_:-ms-fullscreen, :root .child-3 {
  flex: 5 0 0px;
  min-width: 80px;
}
Run Code Online (Sandbox Code Playgroud)

更新代码笔

堆栈片段

_:-ms-fullscreen, :root .flex-child {
  flex-basis: auto;
}
_:-ms-fullscreen, :root .child-3 {
  flex: 5 0 0px;
  min-width: 80px;
}
Run Code Online (Sandbox Code Playgroud)
.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;
}
Run Code Online (Sandbox Code Playgroud)


Jon*_*han 1

不是首选解决方案,因为它使用 Javascript。然而,它确实有效。

创建所有 flex-children 后,每当屏幕尺寸发生变化时,检查每个 flex-children 的宽度是否小于其内容的宽度(为此,内容必须用带有 的内容包裹display: table-cell)。如果是这样,请向 flex-child 添加等于其内容宽度的最小宽度。一旦添加了min-width,就不需要再次进行计算,因此不再检查屏幕尺寸何时变化。仅在 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>
Run Code Online (Sandbox Code Playgroud)

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

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

可以在此处找到查看此解决方案的代码笔。

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