152

自从从 TABLE-layout 切换到 DIV-layout 后,一个常见的问题仍然存在:

问题:你用动态文本填充你的 DIV,不可避免地会有一个超长的词延伸到你的 div 列的边缘,使你的网站看起来不专业。

RETRO-WHINING:这在表格布局中从未发生过。表格单元格总是会很好地扩展到最长单词的宽度。

严重性:我什至在最主要的网站上也看到了这个问题,特别是在德国网站上,即使是“限速”等常用词也很长(“Geschwindigkeitsbegrenzung”)。

有没有人对此有可行的解决方案?

4

26 回答 26

139

软连字符

您可以通过插入软连字符 ( ) 告诉浏览器在哪里拆分长词­

averyvery­longword

可以呈现为

非常非常长的词

或者

非常
长词

一个好的正则表达式可以确保您不会插入它们,除非有必要:

/([^\s-]{5})([^\s-]{5})/ → $1­$2

浏览器和搜索引擎足够聪明,可以在搜索文本时忽略此字符,而 Chrome 和 Firefox(尚未测试其他人)在将文本复制到剪贴板时会忽略它。

<wbr>元素

另一种选择是注入<wbr>,以前的IE-ism,现在是 HTML5

averyvery<wbr>longword

没有连字符的中断:

非常
长的词

您可以使用零宽度空格字符&#8203;(或&#x200B)来实现相同的目的。


仅供参考,最新的 IE、Firefox 和 Safari(但目前不支持 Chrome )也支持CSShyphens: auto

div.breaking {
  hyphens: auto;
}

但是,这种连字符是基于连字符字典的,并且不能保证会打断长词。它可以使合理的文本更漂亮。

复古抱怨解决方案

<table>for 布局很糟糕,但display:table在其他元素上很好。它将像老式桌子一样古怪(和有弹性):

div.breaking {
   display: table-cell;
}

overflow下面的white-space: pre-wrap答案也很好。

于 2008-11-26T10:20:49.237 回答
40

两个修复:

  1. overflow:scroll-- 这可以确保你的内容可以被看到,但代价是设计(滚动条很难看)
  2. overflow:hidden- 只是切断任何溢出。这意味着人们无法阅读内容。

如果(在 SO 示例中)您想阻止它与填充重叠,您可能必须在填充内创建另一个 div 来保存您的内容。

编辑:正如其他答案所述,有多种截断单词的方法,即在客户端计算渲染宽度(永远不要尝试在服务器端执行此操作,因为它永远不会可靠地工作,跨平台)通过JS 和插入中断字符,或使用非标准和/或完全不兼容的 CSS 标记(word-wrap: break-word 在 Firefox 中似乎不起作用)。

不过,您总是需要一个溢出描述符。如果您的 div 包含另一个太宽的块类型内容(图像、表格等),您将需要溢出以使其不会破坏布局/设计。

因此,请务必使用另一种方法(或它们的组合),但请记住也要添加溢出,以便覆盖所有浏览器。

编辑2(以解决您在下面的评论):

开始使用 CSSoverflow属性并不完美,但它可以阻止设计中断。先申请overflow:hidden。请记住,溢出可能不会在填充上中断,因此可以使用 nestdiv或使用边框(无论哪种方式最适合您)。

这将隐藏溢出的内容,因此您可能会失去意义。您可以使用滚动条(使用overflow:autooverflow:scroll代替overflow:hidden),但根据 div 的尺寸和您的设计,这可能看起来或效果不佳。

为了解决这个问题,我们可以使用 JS 将内容拉回来并进行某种形式的自动截断。我正在为您编写一些伪代码,但在中途它变得非常复杂。如果您需要尽可能多地显示,请在hyphenator中查看(如下所述)。

请注意,这是以用户 CPU 为代价的。这可能导致页面需要很长时间才能加载和/或调整大小。

于 2008-11-26T10:02:02.707 回答
33

正如我们所知,这是一个复杂的问题,并且在浏览器之间没有任何常见的方式支持。大多数浏览器根本不支持此功能。

在使用 HTML 电子邮件完成的一些工作中,使用了用户内容,但脚本不可用(甚至 CSS 也没有得到很好的支持),围绕未分隔内容块的包装器中的以下 CSS 位至少应该有所帮助:

.word-break {
  /* The following styles prevent unbroken strings from breaking the layout */
  width: 300px; /* set to whatever width you need */
  overflow: auto;
  white-space: -moz-pre-wrap; /* Mozilla */
  white-space: -hp-pre-wrap; /* HP printers */
  white-space: -o-pre-wrap; /* Opera 7 */
  white-space: -pre-wrap; /* Opera 4-6 */
  white-space: pre-wrap; /* CSS 2.1 */
  white-space: pre-line; /* CSS 3 (and 2.1 as well, actually) */
  word-wrap: break-word; /* IE */
  -moz-binding: url('xbl.xml#wordwrap'); /* Firefox (using XBL) */
}

对于基于 Mozilla 的浏览器,上述 XBL 文件包含:

<?xml version="1.0" encoding="utf-8"?>
<bindings xmlns="http://www.mozilla.org/xbl" 
          xmlns:html="http://www.w3.org/1999/xhtml">
  <!--
  More information on XBL:
  http://developer.mozilla.org/en/docs/XBL:XBL_1.0_Reference

  Example of implementing the CSS 'word-wrap' feature:
  http://blog.stchur.com/2007/02/22/emulating-css-word-wrap-for-mozillafirefox/
  -->
  <binding id="wordwrap" applyauthorstyles="false">
    <implementation>
      <constructor>
        //<![CDATA[
        var elem = this;

        doWrap();
        elem.addEventListener('overflow', doWrap, false);

        function doWrap() {
          var walker = document.createTreeWalker(elem, NodeFilter.SHOW_TEXT, null, false);
          while (walker.nextNode()) {
            var node = walker.currentNode;
            node.nodeValue = node.nodeValue.split('').join(String.fromCharCode('8203'));
          }
        }
        //]]>
      </constructor>
    </implementation>
  </binding>
</bindings>

不幸的是,Opera 8+ 似乎不喜欢上述任何解决方案,因此 JavaScript 必须成为这些浏览器(如 Mozilla/Firefox)的解决方案。另一个跨浏览器解决方案 (JavaScript) 包括更高版本的 Opera将使用在这里找到的 Hedger Wang 的脚本: http ://www.hedgerwow.com/360/dhtml/css-word-break.html

其他有用的链接/想法:

不连贯的 Babble » 博客存档 » 为 Mozilla/Firefox 模拟 CSS 自动换行
http://blog.stchur.com/2007/02/22/emulating-css-word-wrap-for-mozillafirefox/

[OU] Opera 中没有自动换行,在 IE 中显示正常
http://list.opera.com/pipermail/opera-users/2004-November/024467.html
http://list.opera.com/pipermail/opera- users/2004-11月/024468.html

于 2009-03-31T23:03:58.063 回答
27

CSS 跨浏览器自动换行

.word_wrap
{
    white-space: pre-wrap; /* css-3 */
    white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
    white-space: -pre-wrap; /* Opera 4-6 */
    white-space: -o-pre-wrap; /* Opera 7 */
    word-wrap: break-word; /* Internet Explorer 5.5+ */
}
于 2011-01-12T12:38:20.463 回答
16

使用风格word-break:break-all;。我知道它适用于桌子。

于 2010-08-09T18:06:14.543 回答
13

你的意思是,在支持它的浏览器中,word-wrap: break-word不起作用?

如果包含在样式表的正文定义中,它应该适用于整个文档。

如果溢出不是一个好的解决方案,只有自定义的 javascript 可以人为地分解长单词。

注意:还有这个<wbr>Word Break 标签。这为浏览器提供了一个可以拆分队列的位置。不幸的是,该<wbr>标签不适用于所有浏览器,只有 Firefox 和 Internet Explorer(以及带有 CSS 技巧的 Opera)。

于 2008-11-26T10:02:07.747 回答
9

刚刚检查了 IE 7、Firefox 3.6.8 Mac、Firefox 3.6.8 Windows 和 Safari:

word-wrap: break-word;

适用于具有设定宽度且在 css 中声明没有溢出的 div 内的长链接:

#consumeralerts_leftcol{
    float:left;
    width: 250px;
    margin-bottom:10px;
    word-wrap: break-word;
}

我没有看到任何不兼容问题

于 2010-08-24T21:23:41.987 回答
6

我刚刚从这个问题中发现了连字符。那可能会解决问题。

于 2008-11-26T10:40:41.100 回答
6

经过多次战斗,这对我有用:

.pre {
    font-weight: 500;
    font-family: Courier New, monospace;
    white-space: pre-wrap;
    word-wrap: break-word;
    word-break: break-all;
    -webkit-hyphens: auto;
    -moz-hyphens: auto;
    hyphens: auto;
}

适用于最新版本的 Chrome、Firefox 和 Opera。

请注意,我排除white-space了其他人建议的许多属性——这实际上打破了pre我的缩进。

于 2012-07-16T18:47:18.827 回答
5

对我来说,在没有固定大小和动态内容的 div 上,它使用:

display:table;
word-break:break-all;
于 2013-03-06T08:45:05.280 回答
4

对于这个问题,我通常使用的解决方案是为 IE 和其他浏览器设置 2 个不同的 css 规则:

word-wrap: break-word;

在 IE 中很完美,但自动换行不是标准的 CSS 属性。这是 Microsoft 特有的属性,在 Firefox 中不起作用。

对于 Firefox,最好只使用 CSS 来设置规则

overflow: hidden;

对于包含要换行的文本的元素。它不换行文本,而是隐藏超出容器限制的文本部分<a>如果您不需要显示所有文本(即,如果文本在标签内),这可能是一个很好的解决方案

于 2008-11-26T11:24:01.060 回答
4

重新使用此评论中的正则表达式,这很好,但它仅在 5 个非空白或连字符的组之间添加了连字符。这允许最后一组比预期的长得多,因为它后面没有匹配的组。

例如,这个:

'abcde12345678901234'.replace(/([^\s-]{5})([^\s-]{5})/g, '$1&shy;$2')

...结果:

abcde&shy;12345678901234

这是一个使用正向前瞻来避免该问题的版本:

.replace(/([^\s-]{5})(?=[^\s-])/g, '$1&shy;')

...结果如下:

abcde&shy;12345&shy;67890&shy;1234
于 2011-06-09T20:17:27.307 回答
4

更新:在 CSS 中处理这个非常简单且开销很低,但是您无法控制中断发生的位置。如果您不在乎,那很好,或者您的数据有很长的字母数字运行而没有任何自然中断。我们有很多长文件路径、URL 和电话号码,所有这些都有比其他文件更容易破解的地方。

我们的解决方案是首先使用正则表达式替换,在每 15 个(比如说)不是空格的字符或我们希望中断的特殊字符之一之后放置一个零宽度空格(​)。然后我们再做一次替换,在这些特殊字符之后放置一个零宽度的空格。

零宽度空间很好,因为它们在屏幕上是不可见的;害羞的连字符在显示时会让人感到困惑,因为数据中有重要的连字符。从浏览器中复制文本时,也不包括零宽度空格。

我们目前使用的特殊中断字符是句点、正斜杠、反斜杠、逗号、下划线、@、| 和连字符。你不会认为你需要做任何事情来鼓励在连字符后中断,但 Firefox(至少 3.6 和 4)不会在由数字(如电话号码)包围的连字符处自行中断。

我们还想根据可用的布局空间来控制人为中断之间的字符数。这意味着匹配长时间不间断运行的正则表达式需要是动态的。这被调用了很多,出于性能原因,我们不想一遍又一遍地创建相同的正则表达式,所以我们使用了一个简单的正则表达式缓存,由正则表达式及其标志键控。

这是代码;您可能会命名实用程序包中的函数:

makeWrappable = function(str, position)
{
    if (!str)
        return '';
    position = position || 15; // default to breaking after 15 chars
    // matches every requested number of chars that's not whitespace or one of the special chars defined below
    var longRunsRegex = cachedRegex('([^\\s\\.\/\\,_@\\|-]{' + position + '})(?=[^\\s\\.\/\\,_@\\|-])', 'g');
    return str
                .replace(longRunsRegex, '$1&#8203;') // put a zero-width space every requested number of chars that's not whitespace or a special char
                .replace(makeWrappable.SPECIAL_CHARS_REGEX, '$1&#8203;'); // and one after special chars we want to allow breaking after
};
makeWrappable.SPECIAL_CHARS_REGEX = /([\.\/\\,_@\|-])/g; // period, forward slash, backslash, comma, underscore, @, |, hyphen


cachedRegex = function(reString, reFlags)
{
    var key = reString + (reFlags ? ':::' + reFlags : '');
    if (!cachedRegex.cache[key])
        cachedRegex.cache[key] = new RegExp(reString, reFlags);
    return cachedRegex.cache[key];
};
cachedRegex.cache = {};

像这样测试:

makeWrappable('12345678901234567890 12345678901234567890 1234567890/1234567890')

更新 2:似乎零宽度空格实际上至少在某些情况下包含在复制的文本中,您只是看不到它们显然,鼓励人们复制带有隐藏字符的文本是在邀请将此类数据输入其他程序或系统,甚至是您自己的程序或系统,这可能会导致问题。例如,如果它最终在数据库中,针对它的搜索可能会失败,并且像这样的搜索字符串也可能会失败。使用箭头键在这样的数据中移动需要(正确地)额外的按键来移动你看不到的字符,如果用户注意到的话,这对用户来说有点奇怪。

在封闭系统中,您可以在输入时过滤掉该字符以保护自己,但这对其他程序和系统没有帮助。

总而言之,这种技术效果很好,但我不确定什么是破坏角色的最佳选择。

更新 3:让这个字符最终出现在数据中不再是理论上的可能性,而是一个观察到的问题。用户提交从屏幕上复制的数据,它被保存在数据库中,搜索中断,事情排序奇怪等等。

我们做了两件事:

  1. 编写了一个实用程序,将它们从该应用程序的所有数据源中所有表的所有列中删除。
  2. 添加了过滤以将其删除到我们的标准字符串输入处理器中,因此在任何代码看到它时它就消失了。

这很有效,技术本身也很有效,但这是一个警示故事。

更新 4:我们在提供给它的数据可能是 HTML 转义的上下文中使用它。在适当的情况下,它可以在 HTML 实体的中间插入零宽度的空格,从而获得时髦的结果。

修复是在我们不中断的字符列表中添加&符号,如下所示:

var longRunsRegex = cachedRegex('([^&\\s\\.\/\\,_@\\|-]{' + position + '})(?=[^&\\s\\.\/\\,_@\\|-])', 'g');
于 2011-06-28T14:34:22.183 回答
3

需要设置“表格布局:固定”才能使自动换行工作

于 2010-08-11T14:36:51.553 回答
2

HYPHENATOR 是正确的答案(如上所示)。您的问题背后的真正问题是网络浏览器(在 2008 年)仍然非常原始,它们没有连字符功能。看,我们仍处于计算机使用的早期阶段——我们必须要有耐心。只要设计师统治网络世界,我们将很难等待一些真正有用的新功能。

更新:截至 2011 年 12 月,我们现在有了另一种选择,即 FF 和 Safari 中对这些标签的新兴支持:

p {
    -webkit-hyphens: auto;
    -moz-hyphens: auto;
    hyphens: auto;
}

我已经完成了一些基本测试,它似乎可以在最新版本的 Mobile Safari 和 Safari 5.1.1 上运行。

兼容性表:https ://developer.mozilla.org/en/CSS/hyphens#AutoCompatibilityTable

于 2008-11-26T11:37:55.947 回答
2

为了与 IE 8+ 兼容,请使用:

-ms-word-break: break-all;
     word-break: break-all;

     /* Non standard for webkit */
     word-break: break-word;

-webkit-hyphens: auto;
   -moz-hyphens: auto;
        hyphens: auto;

在这里查看http://css-tricks.com/snippets/css/prevent-long-urls-from-break-out-of-container/

我所要做的就是将其应用于具有设定宽度的 div 容器的样式。

于 2013-07-12T22:38:16.827 回答
2
p {
    overflow-wrap: break-word;
}


@-moz-document url-prefix() { 
    p {
        white-space: -moz-pre-wrap;
        word-wrap: break-word;
    }
}
于 2014-11-20T16:19:44.903 回答
2

用这个

word-wrap: break-word;
overflow-wrap: break-word;
word-break: break-all;
于 2016-01-07T09:10:51.407 回答
1

是的,如果可能的话,设置绝对宽度和设置overflow : auto效果很好。

于 2009-03-31T20:58:40.597 回答
1

如果你有这个 -

  <style type="text/css">
      .cell {
            float: left;
            width: 100px;
            border: 1px solid;
            line-height: 1em;
      }
  </style>

  <div class="cell">TopLeft</div>
  <div class="cell">TopMiddlePlusSomeOtherTextWhichMakesItToLong</div>
  <div class="cell">TopRight</div>
  <br/>
  <div class="cell">BottomLeft</div>
  <div class="cell">BottomMiddle</div>
  <div class="cell">bottomRight</div>

只需切换到包含 div 的垂直格式,并在 CSS 中使用 min-width 而不是 width -

  <style type="text/css">
      .column {
            float: left;
            min-width: 100px;
      }
      .cell2 {
            border: 1px solid;
            line-height: 1em;
      }
  </style>

  <div class="column">
      <div class="cell2">TopLeft</div>
      <div class="cell2">BottomLeft</div>
  </div>
  <div class="column">
      <div class="cell2">TopMiddlePlusSomeOtherTextWhichMakesItToLong</div>
      <div class="cell2">BottomMiddle</div>
  </div>
  <div class="column">
      <div class="cell2">TopRight</div>
      <div class="cell2">bottomRight</div>
  </div>
  <br/>

当然,如果您要显示真正的表格数据,则可以使用真正的表格,因为它在语义上是正确的,并且会通知人们使用应该在表格中的屏幕阅读器。它正在将它们用于一般布局或图像切片,人们会为此而私刑。

于 2009-05-21T00:26:28.237 回答
1

我必须执行以下操作,因为如果未按正确顺序声明属性,它会在错误的位置随机破坏单词并且不添加连字符。

    -moz-white-space: pre-wrap;
white-space: pre-wrap;        
    hyphens: auto;
    -ms-word-break: break-all;
    -ms-word-wrap: break-all;
    -webkit-word-break: break-word;
    -webkit-word-wrap: break-word;
word-break: break-word;
word-wrap: break-word;
    -webkit-hyphens: auto;
    -moz-hyphens: auto;
    -ms-hyphens: auto;
hyphens: auto;

最初由 Enigmo 发布:https ://stackoverflow.com/a/14191114

于 2014-06-11T08:25:59.220 回答
0

"word-wrap: break-word" 适用于 Firefox 3.5 http://hacks.mozilla.org/2009/06/word-wrap/

于 2010-04-17T20:24:18.570 回答
0

在所有的单词换行和中断之后,保留你的溢出,看看这是否能解决你的问题。只需将 div 的显示更改为:display: inline;

于 2013-06-02T13:17:20.650 回答
0

将此添加到css您的 div 中:word-wrap: break-word;

于 2014-05-15T19:14:06.633 回答
-1

一个简单的函数(需要 underscore.js)——基于 @porneL 的回答

    String.prototype.shyBreakString = function(maxLength) {
        var shystring = [];
        _.each(this.split(' '), function(word){
            shystring.push(_.chop(word, maxLength).join('&shy;'));
        });
        return shystring.join(' ');
    };
于 2013-09-30T00:01:05.147 回答
-1

我编写了一个很好用的函数,它可以&shy;在单词中插入 x 字母以实现良好的换行。这里的所有答案都不支持所有浏览器和设备,但使用 PHP 效果很好:

/**
 * Add line-break to text x characters in
 * @param  string  $text          
 * @param  integer $characters_in 
 * @return string                 
 */
function line_break_text($text, $characters_in = 10) {

    $split = explode(' ', $text);

    if ( ! empty($split)) {

        foreach ($split as $key => $var) {

            if ( strlen($var) > $characters_in ) {

                $split[$key] = substr_replace($var, '&shy;', $characters_in, 0);

            }

        }

    }

    return implode(' ', $split);

}
于 2017-11-15T17:08:42.787 回答