JavaScript避免孤行问题

18

在 HTML/CSS 中处理排版时常见的问题是我们在瑞典称之为“horunge”(在英语中称为“widow”)。

它是什么:

假设你有一个宽度为 200px 的盒子,里面写着“我非常喜欢排版”。现在文字折行变成了:

我非常喜欢
排版

作为设计师,我不想要一个孤立的单词出现在一行上。如果这是一个文件/PDF 等等,我会在 very 前面断开单词,效果如下:

我非常喜欢
排版

看起来更好。

我能用 CSS 规则或 JavaScript 来解决这个问题吗?规则应该是不让一个单词空在一行上。

我知道可以通过添加 <br /> 来解决,但这不适用于动态宽度、提供的内容、不同的翻译、浏览器字体渲染问题等。

更新(解决方案) 我使用了这个 jQuery 插件来解决我的问题:http://matthewlein.com/widowfix/


Windows... 该死的 Word... 我爱瑞典! :) - rybo111
6个回答

8
一个简单的 jQuery / 正则表达式解决方案可能如下所示,如果您将类“noWidows”添加到包含您担心的任何文本的元素的标记中。

例如:

<p class="noWidows">This is a very important body of text.</p>

然后使用这个脚本:

$('.noWidows').each(function(i,d){
   $(d).html( $(d).text().replace(/\s(?=[^\s]*$)/g, "&nbsp;") )
});

这个方法使用正则表达式来查找并替换字符串中的最后一个空格为不间断字符。这意味着最后两个单词将被强制放在同一行上。如果行末有空间,这是一个很好的解决方案,因为这可能导致文字超出具有固定宽度的元素范围,或者如果没有固定宽度,会导致元素变得更大。


1
希望这不会破坏所述元素内的HTML。 - ShayneStatzell
这会去除HTML中的任何格式,例如强调、锚点等。 - Garconis

2

我想补充这个页面,因为它对我有很大帮助。

如果你有孤行问题,实际上应该是“孤儿”问题,因为孤行是单词落在下一页,而不是新行的单词。

处理邮编如“N12 5GG”将导致完整邮编出现在新行,但仍被视为孤行,因此可以使用以下解决方法(将类更改为“noWidow2”,以便您可以使用两个版本)。

123 Some_road,Some_town,N12 5GG

$('.noWidows2').each(function(i,d){ 
    var value="&nbsp;"
    $(d).html($(d).text().replace(/\s(?=[^\s]*$)/g, value).replace(/\s(?=[^\s]*$)/g, value)); 
}); 

这将导致最后3个空格在一个新行上,使邮政编码问题得以解决。
最终结果
123 Some_road,
Some_town, N12 5GG

0
我写了一个小的脚本,利用这个函数来查找行高。
这只是一种方法,可能会有一定的问题,由于时间紧张,没有进行彻底的测试。
目前,text_element必须是jQuery对象。
function avoidBastardWord( text_element )
{
    var string = text_element.text();
    var parent = text_element.parent();
    var parent_width =  parent.width();
    var parent_height = parent.height();

    // determine how many lines the text is split into
    var lines = parent_height / getLineHeight(text_element.parent()[0]);

    // if the text element width is less than the parent width,
    // there may be a widow
    if ( text_element.width() < parent_width )
    {
        // find the last word of the entire text
        var last_word =  text_element.text().split(' ').pop();

        // remove it from our text, creating a temporary string
        var temp_string = string.substring( 0, string.length - last_word.length - 1);

        // set the new one-word-less text string into our element
        text_element.text( temp_string );

        // check lines again with this new text with one word less
        var new_lines = parent.height() / getLineHeight(text_element.parent()[0]); 

        // if now there are less lines, it means that word was a widow
        if ( new_lines != lines )
        {
            // separate each word
            temp_string = string.split(' ');

            // put a space before the second word from the last
            // (the one before the widow word)
            temp_string[ temp_string.length - 2 ] = '<br>' + temp_string[ temp_string.length - 2 ] ;

            // recreate the string again
            temp_string = temp_string.join(' ');

            // our element html becomes the string
            text_element.html( temp_string );
        }
        else
        {
            // put back the original text into the element
            text_element.text( string );
        }

    }

}

不同的浏览器有不同的字体设置。尝试进行一些调整以查看差异。我在IE8和Opera上进行了测试,每次修改字符串,似乎都可以正常工作。
我希望能听到一些反馈并改进,因为我认为它可能会很有用。
只需玩一下就好啦! :)

0

$('span').each(function() {
  var w = this.textContent.split(" ");
  if (w.length > 1) {
    w[w.length - 2] += "&nbsp;" + w[w.length - 1];
    w.pop();
    this.innerHTML = (w.join(" "));
  }
});
#foo {
  width: 124px;
  border: 1px solid #ccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo">
  <span class="orphan">hello there I am a string really really long, I wonder how many lines I have</span> 
</div>


这将删除HTML中的任何格式,例如加粗、锚点等。 - Garconis

0

手动地,你可以用&nbsp;替换中间的空格。

我一直在寻找动态添加它的方法。我找到了一些,但自己还没有成功实现。


以上是程序相关的内容,请将以下文本从英语翻译成中文。仅返回翻译后的文本:应该与" & n b s p ;"(无空格,使用&非断行空格) - matt
将代码用两个 ` 符号包裹起来以允许正确格式化。 - Luca

0

这两个只适用于打印 http://www.w3.org/TR/CSS21/page.html#break-inside - c69
@c69 你说得对。有没有人知道是否有计划为非分页媒体添加此功能?在网上找不到任何信息。如果能为屏幕媒体实现更多的排版工具,像这样的(以及流动和环绕),那将是很棒的。 - Sam Dutton
http://www.w3.org/TR/css3-regions/#best-region-breaks - 这些东西在IE10 pp3中有一些可用,并且也将在新的WebKit中起作用。 - c69
@c69 更多关于WebKit实现的信息请参见此处:https://bugs.webkit.org/buglist.cgi?quicksearch=orphans。 - Sam Dutton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接