Передряги при переносах
Перевод статьи Word Wrapping Woes с сайта jonibologna.com, опубликовано на css-live.ru с разрешения автора — Джони Трайтел.
Почему-то мне как-то особенно «везет» на странные, неожиданные фокусы с переносом текста.
Я написала электронную книгу, и решать, как переносить строки кода в блоках — это был кошмар! Порой блок текста из-за переноса выбивался по высоте из контейнера. А одни слишком длинные ссылки чего стоили!
Вставлять дефис в месте переноса или нет? Здесь переносим, там не переносим. Тут вставляем дефис, там нет. Одно свойство ни в какую не хочет работать без другого. И почему этот горизонтальный скроллинг упорно не хочет пропадать?
/me бьется об стол
Бывает множество ситуаций, с которыми здесь можно столкнуться, требующие слегка разного подхода к оформлению стилями, так что в этой статье мы рассмотрим типичные свойства, используемые для решения таких проблем, а также пару сценариев из реальной жизни, в которых, по-моему, особенно ярко проявляются проблемы с переносом/переполнением текста.
Свойства
В конце концов при решении проблем с переносом текста остается некий типичный «список подозреваемых». Одни довольно очевидные и логичные, а другие — нет. Одни делают свое дело сами по себе, а другие не очень.
Итак, давайте взглянем.
word-wrap
/overflow-wrap
Свойство word-wrap
принимает в виде значений два ключевых слова: normal
(по умолчанию) и break-word
. Это в дополнение к трём глобальным значениям inherit
, initial
и unset
.
По умолчанию слишком длинное слово не разрывается. Браузер не влияет на такое слово, что выглядит замечательно, пока мы не сталкиваемся с мобильными. Хотя размер контейнера может подстраиваться под слово, оно в итоге вывалится из его границ и приведёт к страшной горизонтальной прокрутке на всей странице.
В первом примере этого демо можно наглядно увидеть поведение по умолчанию:
Второй пример на этом демо включает объявление overflow-wrap: break-word;
, приказывающее браузеру разбить слово перед возможным переполнением своего контейнера.
Важно заметить: в текущем черновике спецификации CSS3 Text word-wrap
было заменено на overflow-wrap
, но значения остались прежними. И взгляните на текущую поддержку браузерами этого изменения.
word-break
Насколько я поняла, свойство word-break
нужно только для того, чтобы как-то по-особому форматировать текст на китайском, японском и корейском языках.
Я применяла word-break
для разбивки длинных слов, но правильным свойством (если вы не работаете с дальневосточным текстом) будет более общее вышеупомянутое overflow-wrap
.
hyphens
Свойство hyphens рассказывает браузеру, как расставлять дефис при переносе, и допускает следующие значения: none
, manual
и auto
, которые в настоящий момент плохо поддерживаются браузерами, поэтому вам, видимо, придётся запустить FireFox.
Значение none
гарантирует, что в слова никогда не будет подставляться символ переноса.
При значении manual
дефис выставляется в месте переноса только при наличии указывающего на это символа. Указать это можно, вставив символ либо жёсткого, либо мягкого переноса в нужное место в разметке.
Жёсткий перенос (-
) прикажет слову разорваться в определённом месте при необходимости, но всё в любом случае будет отображаться на экране.
Мягкий перенос (­
) делает тоже самое, но фактически не отображает дефис на экране, что, как правило, предпочтительнее.
При значении auto
слова можно разбивать либо в явно указанных местах, либо автоматически, в соответствии с правилами расстановки переносов для конкретного языка, указанными в специальных файлах (если они предусмотрены в браузере). Расстановка переносов специфична для языка, и для документа нужно определять атрибут lang
.
white-space
У каждого из нас есть любимые CSS-свойства, на которые можно положиться, словно на запасной выход с надписью «При аварии разбить стекло молотком», чтобы выбраться из запутанной ситуации; см. также overflow: hidden
и display: none
. Для меня таким свойством является white-space
.
Это свойство указывает правила обработки пробельных символов (пробелы, табы, переводы строки) в элементе. Что порой может вдруг оказаться невероятно полезным, например, при отладке, или чтобы лучше контролировать содержимое ячеек таблицы.
У этого свойства бывает пять значений: normal
(по умолчанию), nowrap
, pre
, pre-wrap
и pre-line
.
Взглянуть на эти свойства в действии можно в примере ниже: учитывайте добавочные пробельные символы в разметке.
По умолчанию пробельные символы схлопываются в один пробел и строки разбиваются, чтобы уместиться в контейнер; как видно в первом демо-примере, в тексте есть лишние пробелы, но они не отображаются.
nowrap
(пример 2) также игнорирует дополнительные пробелы, но зато не разбивает строку текста на границах контейнера.
pre
учитывает все пробельные символы в разметке, и не разбивает строки (как видно выше в примере 3).
pre-wrap
(пример 4) учитывает добавочные пробелы, но заставляет строку разбиваться.
pre-line
(последний пятый пример) схлопывает пробельные символы (кроме перевода строки) и принуждает «цепочку» текста умещаться в контейнер.
На CSS—Tricks есть удобная табличка, которая поможет всё это резюмировать.
Строки кода в блоке
Строки кода в теге pre
по умолчанию не переносятся. Это может вызвать неприятности в статьях блога и технических электронных книгах на мобильном, например.
По моему опыту, обычно решение зависит от того, на каком языке этот код, и вообще от задачи, но эти проблемы можно обойти при помощи принудительных переносов (без дефиса!) или горизонтального скроллинга. Методом проб и ошибок можно понять, какое точное сочетание свойств нужно тому или иному браузеру. Убедитесь, что значение white-space
случайно не переопределилось на одно из тех, при которых пробелы схлопываются, потому что это может оказаться значимым для синтаксиса кода.
Также я нарвалась на проблемы с адаптивностью при оформлении кода для github (gist), который особенно коварен из-за того, что это table. В таких случаях я понимаю, что мне придётся применить особенное оформление для переопределения контейнера таблицы.
Многоточие со смыслом
Как по мне, CSS-объявление text-overflow: ellipsis;
— какая-то шляпа. Оно очень капризное и работает только при сочетании с группой других свойств. К тому же оно применяется только к единственной строке текста, что делает его не особо полезным.
С jQuery-плагином dotdotdot можно расставить многоточие в нескольких строках текста и даже добавить в конце ссылку для продолжения чтения.
Вот быстрый примерчик:
Перенос только в строго определенном месте
Порой необходимо, чтобы слова разрывались только в строго определённых местах, где в этом есть смысл, что добавляет ещё один уровень сложности; как же сообщить эти точки разрыва браузеру?
Сделать это можно с помощью мягкого или жёсткого переносов, которые, как обсуждалось ранее, размещаются в определённом месте разметки.
Не сомневайтесь, что если мягкий дефис поддерживается в браузере, то при необходимости строка будет разрываться в тех местах, где установлен ­
.
Эй, чем ты занимался на вы­ходных? Я рисовал по керамике, это выглядело натурально.
Слишком длинные ссылки
Я постоянно сталкивалась с проблемой слишком длинных ссылок, снова, при подготовке электронной книги (да, при публикации электронной книги это буквально худшее) с множеством целых ссылок в сносках.
По умолчанию такие ссылки не разрываются и вызывают всяческие неприятности на небольших экранах. При необходимости URL’ы должны разрываться без дефиса, поскольку ссылка в таком случае будет нерабочей. Также здесь нужно быть осторожным, поскольку, если вы такое допустите, то разорвутся не только URL’ы, но и все слова.
overflow-wrap: break-word;
на ссылке гарантирует, что URL разорвётся в границах контейнера и переполнения не будет, хотя добиться кроссбраузерности тут не так просто, как можно было бы подумать.
Заключение (Ха!)
Бывает непросто выстроить точно необходимое сочетание этих свойств, чтобы справиться с внезапно возникшей исключительной ситуацией, но более глубокое знание возможных вариантов и умение быстро распознавать типичные примеры определенно помогут обойтись без лишнего гадания.
P.S. Это тоже может быть интересно:
Немного не понял, про «Слишком длинные ссылки», что я такого должен сделать в этом примере для Chrome, чтобы сработало это «При необходимости URL’ы должны разрываться без дефиса, поскольку ссылка в таком случае будет нерабочей».
Скорее всего не понял, что автор имеет ввиду.
Джони говорит про сам URL ссылки, когда его нужно впихнуть в узкую колонку электронной книги, но сохранить возможность скопировать и вставить в адресную строку браузера. Логично, что если при этой процедуре в URL вкрадутся лишние дефисы, работать скопированная ссылка не будет.
А, теперь понял. Спасибо!
Автор — Джони Трайтел.
«Я написала электронную книгу»
это такая опечатка или Джони еще может быть женским именем?
Нет, никакой опечатки! Если вы пройдёте в Твиттер Джони, вы сами это увидите. Кстати, ничего особенного не вижу в женском имени «Джони» (Joni). История знает не мало женщин (даже известных) с таким именем, как пример.
Слиплось: «Убедитесь, что значение white-spaceслучайно»
Спасибо, Юля, поправил!
Так что в итоге?
:root, html
{
overflow-wrap: break-word;
word-wrap: break-word;
-webkit-hyphens: auto;
-moz-hyphens: auto;
-ms-hyphens: auto;
hyphens: auto;
}
А в html добавляем
, а английские слова и абзацы оборачиваем отдельно в
Тогда для Мозилы работает человеческая поддержка hyphens, а для остальных работает значение break-word, которое тупо переносит слишком длинные слова в узком контейнере на другую строчку, при этом переносит в любом месте, когда видит что слово в одну строчку не умещается.
Насколько я понимаю, свойство
word-break: break-all
делает hyphens не действующим. При этом, я, к сожалению, так и не понял, чем свойство word-break отличается от word-wrap по смыслу.То что не отобразилось, поправлю:
А в html добавляем
lang="ru"
, а английские слова и абзацы оборачиваем отдельно вlang="en"
.К сожалению, hyphens не является кросс-браузерным способом расстановки переносов и тем более не для всех языков и уже тем паче для присутсвия нескольких языков на странице. К тому же могут встречаться слова, которых нет в словаре, но хотелось бы перенести именно как Вам нужно.
Единственный способ гарантировать кросс-браузерную расстановку переносов это вставить мнемокоды мягких переносов (­) непосредственно в html. Самый простой способ (чтобы не вспоминать правила переноса и много работать руками) — это воспользоваться готовым сервисом автоматической расстановки мягких переносов. Вставляете свой текст и получаете на выходе готовый html с мягкими переносами, который можете поместить у себя на сайте.
При этом можно указать язык и задать минимальную длину слова при которой необходимо его разбивать (например разбивать только особо длинные слова и т.п.)