Подтвердить что ты не робот

JavaScript, чтобы избежать вдов

Общей проблемой при работе с типографикой в ​​HTML/CSS является то, что мы называем "horunge" на шведском языке ( "widow" на английском языке).

Что это такое:

Скажем, у вас есть ящик шириной 200 пикселей и с текстом "Я очень люблю типографию". Теперь текст разбивается и становится:

Я люблю типографию очень
много

В качестве дизайнера я не хочу слова "ублюдок" (одно слово/строка). Если бы это был документ /PDF и т.д., Я бы сломал слово раньше и выглядел так:

Я люблю типографию
очень

который выглядит намного лучше.

Можно ли разрешить это с помощью правила CSS или с помощью javascript? Правило должно состоять в том, чтобы никогда не оставлять пустое слово в строке.

Я знаю, что это можно решить, добавив <br />, но это не решение, которое работает с динамической шириной, содержимым корма, разными переводами, проблемами с отображением шрифтов браузера и т.д.

Обновление (решение) Я решил проблему с этим плагином jquery: http://matthewlein.com/widowfix/

4b9b3361

Ответ 1

Простое решение jQuery/regrex может выглядеть следующим образом, если вы добавите класс "noWidows" в тег любого элемента, который содержит текст, который вас беспокоит.

Например:

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

И затем используйте этот script:

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

Это использует регулярное выражение для поиска и замены последнего пробела в строке символом неразрывности. Это означает, что последние два слова будут принудительно перенесены в одну строку. Это хорошее решение, если у вас есть пространство вокруг конца строки, потому что это может привести к тому, что текст будет работать за пределами элемента с фиксированной шириной или, если он не исправлен, приведет к тому, что элемент станет больше.

Ответ 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

Ответ 4

Я сделал немного script здесь, с помощью этой функции, чтобы найти высоту строки.

Это просто подход, он может работать или не работать, не успел протестировать.

На данный момент 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, каждый раз изменяя строку и, похоже, работал нормально.

Я хотел бы услышать некоторые отзывы и улучшить, потому что я думаю, что это может пригодиться в любом случае.

Просто поиграй!:)

Ответ 5

Вручную, вы можете заменить промежуток между ними с помощью &nbsp;

Я искал способы динамически добавлять его. Я нашел несколько, но не смог заставить его работать сам.

Ответ 6

$('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>