【问题标题】:Flex-Basis: 0% causes incorrect overflow in IE11Flex-Basis:0% 导致 IE11 中的错误溢出
【发布时间】:2018-04-09 08:04:57
【问题描述】:

我遇到的问题涉及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 应该并排,并且文本不会折叠:

当窗口水平缩小时,最右边框中的文本应该开始换行:

当文本不能再分成更多行时,弹性框本身应该开始换行:

这在大多数现代浏览器中都非常有效,但在我们的朋友 IE11 中却不行。在 IE11 中,更改屏幕大小时,文本可以很好地换行,但 flex-children 根本不换行。因为 flex-children 不换行,所以它们的内容会相互溢出:

将 flex base 更改为 flex-basis: auto; 会产生相反的效果:文本不会换行,但 flex-children 会换行,但没有内容溢出(在此屏幕截图中,绿色框中的文本应该是断行而不是flex-box 换行):

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

我还应该说,我只需要它在最新的浏览器上工作(技术上只在 Chrome 和 IE11 的某些版本上工作,但让其他浏览器和版本也能工作是一个加分项)。

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

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

记住,要求是:

  • 未指定宽度的 flex-children 数量未知
  • 某些文本必须在 flex-boxes 换行之前换行
  • 一旦文本不能再换行,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>

/*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 中的文本会流出其容器,并且文本过早地开始换行。

here 上可以看到一个显示这个几乎可以工作的解决方案的代码笔(请注意,min-width 已被删除,因为它会在 Chrome 上引起更多问题)。

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

【问题讨论】:

  • 在此处查看第三个要点中的信息和参考链接:stackoverflow.com/a/39310591/3597276
  • @Michael_B 感谢您的评论。我已经研究了单位的差异,但它们都不起作用。根据我的研究,人们建议使用 0%,所以我坚持这样做。
  • 我认为这是使用媒体查询来更改flex-basis 值的情况。但是0% 意味着它们不会被计算到布局流中,这就是 IE 看​​起来像这样的原因。尝试flex-basis:auto; 并添加一些媒体查询,专门将项目更改为您想要的大小比例。您也可以尝试将flex-wrap 添加到flex-child div。
  • @AlexW 感谢您的建议。简单地更改为flex-basis: auto 不起作用,因为它会停止文本换行,而且我不能使用大小比,因为所有内容都应该适合其内容(flex-basis: content 现在听起来很棒)。据我所知,flex-wrap 只影响弹性容器(即带有display: flex 的容器)。
  • 您在第一段中链接到的错误正是导致此问题的原因。

标签: css flexbox internet-explorer-11 word-wrap


【解决方案1】:

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

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

IE 需要 break-able 的父级上的最小宽度,因此文本不会在元素换行之前折叠成 0 宽度,并且作为 flex-basis 通常需要为 auto,但在 break-able 的父级上为 0pxflex-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

堆栈sn-p

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

【讨论】:

  • 感谢您的回答。真的很近。确实,它解决了最初的问题;但是,我在对问题的更新中添加了一个附加要求:“在 flex-child 中,可以有可换行文本和不可换行文本的任意组合”。不幸的是,它没有满足这个额外的要求。我会看看我是否可以使用您提出的解决方案,除非出现更好的解决方案。
  • @Jonathan 是的,我理解它可能,有时它就足够了,有时又不够......所以我很确定你需要一个脚本后备,以涵盖所有这些异常,或者只是拥有 IE以它的方式呈现它
  • 经过一些测试,我发现这在我正在编写的实际应用程序中可以工作,除了两个问题:(1) min-width 值导致内容溢出(不在我给出的简化示例中这里)。 (2) 假设动态生成的内容在所有三个 flex-children 中都有可换行的文本。您的解决方案会导致再次发生溢出(将 .child-3 CSS 应用于每个 flex-children 时)。我尝试overflow: auto 来解决其中的一些问题,但它导致 flex-children 无法正确包装。
【解决方案2】:

不是首选解决方案,因为它使用 Javascript。但是,它有效。

在创建所有 flex-children 之后,每当屏幕尺寸发生变化时,检查每个 flex-child 的宽度是否小于其内容的宽度(为此,必须使用 @987654322 包裹内容@)。如果是这样,为 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);
    });
}

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-08
    • 2018-03-04
    • 2021-04-11
    • 2018-06-04
    • 2017-09-07
    • 2019-01-14
    • 2019-04-30
    • 2020-12-10
    相关资源
    最近更新 更多