Где всё сложно с переносами строк. Вот все CSS- и HTML-хитрости для этого

Перевод статьи Where Lines Break is Complicated. Here’s all the Related CSS and HTML. с сайта css-tricks.com для CSS-live.ru, автор — Крис Койер

Скажем, есть действительно длинное слово в каком-то тексте, у контейнера которого недостаточно ширины для него. Типичная причина этого — длинный URL, просочившийся в текст. Что происходит? Зависит от CSS. Как этот CSS управляет раскладкой и как он этим текстом распоряжается.

Вот как может выглядеть ситуация с не поместившимся текстом:

Текст, вылезающий из бокса — визуальная проблема.

Первое решение — overflow: hidden;, как этакий «лобовой» прием, чтобы не дать тексту (и чему угодно) высовываться. Но от этого пострадает доступность текста. В некоторых десктопных браузерах для выделения текста можно три раза кликнуть на нем мышью, но не каждый может об этом знать и не всегда такое возможно.

Название свойства «overflow» — «переполнение» — здесь весьма к месту, ведь именно оно, переполнение, у нас и происходит. Ещё есть overflow: auto;, приводящее к горизонтальному скроллу. Иногда может и подойди, но наверняка вы тоже согласитесь, что обычно это решение неприемлемо.

Нам нужно, чтобы этот зараза длинный URL (или любой текст) разорвался, чтобы перенестись на следующую строку. Варианты есть! Для начала подготовим место, где мы будем со всем этим разбираться.

Экспериментальная площадка

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

Уверен, что этот список неполный и не идеальный. Это лишь некоторые из знакомых мне свойств.

See the Pen Figuring Out Line Wrapping by Максим (@psywalker) on CodePen.

Кувалда: word-break: break-all;

Позволяет словам разрываться везде. Свойство word-break «решает» проблему:

p {
word-break: break-all;
}

В переписке по электронной почте fantasai пояснила, что это работает, поскольку свойство word-break меняет определение того, что считать словом. Значение break-all по сути воспринимает любой текст как восточноазиатский, который может переноситься практически где угодно (кроме точек в конце предложений и закрывающих скобок). Значение keep-all, наоборот, воспринимает восточноазиатские иероглифы как буквы в слове, а не как целые слова.

Прицельное решение: overflow-wrap: break-word;

Свойство overflow-wrap кажется наиболее эффективным решением для данной проблемы.

p {
  word-wrap: break-word; /* old name */
  overflow-wrap: break-word;
}

На первый взгляд это может походить на демо с word-break: break-all; выше, но заметьте, как в URL оно не разрывает «pen» как «pe\n», а делает перенос в конце этого слова, рядом со слешем.

fantasai объясняет:

Если слово не может разорваться, переполняя контейнер, оно может разорваться где угодно во избежание переполнения.

Решение потяжелее, иногда: hyphens: auto;

Свойство hyphens может иногда решить проблему с URL-адресами и длинными словами, но это не точно. На длинном числе, например, он споткнется. Вдобавок, hyphens влияет на весь текст, позволяя себе вольности в разрывах ради того, чтобы сделать правый край текста более ровным.

p {
hyphens: auto;
}

fantasai сказала мне:

Если «слово» находится в конце строки, его можно переносить через дефис.

Думаю, это «слово» в кавычках дает подсказку, в чем тут проблема. Некоторые неприемлемо длинные строки — не «слова», поэтому это решение — не панацея.

Будущая кувалда: line-break: anywhere;

Есть свойство line-break. В основном, кажется оно для пунктуации, но ни в одном браузере оно у меня не заработало. fantasai сказала мне, что появится новое значение anywhere, которое:

«как word-break: break-all;» за исключением того, что она на самом деле разрывает всё, как примитивная программа на терминале.

Другие решения в HTML

Элемент <br> разобъёт строку где угодно, если только у него не будет display:none.

Элемент <wbr> — «возможный разрыв слова», что означает, что длинному слову, обычно вызывающему раздражающую проблему с переполнением можно сказать, чтобы оно разорвалось в конкретном месте. Полезно! Оно ведёт себя, как пробел нулевой ширины.

Другие решения на CSS

Символ ­&shy; делает то же самое, что и элемент <wbr> (На самом деле не совсем, поскольку, в отличие от <wbr>, ­ добавляет дефисы при переносе. — прим. перев.)

Можете вставить разрыв строки с помощью псевдоэлемента ::before { content: "\A"; }, если только элемент не строчный (в противном случае потребуется white-space: pre;)

P.S. Это тоже может быть интересно:

4

Комментарии

  1. websanya

    Привет от подкаста «Суровый веб»! Спасибо за классный перевод статьи! :D

  2. Дмитрий

    word-break: break-word; — не входит в стандарт, но работает (почти?) везде и решает проблему более «умно».

    https://developer.mozilla.org/en-US/docs/Web/CSS/word-break

    1. SelenIT

      SelenIT

      Спасибо за ценное дополнение! Правда, будущее у этого значения довольно туманно, потому что с недавних пор такое «более умное» поведение (перенос длинных слов только при необходимости и учет этого переноса при расчете минимальной ширины контента) — действие overflow-wrap: break-word по умолчанию (см. сообщение в ишью на гитхабе Рабочей группы CSS), и дублировать его в отдельном свойстве стало незачем. Так что есть вероятность, что его уберут даже там, где оно сейчас работает (в WebKit/Blink).

      1. Дмитрий

        Спасибо, буду иметь в виду. У нас «word-break: break-word» в продакшн…

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Ваш E-mail не будет опубликован

Получать новые комментарии по электронной почте. Вы можете подписаться без комментирования.