让 overflow-wrap 失效的 flex-wrap

1,614 阅读4分钟

注: word-wrap 属性原本属于微软的一个私有属性,在 CSS3 现在的文本规范草案中已经被重名为 overflow-wrap 。 word-wrap 现在被当作 overflow-wrap 的 “别名”。 稳定的谷歌 Chrome 和 Opera 浏览器版本支持这种新语法。

连续长单词换行问题

overflow-wrap 是用来说明当一个不能被分开的字符串太长而不能填充其包裹盒子时,为防止其溢出,浏览器是否允许这样的单词中断换行。

默认情况 overflow-wrap: normal; 下是不换行的:

https://developer.mozilla.org/zh-CN/docs/Web/CSS/overflow-wrap

overflow-wrap 取值为 break-word 长文本既可以截断了:

https://developer.mozilla.org/zh-CN/docs/Web/CSS/overflow-wrap

overflow-wrap 还有个 anywhere 值,不在今天探讨内容。

CSS3 几个新的宽度成员

flex nowrap 的作用规则有点复杂,并不是简单的不换行展示,需要用到 min-content 知识,关于这个内容参考,张鑫旭老师的这篇文章:理解CSS3 max/min-content及fit-content等width值

解释下最小宽度 min-content:

<div style="background-color: greenyellow;">
      <div style="width: 100px;height: 20px;margin-bottom: 50px;background-color: #f2f;">1</div>
      <div style="width: 200px;height: 20px;margin-bottom: 50px;background-color: #f2f;">2</div>
      <div style="width: 300px;height: 20px;margin-bottom: 50px;background-color: #f2f;">3</div>
      <div style="width: 400px;height: 20px;margin-bottom: 50px;background-color: #f2f;">4</div>
    </div>

四个盒子竖排排列,在标准文档流子盒子撑开了父盒子,宽度自动填充,于是 greenyellow 沾满了屏幕。

greenyellow

当更改宽度为 min-content:

<div style="width: min-content; background-color: greenyellow;">
      <div style="width: 100px;height: 20px;margin-bottom: 50px;background-color: #f2f;">1</div>
      <div style="width: 200px;height: 20px;margin-bottom: 50px;background-color: #f2f;">2</div>
      <div style="width: 300px;height: 20px;margin-bottom: 50px;background-color: #f2f;">3</div>
      <div style="width: 400px;height: 20px;margin-bottom: 50px;background-color: #f2f;">4</div>
    </div>

greenyellow 变成了 400px

greenyellow 变成了 400px,收缩为子元素最大的一个宽度,这就是 min-content 内部元素最小宽度值最大的那个元素的宽度作为最终容器的宽度

flex-wrap: nowrap;

  • flex-wrap: nowrap; 默认值,表示单行显示,不换行。于是很容易出现宽度溢出的场景,其渲染表现比较复杂,需要对CSS3宽度有一定了解,可以阅读“理解CSS3 max/min-content及fit-content等width值”这篇文章。具体表现如下(以水平布局举例):

    • flex子项最小内容宽度min-content之和大于flex容器宽度,则内容溢出,表现和white-space:nowrap类似。

    • 如果flex子项最小内容宽度min-content之和小于flex容器宽度,则:

      • flex子项默认的fit-content宽度之和大于flex容器宽度,则flex子项宽度收缩,正好填满flex容器,内容不溢出。
      • flex子项默认的fit-content宽度之和小于flex容器宽度,则flex子项以fit-content宽度正常显示,内容不溢出。

上面摘自张鑫旭老师的文章:写给自己看的display: flex布局教程,作为定理放在这,下面解释现象会引用到。

正常盒子长文本换行显示

在线演示代码可直接访问:codepen.io/lehollandai…

正常盒子长文本换行显示

代码如下:

<style>
  .parent {
    width: 200px;
    overflow-wrap: break-word;
    background: gold;
    border: 1px solid transparent;
  }
  .parent div {
    background: silver;
    margin: 5px;
  }
</style>
<h2>Example without <code>display:flex</code>:</h2>
<div class="parent">
  <div>Sidebar with fixed with</div>
  <div>this is a flexible box with a really loooooooooooooooooooooooooooooooooooong word inside.</div>
</div>

overflow-wrap: break-word; 运行良好完全没问题。

flex 布局长文本换行显示异常

flex 布局长文本换行显示异常

代码异常简单:

<style>
  .parent {
    width: 200px;
    overflow-wrap: break-word;
    background: gold;
    border: 1px solid transparent;
  }
  .parent div {
    background: silver;
    margin: 5px;
  }
  #parent-flex {
    display: flex;
  }
</style>
<h2>Example with <code>display:flex</code>:</h2>
<div class="parent" id="parent-flex">
  <div>Sidebar with fixed with</div>
  <div>this is a flexible box with a really loooooooooooooooooooooooooooooooooooong word inside.</div>
</div>

分析下形成的原因,flex 布局下子项的宽为 width: min-content;,所以各自子项的宽就是各自盒子里面最长的那个单词,因为我们没有直接设置子项的 min-content,Sidebar+ loooooooooooooooooooooooooooooooooooong 两个单词的长度占用的宽度加起来,去和 flex 容器盒子宽度比较,符合上面讲到的flex子项最小内容宽度min-content之和大于flex容器宽度,则内容溢出,表现和white-space:nowrap类似。,自然内容溢出。

子项 loooooooooooooooooooooooooooooooooooong 的长度等于子项盒子的宽度,这种情况下 文本没溢出 overflow-wrap: break-word; 就完全没起作用了,如果想让 overflow-wrap: break-word; 起作用就得把子项的宽度变窄。

怎么变窄呢?根据上面提到的:

如果flex子项最小内容宽度min-content之和小于flex容器宽度,则:

  • flex子项默认的fit-content宽度之和大于flex容器宽度,则flex子项宽度收缩,正好填满flex容器,内容不溢出。

只需要保证子项的 min-content 小于 flex 容器宽度就行了,简单的添加一段 CSS 代码:

#parent-flex > div{
    min-width: 0;
}

我们设置了 min-width ,两个子项的 min-content 现在为零,小于 flex 容器宽度,子项里面的 fit-content宽度之和大于flex容器宽度,此时 flex 子项宽度收缩,正好填满 flex 容器,内容不溢出。

结果是子项被缩短了,长文本能溢出,overflow-wrap: break-word; 也就起作用了。

overflow-wrap 生效了

张鑫旭老师的文章:写给自己看的display: flex布局教程,讲解 nowrap 的时候有一个演示例子可以看看,加强理解。

总结

当长文本溢出,想要进行换行展示,我们想到了 overflow-wrap: break-word;,但结合 flex 布局使用的时候,发现 overflow-wrap 没有生效,原来是因为 flex-wrap: nowrap; 导致的,因为子项采用 min-content 来进行撑宽的,导致子项最长的文本和子项一样宽,没有发生溢出现象,解决办法就是缩小子项的宽度,产生溢出现象,于是通过 min-width=0 来实现。