JavaScript避免寡妇

时间:2011-09-16 12:29:08

标签: javascript css typography

在HTML / CSS中使用排版时常见的问题是瑞典语中的“horunge”(英语中为“widow”)。

它是什么:

假设您有一个宽度为200像素的盒子,并且文字“我非常喜欢打字”。现在文本中断并变为:

  

我非常喜欢排版   多

作为一名设计师,我不想要一个单词混蛋(单字/行)。如果这是一个文档/ PDF等我会在之前打破这个词,看起来像这样:

  

我喜欢排版   非常

看起来好多了。

我可以使用CSS规则或使用javascript解决此问题吗?规则应该是永远不要让一个单词在一行中显示为空。

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

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

6 个答案:

答案 0 :(得分:7)

如果您将“noWidows”类添加到包含您担心的文本的任何元素的标记中,那么简单的jQuery / regrex解决方案可能如下所示。

如:

<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 :(得分:2)

只是想添加到此页面,因为它帮助了我很多。

如果你有(寡妇)实际应该是孤儿,因为寡妇是下一页上的单个单词而不是新行上的单个单词。

使用&#34; N12 5GG&#34;等邮政编码将导致完整的邮政编码一起在新的一行,但仍然被归类为孤儿,所以解决这个问题。 (将班级更改为&#34; noWidow2&#34;因此您可以使用这两个版本。

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

答案 2 :(得分:0)

还有CSS寡妇和孤儿属性:请参阅about.com article

不确定浏览器支持...

编辑:有关WebKit实施的更多信息,请访问:https://bugs.webkit.org/buglist.cgi?quicksearch=orphans

答案 3 :(得分:0)

我在script here的帮助下做了一点this function来找到行高。

这只是一种方法,它可能会或可能不会起作用,没有时间进行彻底的测试。

截至目前,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上测试过它,每次都修改字符串,它似乎工作正常。

我希望听到一些反馈和改进,因为我认为它可能会派上用场。

玩吧! :)

答案 4 :(得分:0)

手动,您可以用&nbsp;

替换其间的空格

我一直在寻找动态添加它的方法。我发现了一些,但一直无法让它自己工作。

答案 5 :(得分:0)

&#13;
&#13;
$('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(" "));
  }
});
&#13;
#foo {
  width: 124px;
  border: 1px solid #ccc;
}
&#13;
<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>
&#13;
&#13;
&#13;