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

时间:2008-11-26 09:53:46

标签: css layout html

自从从TABLE布局切换到DIV布局以来,仍然存在一个常见问题:

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

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

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

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

26 个答案:

答案 0 :(得分:135)

软连字符

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

averyvery­longword

可以呈现为

  

averyverylongword

  

averyvery-
      长字

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

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

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

<wbr>元素

另一个选择是注入<wbr>,一个前IE-ism,现在是in HTML5

averyvery<wbr>longword

没有连字符打破:

  

averyvery
      长字

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


仅供参考,最新的IE,Firefox和Safari(CSS hyphens: auto)也支持but currently not Chrome

div.breaking {
  hyphens: auto;
}

然而,该连字符基于连字符词典并且不能保证打破长词。它可以使合理的文本更漂亮。

复古抱怨解决方案

<table>布局不好,但其他元素上的display:table也没问题。它将像老式的桌子一样古怪(和有弹性):

div.breaking {
   display: table-cell;
}

overflowwhite-space: pre-wrap以下答案也不错。

答案 1 :(得分:41)

两个修正:

  1. overflow:scroll - 这可以确保您的内容以设计为代价(滚动条很难看)
  2. overflow:hidden - 只是切断任何溢出。这意味着人们无法阅读内容。
  3. 如果(在SO示例中)你想要阻止它与填充重叠,你可能必须在填充内创建另一个div来保存你的内容。

    编辑:正如其他答案所述,有多种截断单词的方法,就是在客户端计算渲染宽度(从不尝试做这个服务器端,因为它永远不会可靠地工作,交叉平台)通过JS并插入break-characters,或使用非标准和/或非常不兼容的CSS标签(word-wrap: break-word doesn't appear to work in Firefox)。

    但是你总是需要一个溢出描述符。如果你的div包含另一个太宽的块类型的内容(图像,表格等),你需要溢出才能使它不破坏布局/设计。

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

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

    使用CSS overflow属性开始并不完美,但它会阻止设计破解。首先应用overflow:hidden。请记住,填充可能不会在填充中断,因此嵌套div或使用边框(任何最适合您的边框)。

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

    要修复它,我们可以使用JS来回退并执行某种形式的自动截断。我在为你编写一些伪代码的过程中,但是在中途变得非常复杂。如果您需要尽可能多地展示,请在hyphenator中查看as mentioned below

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

答案 2 :(得分: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-November/024468.html

答案 3 :(得分:27)

CSS Cross Browser Word Wrap

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

答案 4 :(得分:14)

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

答案 5 :(得分:13)

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

如果included in the body definition of the stylesheet,它应该适用于整个文档。

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

注意:还有<wbr> Word Break tag。这为浏览器提供了一个可以分割线的位置。遗憾的是,<wbr>标记在所有浏览器中都不起作用,只有Firefox和Internet Explorer(以及带有CSS技巧的Opera)。

答案 6 :(得分: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;
}

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

答案 7 :(得分:6)

我刚刚从hyphenator了解了this question。这可能会解决问题。

答案 8 :(得分: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缩进。

答案 9 :(得分:5)

对于我没有固定大小和动态内容的div,我使用:

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

答案 10 :(得分:4)

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

word-wrap: break-word;

在IE浏览器中完美,但自动换行不是标准的CSS属性。它是Microsoft特定的属性,在Firefox中不起作用。

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

overflow: hidden;

表示包含要包装的文本的元素。它不会包装文本,但隐藏超出容器限制的文本部分。如果您不必显示所有文本(即文本是否在<a>标记内),这可能是一个很好的解决方案

答案 11 :(得分:4)

重新使用this comment中的正则表达式,这很好,但它只在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

答案 12 :(得分:4)

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

我们的解决方案是首先使用正则表达式替换来在每15个(比如说)字符之后放置一个零宽度空格(&amp;#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. 添加过滤以将其移除到我们的标准字符串输入处理器,因此在任何代码看到它时都会消失。
  3. 这样做效果很好,技术本身也是如此,但这是一个警示故事。

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

    修复是将&符号添加到我们没有打破的字符列表中,如下所示:

    var longRunsRegex = cachedRegex('([^&\\s\\.\/\\,_@\\|-]{' + position + '})(?=[^&\\s\\.\/\\,_@\\|-])', 'g');
    

答案 13 :(得分:3)

需要为word-wrap设置“table-layout:fixed”才能工作

答案 14 :(得分:2)

  

HYPHENATOR是正确答案(如上所述)。您的问题背后的真正问题是,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

答案 15 :(得分:2)

使用此

word-wrap: break-word;
overflow-wrap: break-word;
word-break: break-all;

答案 16 :(得分: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-breaking-out-of-container/

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

答案 17 :(得分: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/>

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

答案 18 :(得分: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

答案 19 :(得分:1)

p {
    overflow-wrap: break-word;
}


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

答案 20 :(得分:1)

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

答案 21 :(得分:0)

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

答案 22 :(得分:0)

在所有单词包装和休息之后, 保持你的溢出,看看这是否解决了你的问题。只需将div的显示更改为:display: inline;

答案 23 :(得分:0)

将其添加到您的div的cssword-wrap: break-word;

答案 24 :(得分:-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(' ');
    };

答案 25 :(得分:-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);

}