Flex-Basis: 0% 在 IE11 中导致不正确的溢出
Flex-Basis: 0% causes incorrect overflow in IE11
我遇到的问题涉及 flex-basis: 0%;
以及当用户减小 window 的宽度时 IE11 如何处理它。可能与 box-sizing.
的错误有关
我有可变数量的 flex-children,每个 child 的宽度未知。每个 child 都有任意 dynamically-generated 内容。但是,其中一些内容必须能够换行。
flex-container 本身必须有 100% 宽度并且必须能够包裹它的 children(即 flex-wrap: wrap
)。
假设存在三个 flex-children,最后一个需要 text-wrapping:
<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;
}
当 window 足够宽时,每个 flex-child 应该是 side-by-side,并且文本不会折叠:
当 window 水平收缩时,right-most 框中的文本应开始换行:
并且当文本不能再分行时,flex-boxes 本身应该开始分行:
这适用于大多数现代浏览器,但不适用于我们的朋友 IE11。在 IE11 中,当更改屏幕大小时,文本很好地换行,但 flex-children 根本不换行。因为 flex-children 不换行,它们的内容会相互溢出:
将 flex basis 更改为 flex-basis: auto;
会产生相反的效果:文本不会换行但 flex-children 会换行,但内容不会溢出(在此屏幕截图中,绿色框中的文本应该换行而不是 flex-box 换行):
我见过的大多数解决方案都需要 fixed-length flex-children,但我在这里负担不起,因为它们是动态生成的。我故意没有使用 flex
快捷方式 属性 因为它有一些其他的 non-related 问题。 建议使用 _:-ms-fullscreen, :root .IE11-only-class { /* IE11 specific properties */ }
如果我可以解决 text-wrapping 问题,这可能会起作用,但我无法弄清楚。
我还应该说我只需要它在最新的浏览器上工作(技术上只在某些版本的 Chrome 和 IE11 上工作,但其他浏览器和版本也能工作是一个加号)。
这里 code pen 显示了完整的问题(在 IE11 和 Chrome 中查看区别)。
有没有人知道如何解决这个问题?
记住,要求是:
- 未知数量 flex-children 未指定宽度
- 某些文本必须在 flex-boxes 换行
之前换行
- flex-children 一旦文本不能再换行就必须换行
- Chrome(我使用的是 59.0.3071.109)和 IE11(我使用的是 11.0.9600.18816CO)应该以相同的方式运行。
- CSS-only解决方案优先
谢谢。
更新:
我的一位同事建议为 flex-children 使用单独的 class,不包含可换行的文本。下面的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>
在这种情况下,第二个 div 中的文本在第三个 flex-child 中流出其容器,并且文本过早开始换行。
可以看到显示此 almost-working 解决方案的代码笔 here(请注意,min-width
已被删除,因为它在 Chrome 上引起了进一步的问题)。
更新二:
我认为我之前说得不够清楚:flex-children 的任何、全部或 none 可能有可换行的文本。这完全取决于 dynamically-generated 内容。在我给出的示例中,只有第三个 flex-child 具有可换行的文本,但情况可能并非总是如此。
注意,这个答案是在问题的 2 次更新之前发布的,这使得它部分无效,但我暂时保留它,有人可能需要它。
经过反复试验,我想出了这个设置,我的目标是让 IE 尽可能模仿其他浏览器的行为。
IE 需要 break-able 的父元素的最小宽度,因此文本在元素换行前不会折叠为 0 宽度,并且 flex-basis 通常需要 auto
但 break-able 的父 0px
flex-grow 需要在 5.
左右
我使用仅 IE11 选择器(我在 中展示)添加了以下规则。
_:-ms-fullscreen, :root .flex-child {
flex-basis: auto;
}
_:-ms-fullscreen, :root .child-3 {
flex: 5 0 0px;
min-width: 80px;
}
堆栈片段
.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>
这不是首选解决方案,因为它使用Javascript。但是,它有效。
在创建所有 flex-children 之后,每当屏幕尺寸发生变化时,检查每个 flex-child 的宽度是否小于其内容的宽度(为此,内容必须用带有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>
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。
不幸的是,由于 window 事件,此解决方案在管理资源时需要额外的开销。
我遇到的问题涉及 flex-basis: 0%;
以及当用户减小 window 的宽度时 IE11 如何处理它。可能与 box-sizing.
我有可变数量的 flex-children,每个 child 的宽度未知。每个 child 都有任意 dynamically-generated 内容。但是,其中一些内容必须能够换行。
flex-container 本身必须有 100% 宽度并且必须能够包裹它的 children(即 flex-wrap: wrap
)。
假设存在三个 flex-children,最后一个需要 text-wrapping:
<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;
}
当 window 足够宽时,每个 flex-child 应该是 side-by-side,并且文本不会折叠:
当 window 水平收缩时,right-most 框中的文本应开始换行:
并且当文本不能再分行时,flex-boxes 本身应该开始分行:
这适用于大多数现代浏览器,但不适用于我们的朋友 IE11。在 IE11 中,当更改屏幕大小时,文本很好地换行,但 flex-children 根本不换行。因为 flex-children 不换行,它们的内容会相互溢出:
将 flex basis 更改为 flex-basis: auto;
会产生相反的效果:文本不会换行但 flex-children 会换行,但内容不会溢出(在此屏幕截图中,绿色框中的文本应该换行而不是 flex-box 换行):
我见过的大多数解决方案都需要 fixed-length flex-children,但我在这里负担不起,因为它们是动态生成的。我故意没有使用 flex
快捷方式 属性 因为它有一些其他的 non-related 问题。 _:-ms-fullscreen, :root .IE11-only-class { /* IE11 specific properties */ }
如果我可以解决 text-wrapping 问题,这可能会起作用,但我无法弄清楚。
我还应该说我只需要它在最新的浏览器上工作(技术上只在某些版本的 Chrome 和 IE11 上工作,但其他浏览器和版本也能工作是一个加号)。
这里 code pen 显示了完整的问题(在 IE11 和 Chrome 中查看区别)。
有没有人知道如何解决这个问题?
记住,要求是:
- 未知数量 flex-children 未指定宽度
- 某些文本必须在 flex-boxes 换行 之前换行
- flex-children 一旦文本不能再换行就必须换行
- Chrome(我使用的是 59.0.3071.109)和 IE11(我使用的是 11.0.9600.18816CO)应该以相同的方式运行。
- CSS-only解决方案优先
谢谢。
更新:
我的一位同事建议为 flex-children 使用单独的 class,不包含可换行的文本。下面的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>
在这种情况下,第二个 div 中的文本在第三个 flex-child 中流出其容器,并且文本过早开始换行。
可以看到显示此 almost-working 解决方案的代码笔 here(请注意,min-width
已被删除,因为它在 Chrome 上引起了进一步的问题)。
更新二: 我认为我之前说得不够清楚:flex-children 的任何、全部或 none 可能有可换行的文本。这完全取决于 dynamically-generated 内容。在我给出的示例中,只有第三个 flex-child 具有可换行的文本,但情况可能并非总是如此。
注意,这个答案是在问题的 2 次更新之前发布的,这使得它部分无效,但我暂时保留它,有人可能需要它。
经过反复试验,我想出了这个设置,我的目标是让 IE 尽可能模仿其他浏览器的行为。
IE 需要 break-able 的父元素的最小宽度,因此文本在元素换行前不会折叠为 0 宽度,并且 flex-basis 通常需要 auto
但 break-able 的父 0px
flex-grow 需要在 5.
我使用仅 IE11 选择器(我在
_:-ms-fullscreen, :root .flex-child {
flex-basis: auto;
}
_:-ms-fullscreen, :root .child-3 {
flex: 5 0 0px;
min-width: 80px;
}
堆栈片段
.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>
这不是首选解决方案,因为它使用Javascript。但是,它有效。
在创建所有 flex-children 之后,每当屏幕尺寸发生变化时,检查每个 flex-child 的宽度是否小于其内容的宽度(为此,内容必须用带有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>
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。
不幸的是,由于 window 事件,此解决方案在管理资源时需要额外的开销。