18

在 HTML/CSS 中使用排版时的一个常见问题是我们在瑞典语中称之为“horunge”(英语中的“寡妇”)。

这是什么:

假设你有一个宽度为 200 像素的盒子,上面写着“我非常喜欢排版”。现在文本中断并变为:


我非常喜欢排版

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


我非常喜欢排版

看起来好多了。

我可以用 CSS 规则或 javascript 解决这个问题吗?规则应该是永远不要让一个词在一行上空着。

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

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

4

6 回答 6

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

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

于 2014-02-11T21:23:48.117 回答
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
于 2014-12-07T16:09:42.520 回答
0

还有 CSS widows 和 orphans 属性:参见about.com 文章

不知道浏览器支持...

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

于 2011-09-16T13:07:07.493 回答
0

手动,您可以用&nbsp;

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

于 2012-05-23T19:02:10.527 回答
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>

于 2015-02-08T22:44:00.060 回答
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 上对其进行了测试,每次都修改字符串,它似乎工作正常。

我想听听一些反馈和改进,因为我认为无论如何它可能会派上用场。

只是玩它!:)

于 2011-09-16T13:56:14.037 回答