JavaScript, чтобы избежать вдов
Общей проблемой при работе с типографикой в HTML/CSS является то, что мы называем "horunge" на шведском языке ( "widow" на английском языке).
Что это такое:
Скажем, у вас есть ящик шириной 200 пикселей и с текстом "Я очень люблю типографию". Теперь текст разбивается и становится:
Я люблю типографию очень
много
В качестве дизайнера я не хочу слова "ублюдок" (одно слово/строка). Если бы это был документ /PDF и т.д., Я бы сломал слово раньше и выглядел так:
Я люблю типографию
очень
который выглядит намного лучше.
Можно ли разрешить это с помощью правила CSS или с помощью javascript? Правило должно состоять в том, чтобы никогда не оставлять пустое слово в строке.
Я знаю, что это можно решить, добавив <br />
, но это не решение, которое работает с динамической шириной, содержимым корма, разными переводами, проблемами с отображением шрифтов браузера и т.д.
Обновление (решение)
Я решил проблему с этим плагином jquery: http://matthewlein.com/widowfix/
Ответы
Ответ 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, " ") )
});
Это использует регулярное выражение для поиска и замены последнего пробела в строке символом неразрывности. Это означает, что последние два слова будут принудительно перенесены в одну строку. Это хорошее решение, если у вас есть пространство вокруг конца строки, потому что это может привести к тому, что текст будет работать за пределами элемента с фиксированной шириной или, если он не исправлен, приведет к тому, что элемент станет больше.
Ответ 2
Просто хотел добавить к этой странице, так как это очень помогло мне.
Если у вас есть (вдова) на самом деле должны быть сиротами, так как вдова - это одиночные слова, которые приземляются на следующей странице, а не отдельные слова в новой строке.
Работа с почтовыми кодами, такими как "N12 5GG", приведет к тому, что полный почтовый индекс будет находиться на новой линии вместе, но по-прежнему будет классифицироваться как сирота, поэтому это будет работать. (изменил класс на "noWidow2", чтобы вы могли использовать обе версии.
123 Some_road, Some_town, N12 5GG
$('.noWidows2').each(function(i,d){
var value=" "
$(d).html($(d).text().replace(/\s(?=[^\s]*$)/g, value).replace(/\s(?=[^\s]*$)/g, value));
});
Это приведет к тому, что последние 3 белых пробега будут на новой строке вместе, чтобы проблема с почтовым индексом работала.
Конечный результат
123 Some_road,
Some_town, N12 5GG
Ответ 3
Есть также вложения CSS и сирот: см. статью about.com.
Не уверен в поддержке браузера...
EDIT: больше информации о реализации WebKit здесь: https://bugs.webkit.org/buglist.cgi?quicksearch=orphans.
Ответ 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
Вручную, вы можете заменить промежуток между ними с помощью
Я искал способы динамически добавлять его. Я нашел несколько, но не смог заставить его работать сам.
Ответ 6
$('span').each(function() {
var w = this.textContent.split(" ");
if (w.length > 1) {
w[w.length - 2] += " " + 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>