Эта статья является вольным переводом. Оригинал находится по адресу http://www.cs.tut.fi/~jkorpela/html/nobr.html#prevent.
Internet Explorer переносит строки странным образом. Он считает любой дефис потенциальным местом для переноса, например строка «-a» может быть разделена на две: «-» и «a». Другие браузеры тоже не отличаются хорошим поведением, особенно Opera.
В этой статье будут рассмотрены инструменты по предотвращению нежелательного поведения браузеров в местах переноса строк.
Содержание:
Нежелательные переносы в IE
Было замечено, что в некоторых из приведенных случаев может возникнуть разрыв строки:
- после дефиса (-);
- после знака процента (%);
- после знака градуса (°);
- после следующих символов •, (, ), [, ], {, };
- до открывающей кавычки («);
- после закрывающей кавычки (»);
- после восклицательного и вопросительного знака.
Таким образом, фраза «Latin-1″ может быть разделена на «Latin-» и «1″ или даже «Latin», «-» и «1″. Это очень плохо, например, из-за того, что в финском языке распространены слова с префиксом «-», обозначающим, что первая часть слова опущена. Во французском языке в закавыченной фразе (« comme ici ») важно использовать неразрывный пробел (вместо обычно) между первым словом и открывающей кавычкой и последним словом и закрывающей кавычкой.
Перенос строки после знака процента опасен в ситуациях, когда этот символ используется по особому назначению (в языках программирования или в URL-ах). К счастью, IE не переносит строки вида «%:n». Более того, IE может вставить перенос строки между косой и обратной косой чертой (/\). Но и это еще не все! В полной мере оценить странное поведение браузера можно в разных его версиях и в разных контекстах.
Избегание переносов строк
Довольно часто разрыв слова со знаком переноса приемлем и даже желателен. Страница в таких случаях выглядит лучше, особенно, если в ней встречаются длинные или составные слова, соединенные дефисом. Но проблема в том, что IE любой дефис расценивает как потенциальную точку переноса и разрывает трех- или даже двухбуквенные слова…
Есть несколько способов избежать нежелательного переноса слов. Так как они работают по-разному, то их даже можно комбинировать. Все они представлены в следующей таблице. В первых четырех строках примеры, иллюстрирующие как избежать переноса между цифрой и единицей измерения в строке «100 м», в остальных в строке «A-1″
| Где применять |
Способ |
Пример |
Примечание |
| Html разметка |
Тег nobr |
<nobr>100 м</nobr> |
Нестандартный тег, но поддержка широкая |
| Html разметка |
Атрибут nowrap |
<td nowrap>100 м</td> |
Применяется только для ячеек таблицы, что сужает область применения |
| Css |
White-space: nowrap |
<span style=»white-space: nowrap»>100 м</span> |
Обычно срабатывает на самом глубоковложенном элементе |
| Символ в тексте |
Неразрывный пробел |
100 м |
Хорошо предотвращает разрыв между двумя словами, не подходит для проблем, обсуждаемых здесь |
| Символ в тексте |
Неразрывный дефис |
A‑1 |
Применяется для предупреждения переноса после дефиса. Ограниченная область применения из-за проблем со шрифтами |
| Символ в тексте |
Word joiner (wj) |
A-⁠1 |
Широкая область применения в принципе, но очень небольшая полезность из-за ограниченной поддержки в браузерах |
| Символ в тексте |
Неразрывный пробел с нулевой шириной |
A-1 |
небольшая полезность из-за несовместимости с IE |
Все браузеры, в общем, поддерживают эти методы причудливо, со странностями, однако, nobr сработает в большинстве случаев. Разберем все представленные способы по порядку.
Nobr
Как видим, единственный верный способ – использовать нестандартный тег nobr. С момента его появления не было полного описания принципов работы этого тега. Поэтому браузеры воспринимают его так: <nobr> – отменить все переносы, начиная с этого момента, </nobr> – дальше переносы разрешены. Конечно, нужно учитывать, что лучше всего этот тег применять на небольших по длине фразах.
Нет, не решит наши проблемы
Как сказано в заголовке этого параграфа неразрывный пробел не может решить наши проблемы. Ведь вставляя его, мы вставляем в фразу символ, по отображению идентичный обычному пробелу, а это бывает неприемлемым в некоторых случаях.
Для ячеек таблиц сработает nowrap
В особых случаях, когда информация представлена в таблице, и можно отменить переносы с трок во всей ячейке, нас выручит атрибут nowrap. Конечно, он относится к нерекомендуемым спецификацией Html 4.01, но по-прежнему валиден.
Замечу, что браузеры проигнорируют nowrap, если у ячейки выставлена фиксированная ширина, а контент не сможет уместиться в одну строку без переноса.
Может быть white-spase: nowrap?
Мы можем указать в css правило, говорящее о том, что все переносы строк (кроме переносов, созданных тегом br) запрещаются. Все современные браузеры и IE6 поддерживают это правило.
В IE есть баг: если это правило установить для ячейки таблицы, то оно может не сработать. Лечится оборачиванием содержимого ячейки дополнительным тегом (span или div) и переносом на него правила из ячейки.
Примечание. Согласно спецификации CSS 2.0 свойство white-space применялось только для блочных элементов, позволяя избегать нежелательных переносов внутри параграфов. Однако, это ограничение было снято в CSS 2.1
Unicode: word joiner (WJ)
В стандарте Unicode говорится, что есть специальный символ U+2060 (в html ⁠), который используется для предотвращения переносов строк.Значит, чтобы строка «2003-03-24» была представлена в одну линию всегда, нужно использовать запись 2003-⁠03-⁠24, – решим мы. Однако, некоторые браузеры не распознают wj как специальный символ и просто пытаются его отобразить, но в большинстве шрифтов нет глифов для этого символа. В результате мой IE6 на месте wj символа показывает квадрат со знаком вопроса.

Даже при использовании такого редкого шрифта, как Code2000, содержащего глиф для wj символа, этот способ непригоден, потому что IE не знает специального значения нашего символа и продолжает его отображать кракозяброй.
Можно еще попробовать неразрывный пробел нулевой ширины. В тексте он имеет такое же значение как и wj символ, да и в Unicode он гораздо дольше… К счастью IE понимает, что для этого символа нет глифа и не отображает его в виде кракозябры, но на сегодняшний день ни одна версия IE не знает, что этот символ запрещает разрыв.
Проблемы с валидацией nobr
Так как тега nobr нет ни в одной спецификации html, он вызывает ошибки при попытке прохождения валидации. Но мы можем (если нам очень важна зеленая галочка валидатора) , используя nobr, пройти валидацию! Достаточно использовать модифицированный DTD (Creating your own DTD for HTML validation)
Однако, заметьте, что в таком случае w3c валидатор не подойдет для нашего документа в силу внутренних ограничений. Вместо него можно использовать WDG валидатор.
Строго говоря, при модификации DTD мы не можем заявлять о соответствии своих страниц спецификации HTML 4.01 или какой-то другой…
Особые случаи с дефисом
Возвращаясь к дефису, теоретически, мы можем его заменить различными Unicode аналогами, в надежде обмануть IE
. Например, переноса в фразе «a-b» можно избежать написав «a‑b» однако, хотя такая конструкция хорошо поддерживается современными браузерами, поддержка все-таки не универсальна. Основная проблема в том, что в большинстве шрифтов нет такого неразрывного дефиса, и браузер отобразит какой-нибудь квадрат или вопрос на его месте.
Не редки случаи, когда дефисы заменяют длинные или короткие тире. В таких случаях нестандартное поведение IE (помним, что дефис для IE – место, куда можно вставить разрыв строки) крайне нежелательно. Например, 5 - 6. В данном случае дефис, окруженный двумя неразрывными пробелами, эмулирует длинное тире. Мы уверены, что наша фраза всегда останется на одной строке. НО! IE ведет себя непредсказуемо. Он может разделить строку на две в том месте, где встречается дефис, хотя даже после него стоит неразрывный пробел. Единственный действенный способ в данном случае обернуть фразу тегом nobr.

Особые случаи: номера телефонов
Телефонные номера вызывают проблемы достаточно часто:
- это может случиться в таблице. Расположенные в одном столбце номера, браузер может расположить в две строки. Неприятно, но этого можно избежать, используя атрибут nowrap, как описано выше в таблице;
- проблемы возникают из-за появления в номере символов, к которым IE не равнодушен. Например, в номере (495) 555 555 IE может вставить перенос строки после закрывающей скобки. К счастью в данном случае, проблемы с IE можно избежать, поставив после скобки вместо обычного пробела неразрывный.
Как указать возможное место переноса. Почему это проблема?
В большинстве своем, браузеры не переносят слова. IE – исключение, но только в некоторых случаях. Раньше нам приходилось просто жить с этим, пока браузеры не стали лучше и не стали понимать язык страницы и применять специфичные для него правила переноса слов. Теоретически, это могло решить проблему, но решение грубовато.
К счастью, сегодня браузеры поддерживают мягкий перенос (­). Вам нужно просто указать с помощью специального символа (­) место возможного переноса, а браузер при необходимости сам вставит туда перенос.
Бывают случаи, когда браузер не переносит строку даже в том месте, где стоит обычный пробел. IE грешит таким поведением, когда фраза содержит двоеточие. Например, мы в своей работе описываем «псевдоэлемент :before». IE будет считать эту строку неделимой до тех пор, пока не появится символ разрыва строки перед двоеточием. Аналогичные проблемы у этого браузера и с точкой в начале строки. Более того, IE не разорвет строку в месте, где открывающая скобка следует за закрывающей кавычкой (“example” (intentionally).
Нормальный перенос слова против разрыва строки
У нас есть два пути:
- настоящий перенос слова, когда в месте разрыва слова ставится дефис. И
- разрыв строки на две или более частей без указания дефиса в местах разрыва (C:\Program Files\Netscape\Communicator\
Program\NetHelp\Netscape).
Переносим все: word-wrap
В соответствии с документацией Microsoft, начиная с версии 5.5, IE поддерживает свойства word-wrap, полезное, когда контент выходит за границы содержащего его контейнера. Свойство оказалось настолько необходимым, что его включили в черновик CSS3. Оно поддерживается последними версиями браузеров, отличных от IE.
Конечно, у нас еще есть принудительный перенос br, но он пригоден не во всех случаях в силу малой своей гибкости.
Удобный путь: wbr
Тегом wbr отмечается место, где, в случае необходимости, браузер может поставить перенос строки. Это одиночный пустой тег без атрибутов.
В настоящее время этот тег поддерживают все современные браузеры, IE6, кроме IE8 в стандартном режиме. IE8 просто не знает этого тега. Для обхода этой проблемы можно, например, перевести браузер в режим IE7.
Заметим, что не следует использовать wbr для разметки мест возможных переносов внутри слов. Так как в таком случае браузер перенесет слово, но не поставит знак переноса. Используйте wbr в местах предполагаемого переноса слов после дефиса (мышка-норушка).
Так как wbr не включен ни в одну спецификацию, при валидации страниц возникнут проблемы, аналогичные описанным выше.
Unicode: ZWSP
В случаях, когда при переносе слова появление символа переноса нежелательно, например, при разрыве длинной строки URL, есть способ сделать это с помощью специального Unicode символа:
ZWSP (zero width space character, U+200B, в html ​).
Этот символ не имеет ширины и указывает на место возможного разрыва там, где обычный символ пробела недопустим. Однако, поддержка этого символа браузерами достаточно ограничена. Последствия применения zwsp аналогичны описанным выше. Единственные широко распространенные шрифты, в которых есть глифы для этого символа – Arial Unicode MS и Lucida Sans Unicode.
Правила Unicode line breaking
Вдобавок ко всему, в нашу непростую ситуацию вмешиваются Unicode стандарты…
Например, последовательность «.foo» (.foo .foo .foo …) в IE отображается в одну строку, как длина она бы не была. Такую строку сложно встретить, но все же нельзя забывать и о такой возможности. Самое быстрое лекарство – вставить wbr перед каждым словом, начинающимся с точки. Теоретически верным и соответствующим стандартам решением будет использование zwsp, но мы уже говорили о его ограниченной поддержке…
Если немного углубиться в теорию, то согласно Unicode-стандартам точка перед словом (принадлежит классу IS: infix separator (numeric)) запрещает перенос строки перед собой, а также после себя в случае, когда за точкой следует цифра. Таким образом, в фразе «foo .foo» пробел разрешает перенос строки после себя, а точка запрещает перенос строки перед собой. В данном противостоянии побеждает правило для точки (LB 8: Don’t break before a character in class IS even after spaces). Аналогично, для случая с открывающей скобкой, следующей за закрывающей кавычкой.
Html спецификации ничего не говорят по поводу большинства правил Unicode line breaking. Они просто ссылаются на эти правила, что можно расценить как слепое им подчинение. К несчастью, именно это браузеры и начали делать…