如何防止长词破坏我的div?


148

从TABLE布局切换到DIV布局以来,一个普遍的问题仍然存在:

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

RETRO-WHINING:表格布局从未发生过这种情况。一个表格单元将总是很好地扩展到最长单词的宽度。

严重性:我什至在大多数主要站点上都遇到了这个问题,尤其是在德国站点上,这些站点甚至连诸如“速度限制”之类的通用词都非常长(“ Geschwindigkeitsbegrenzung”)。

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


4
您一定已经忘记了那些超级拉伸且有效破坏的表布局。我会溢出:任何一天都隐藏在无法控制的拉伸细胞中。
Kornel

1
一个表格单元格将总是很好???????? 扩展到最长的单词的宽度
尽管有

1
我认识很多人(也许我会算在内),他们会说这是更糟糕的行为。页面和元素的宽度通常要花很多时间。如果您可能会有随机的单词使宽度无法控制,则说明您的设计失败了。
奥利

13
我一直觉得表的行为更符合HTML最初的灵活性哲学。DIV / CSS刚性柱宽哲学似乎来自杂志设计者,他们无法应对有时宽而窄的色谱柱。
爱德华·唐格

1
一个好的设计应该是一致的;如果页面内容能够更改UI的尺寸,则会违反设计。认真地说,您将在哪里绘制具有伸缩性的线条?Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch?
琼斯医生

Answers:


138

软连字符

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

averyvery­longword

可能呈现为

veryverylongword

要么

每个

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

/([^\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>布局不好,但display:table在其他元素上很好。它会像老式桌子一样古怪(并且富有弹性):

div.breaking {
   display: table-cell;
}

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


7
凉!根据维基百科,您可以使用&#8203;获得零宽度的空间。-自从您提出以来,您是否知道它的丑陋转义代码?如果需要的话,我会记住8203,但是…
ojrac

1
@ojrac-这取决于您是否认为&#x200B; 是否“不太丑”。:-) AFAIK,零宽度空间没有“单词实体”。
本·布兰克

1
很好,但是不能解决最初的问题。
阿不思·邓布利多

25
这会中断复制/粘贴。
nornagon

4
仅供参考,您也可以使用<wbr>。参见quirksmode.org/oddsandends/wbr.html
HaxElit 2012年

40

两种修复:

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

如果(在SO示例中)要停止与填充重叠,则可能必须在填充内部创建另一个div来容纳内容。

编辑:作为其他答案的状态,有多种方法可以截断单词,例如在客户端上计算渲染宽度(不要尝试在服务器端进行渲染,因为它将永远无法可靠地工作,跨平台) JS和插入换行符,或使用非标准和/或完全不兼容的CSS标签(word-wrap: break-word 在Firefox中似乎不起作用)。

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

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

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

开始使用CSS overflow属性并不是完美的方法,但它会阻止设计中断。overflow:hidden先申请。请记住,溢出可能不会在填充时中断,所以请使用nest div或使用边框(最适合您的方法)。

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

要解决此问题,我们可以使用JS将内容拖回去并进行某种形式的自动截断。我在为您编写一些伪代码的过程中途中途,但是在途中它变得非常复杂。如果需要尽可能多地显示,请给连字符添加一个外观(如下所述)。

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


1
带有文本溢出:省略号; 文本可以很好地剪切。
Kornel

1
text-overflow:省略号仅适用于IE(并且通过扩展,是非标准的)。
奥利

overflow: scroll;如果内容包含有用的信息,我总是会去的。然后,下一个目标是尝试创建不会显示滚动条的CSS。如果确实如此,您总是将滚动条作为备份。
雪人2012年

关于使用text-overflow: ellipsis stackoverflow.com/a/22811590/759452
Adrien Be

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

其他有用的链接/想法:

Incoherent 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


如果我需要的是width:100%怎么办?这意味着100%的外部容器。这样做的目的是避免水平滚动条出现在页面上并弄乱布局的其余部分。
pilavdzice 2012年

1
较新版本的Firefox现在支持word-wrap: break-word;CSS属性,因此,如果不需要较早版本的Firefox支持,则可以消除XBL。
尼尔·梦露2012年

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+ */
}

Opera 9.24
SCC

14

使用样式word-break:break-all;。我知道它可以在桌子上工作。


@sanimalp在Opera 9.24中不支持
SCC

13

您是说在支持该功能的浏览器中word-wrap: break-word不起作用吗?

如果包含在样式表的主体定义中,则它应该在整个文档中都有效。

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

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


9

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

word-wrap: break-word;

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

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

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



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对我来说是缩进。


5

对于没有固定大小且具有动态内容的div来说,它可以使用:

display:table;
word-break:break-all;

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

4

我通常用于此问题的解决方案是为IE和其他浏览器设置2种不同的CSS规则:

word-wrap: break-word;

在IE中可以正常使用,但是自动换行不是标准的CSS属性。这是Microsoft的特定属性,在Firefox中不起作用。

对于Firefox,最好的做法是仅使用CSS设置规则

overflow: hidden;

包含要包装的文本的元素。它不包装文本,而是隐藏超出容器限制的文本部分。如果不是必须显示所有文本(例如,文本在<a>标签内),这可能是一个不错的解决方案


自动换行:打破字似乎在Firefox 10的工作没有问题啊
乔恩·施耐德

CanIUse说它与IE8 +,Firefox28 +,Chrome33 +,Safari7 +等兼容。caniuse.com/#search=word-wrap
Adrien Be

4

更新:在CSS中处理此问题非常简单且开销很小,但是您无法控制中断发生在何处。如果您不在乎,或者您的数据具有较长的字母数字运行而没有任何自然中断,那很好。我们有很多长文件路径,URL和电话号码,所有这些地方都有明显的优势。

我们的解决方案是首先使用正则表达式替换,在每隔15个(例如)非空格字符或需要中断的特殊字符之一之后放置零宽度空格(&#8203;)。然后,我们进行另一次替换,以在那些特殊字符之后放置一个零宽度的空格。

零宽度的空格很不错,因为它们在屏幕上永远不可见。害羞的连字符在显示时会造成混淆,因为数据中有很大的连字符。当您从浏览器中复制文本时,零宽度空格也不包括在内。

我们当前使用的特殊分隔符是句号,正斜杠,反斜杠,逗号,下划线,@,|和连字符。您不会认为需要采取任何措施来鼓励在连字符后面打断,但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');

我使用了它,但是对于一个长域名,我只需要运行一次,因此我将其缩短为:if(domainName.length > 15) domainName.replace(/([^\\s]{5})(?=[^\\s])/g, '$1&#8203;');
CBarr 2012年

3

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


1
这次真是万分感谢!自动换行:断词;否则不适用于表。
liviucmg

2

连字符是正确的答案(以上给出)。您的问题背后的真正问题是,Web浏览器(在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




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

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


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


1

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


1
p {
    overflow-wrap: break-word;
}


@-moz-document url-prefix() { 
    p {
        white-space: -moz-pre-wrap;
        word-wrap: break-word;
    }
}



0

在所有的单词都折断后,保留您的溢出内容,看看是否能解决您的问题。只需将div的显示更改为:display: inline;


-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(' ');
    };

-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);

}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.