Как стать автором
Обновить

Улучшаем тексты в вебе при помощи text-wrap: pretty

Уровень сложностиПростой
Время на прочтение12 мин
Количество просмотров1.9K
Автор оригинала: Jen Simmons

В новом Safari Technology Preview реализовано значение text-wrap: pretty, обеспечивающее беспрецедентный уровень чёткости типографики в вебе. Давайте рассмотрим возможности WebKit-версии pretty, а затем сравним её с balance и другими значениями text-wrap, чтобы лучше понять, когда какие следует выбирать.

Идеи о том, что «хорошо» для типографики произрастают из эпохи, когда набор производился вручную при помощи металла, дерева и чернил. Наборщики тщательно выбирали, где должно находится слово: в конце строки, в начале другой или его нужно разбить дефисом. Их усилия повышали понятность текстов, снижали напряжение глаз и просто увеличивали удовольствие от чтения. Хотя восприятие красоты может быть субъективным, в мире существуют и глубоко укоренившиеся типографские традиции для разных языков и написаний. Эти традиции через века несут человеческую культуру от поколения к поколению.

В цифровой типографике все слова располагает компьютер, а не человек. Веб-дизайнеры или разработчики часто создают шаблон, заполняемый различными версиями контента. Типографика в вебе не настраивается вручную, особенно в случае гибкой структуры текста, меняющейся в зависимости от формы и размеров экрана. Что же мы можем сделать, чтобы приблизиться к качеству традиционной типографики, сохранив при этом возможность механизации, привносимую современными компьютерами?

Одним из решений может стать text-wrap:pretty. Оно предназначено для обеспечения нового уровня качества типографики в вебе благодаря использованию учитывающих абзацы алгоритмов.

Повышение качества типографики

Традиции типографики формулируют множество правил:

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

  2. Избегайте «бахромы». Общая длина строк должна быть приблизительно одинаковой, чтобы избежать рваного края по концам строк. При ручном наборе типографы немного сдвигают слова, чтобы минимизировать визуальные различия между соседними строками. Хороший край повышает читаемость текста и делает весь блок текста более приятным для глаза.

  3. Избегайте плохой разбивки дефисами. В языках с возможностью разбивки дефисами она создаёт хороший край абзаца. Но в то же время она разбивает слово на части и помещает их на максимальном горизонтальном расстоянии друг от друга. Это повышает когнитивную нагрузку при чтении. Лучше минимизировать использование дефисов и избегать переносов в двух строках подряд.

  4. Избегайте коридоров. Иногда можно заметить, что пробелы между словами произвольным образом выстраиваются в одну линию. Такие коридоры могут отвлекать от чтения.

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

A screenshot of paragraph text that demonstrates a short last line, bad rag, bad hyphenation, and a typographic river.

Дизайнеры и шрифтовики часто используют разбивку дефисами и/или выравнивание для уменьшения рваного края, но в вебе ни то, ни другое не даёт удовлетворительного результата. До недавнего времени мы почти ничего не могли поделать с короткими строками, рваными краями и коридорами в вебе. Нам просто приходилось с ними мириться.

Структура строк в вебе с 1991 года

В течение более чем тридцати лет в вебе существовала лишь одна методика определения точки переноса текста.

Браузер начинает с первой строки текста и размещает каждое слово или слог один за другим, пока у него не кончится место. Как только не останется места для размещения ещё одного слова/слога, он выполняет перенос на следующую строку (если перенос разрешён). Затем он начинает следующую строку, умещая в неё весь возможный контент, у него заканчивается место, он выполняет перенос и так далее.

Он всегда учитывает только одну строку текста и выполняет перенос, когда сочтёт это необходимым, после того, как уместит максимальный объём контента в предыдущую строку. Если включена разбивка дефисами, то он будет переносить с дефисом последнее слово в строке, при этом стремясь оставить на предыдущей строке максимальную часть слова. Ничто остальное не берётся в расчёт, поэтому текст в вебе имеет рваный край, содержит коридоры, короткие последние строки и нелогичную разбивку дефисами.

Но с этими проблемами компьютер вполне может справляться. Уже десятки лет ПО наподобие Adobe InDesign и LaTeX умело одновременно анализировать множественные строки и решать, где будет заканчиваться одна и начинаться другая. Многострочного алгоритма не было только в вебе. До недавнего момента.

Мы с радостью впервые представляем эту возможность для веба в Safari Technology Preview 216.

text-wrap: pretty

Теперь у веба есть возможность анализировать весь блок текста при выборе мест переносов. Можно попросить браузеры делать это при помощи text-wrap: pretty. WebKit — не первый браузерный движок, который реализует это значение, но первый, использующий его для анализа и выравнивания целого абзаца. И это первый браузер, который применяет его для уменьшения рваности края. Мы решили применить в своей реализации более целостный подход, потому что хотели, чтобы наши пользователи могли задействовать это значение CSS для повышения удобства чтения текста. И просто для того, чтобы создать нечто красивое.

Safari Technology Preview 216 предотвращает возникновение коротких строк, улучшает ситуацию с рваным краем и снижает необходимость в разбивке дефисами во всём тексте, вне зависимости от его длины. Пока мы не вносим изменения для предотвращения коридоров, но нам бы хотелось заняться этим в будущем.

Хотя поддержка pretty появилась в Chrome 117, Edge 177 и Opera 103 осенью 2023 года, а в Samsung Internet 24 — в 2024 году, его версия для Chromium более ограничена в своей функциональности. Согласно статье разработчиков Chrome, движок Chromium вносит корректировки только в последних четырёх строках абзаца. Он делает упор на предотвращение коротких последних строк. Кроме того, он регулирует разбивку дефисами, если в конце абзаца несколько строках по порядку заканчиваются дефисами.

По замыслу CSS Working Group, задача pretty в каждом браузере заключается в максимальном улучшении ситуации с переносами текста. В спецификации CSS Text Level 4 это определяется следующим образом («user agent» — это веб-браузер; выделение добавлено нами):

Среди прочего, user agent может пытаться избегать излишне коротких последних строк… но также предпринимать дополнительные усилия по улучшению структуры. Конкретный список улучшений зависит от user agent; он может включать в себя: снижение колебаний длины строк; устранение типографических коридоров; приоритетизацию разных классов возможностей мягких переносов, возможностей разбивки дефисами или возможностей выравнивания; избегание разбивки дефисами в слишком большом количестве идущих по порядку строк.

Здесь очень важно слово «может»: оно чётко даёт понять, что каждый браузер сам должен решать, что конкретно должно делать pretty. Все браузеры не обязаны выбирать один и тот же вариант. На самом деле, команда разработчиков браузера может решить в 2025 году обрабатывать некоторые аспекты улучшения этих качеств, а в будущем изменить свою реализацию.

Из-за того, что большинство привыкло к реализации pretty в Chrome, многие веб-разработчики ожидают, что это значение будет только предотвращать короткие строки. Но оно никогда не предназначалось именно для этого. На самом деле, CSS Working Group определила для этой цели другое значение. Оно было переименовано на прошлое неделе в text-wrap: avoid-short-last-lines.

Демо

Вы можете попробовать text-wrap: pretty уже сегодня в Safari Technology Preview 216. Посмотрите наше демо, котором можно включать и отключать pretty для изучения его влияния. Также можно отключать разбивку дефисами и выравнивание, чтобы попробовать все комбинации. Направляющие и «призрачные» строки помогут понять происходящее. Или попробуйте text-wrap: balance, чтобы увидеть разницу. В демо есть контент на английском, арабском, немецком, китайском и японском языках, чтобы можно было увидеть влияние значения на разные системы письменности.

Screenshot of the demo showing a control panel of options that include: text-wrap: pretty, hyphenate, justify, show guides, show ghosts, text-wrap: balance. With a bunch of text on the page which will change as different options are applied.

Вот пример текста на английском без применения text-wrap. Это алгоритм расстановки переносов, который долгие годы по умолчанию использовался в вебе. Я включил опцию «show guides», чтобы отметить края текстового блока. Зелёной линией указан правый край блока, которого стремится достичь алгоритм выравнивания строк для каждой строки. Браузер выполняет перенос, когда текст достигает зелёной линии.

Three paragraphs of text, with a green vertical line marking the inline end edge of the text box.

А вот, как выглядит тот же текст при включенном text-wrap: pretty. Зелёная линия сместилась. Теперь браузер стремится выполнить перенос каждой строки раньше, чем максимум текстового блока. Он выполняет перенос внутри интервала, после сиреневой линии и до красной. Это снижает рваность края текста.

Demo of the same text, only now with better rag. The "guides" show three vertical lines about 50 pixels apart — the far right edge is marked with a red line. 45 pixels in from the left is a vertical green line. And another 45 pixels left of that line is a vertical magenta line.

Можно также включить опцию «show ghosts», чтобы увидеть на фоне прозрачную версию текста без pretty.

The same text, only now the well wrapped version is in normal color text, with the previous, badly wrapped version directly behind the good version, in a faint cyan color. It's a ghost of the before version, making it clear which lines have changed and how.

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

Можно заметить. что поскольку Safari Technology Preview применяет pretty к каждой строке текста, а не только к четырём последним строкам, значение влияет на текст гораздо сильнее. Блок текста начинает больше походить на прямоугольник.

Попробуйте добавить в типографику text-wrap: pretty , чтобы увидеть, что это поменяет. Результат будет трудно уловимым, но заметным. Если добавить к этому margin абзаца в 1lh, то текст станет выглядеть великолепно.

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

Производительность

Многих разработчиков вполне обоснованно беспокоит производительность text-wrap: pretty. Хотя качественная типографика приятнее глазу, за неё приходится расплачиваться замедлением страниц. При выборе ограничений команда разработчиков каждого браузера должна учитывать оборудование и чипы в устройствах пользователей.

Мы очень рады работе, проделанной нами для того, чтобы пользователи Safari не ощутили падения производительности, даже если веб-разработчики применят text-wrap: pretty к большой части контента веб-страницы.

Разработчику следует знать, что на производительность text-wrap не влияет то, к какому количеству элементов на странице оно применено. Вопросы производительности возникают, когда алгоритм pretty начинает учитывать всё больше строк в своих вычислениях. В браузерах или приложениях на основе WebKit для заметного снижения производительности понадобилось бы, чтобы текстовый элемент содержал сотни или тысячи строк, а такой контент редко встречается в вебе. Если ваш контент разбит на абзацы стандартной длины, то вам не о чем беспокоиться. Используйте text-wrap: pretty в любом нужном вам объёме, и будьте уверены в том, что разработчики браузера не позволят ощутить никаких недостатков такого подхода.

Возможно, мы добавим механизм разбиения длинных абзацев на более приемлемые блоки, чтобы WebKit вычислял каждый блок по отдельности. Если мы сделаем это, то на производительность не повлияют даже абзацы из тысячи строк. Такой подход применяется в Adobe InDesign. Он улучшает структуру всех строк текста, но не вычисляет бесконечное количество строк в каждом абзаце одновременно. Возможно, команда разработчиков WebKit найдёт и другие способы уравновесить красоту и скорость, чтобы значение pretty делало всё возможное для улучшения текста, не влияя при этом на удобство для пользователей.

Протестируйте text-wrap: pretty в Safari Technology Preview 216 уже сегодня, и сообщите нам, если столкнётесь со снижением производительности. Отправьте issue на bugs.webkit.org, чтобы мы учли ваш отзыв при совершенствовании фичи перед выпуском её в самом Safari.

Когда использовать pretty и balance?

Очевидно, что text-wrap: pretty предназначен для повышения красоты типографики текста в теле страницы. Но только ли для этого его можно использовать? А что насчёт text-wrap: balance? Когда следует применять pretty, а когда balance?

Кто-то может дать слишком простой ответ: «pretty — для абзацев, а balance — для заголовков», но это, скорее всего, будет плохим советом. Давайте сравним поведение balance и pretty, чтобы понять, какое значение следует использовать в заголовках, подписях, тизерах и других типах короткого текста с переносами.

text-wrap: balance

По сути, правило text-wrap: balance приказывает браузеру выполнять переносы в таких местах, чтобы каждая строка имела примерно ту же длину, что и остальные. Это похоже на складывание листа бумаги вдвое, втрое или вчетверо.

Возьмём для примера заголовок с используемым по умолчанию text-wrap: auto. Как видите, слово «enough» оказалось первым во второй строке просто потому, что после «with» в первой строке ей не осталось места. Каждая строка выстраивается одна за другой, без учёта остальных. Из-за этого в заголовке слово «itself» оказалось единственным в последней строке

А вот похожий заголовок с text-wrap: balance. Больше в последней строке нет одинокого слова. И это здорово! Но это ещё не всё. Последняя строка теперь имеет почти ту же длину, что и две другие. Первая строка сделана гораздо более короткой, чтобы её длина была «сбалансирована» с длиной остальных. По сути, все три строки имеют одинаковую длину.

Можно заметить. что в результате этого визуально заголовок стал существенно уже, чем общее пространство контейнера (отмеченное здесь голубой линией).

A balanced headline, where all three lines are about the same length. All of them are about two-thirds as wide as the box they are in, leaving a lot of white space on the right. The first line is actually the shortest line.

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

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

Для таких заголовков можно использовать text-wrap: pretty. Так вы избавитесь от короткой строки, и в то же время заполните контейнер в направлении движения текста.

A similar headline, with three words on the last line. The first line does stretch all the way across the box, and the second line is a bit shorter so that some of its words can fill in the last line.

Вы можете самостоятельно попробовать эти примеры в Safari Technology Preview 126+ и Chrome/Edge 130+, чтобы чётче уяснить, как text-wrap влияет на длинные, средние и короткие заголовки. Перетаскивайте угол контейнеров, чтобы увидеть, как по-разному они обрабатывают переносы.

А как text-wrap: balance влияет на производительность? Веб-стандарт CSS и в этом случае позволяет браузерному движку решать, какие ограничения будут применяться, чтобы это не повлияло на удобство для пользователей. Каждый браузер не обязан делать тот же выбор, что и остальные.

Реализация в Chromium ограничивает балансируемых количество строк четырьмя, чтобы Chrome, Edge и другие браузеры на Chromium продолжали оставаться быстрыми. Реализация в WebKit не требует ограничений по количеству строк. Каждая строка балансируется со всеми остальными.

То есть «pretty — для текста тела, а balance — для заголовков» — это слишком упрощённая рекомендация; тогда в каком ключе лучше рассуждать над этим выбором?

Я думаю об этом так:

  • pretty может применяться к любым элементам страницы — тексту тела, заголовкам, подписям, тизерам и так далее. Посмотрите, что делает это значение, и нравится ли вам его влияние. Если у вас есть невероятно длинные абзацы (иными словами, длинный текст тела страницы вообще без разбиения на абзацы, допустим, сотни или тысячи строк текста), то сначала измерьте производительность. Кроме того, если вы анимируете текст таким образом, что при анимации места переносов меняются, то это тоже стоит протестировать.

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

  • auto применяется по умолчанию; на данный момент при вычислении структуры оно учитывает только по одной строке за раз, как и весь веб с 1991 года (см. ниже).

  • stable должно использоваться для редактируемых полей текста и другого (см. ниже).

Вас не убедило заявление о том. что text-wrap: balance обычно неразумно использовать с длинными блоками текста? Можете попробовать это сами в том же демо.

The same demo, now with `text-wrap: balance` applied to the paragraphs. Each paragraph is now wildly different widths from the others. This is not useful for anything.

Видите, как общая ширина каждого абзаца выравнивается так, что все строки текста имеют примерно одинаковую длину, без учёта их ширины относительно контейнера? Именно это делает балансировка. В примере выше каждый абзац по ширине сильно отличается от остальных. Выглядит это странно. Используйте это только тогда, когда вам нужен такой эффект; в противном случае, наверно, стоит выбрать другой вариант.

А что делают другие значения text-wrap? Давайте их разберём.

text-wrap: avoid-short-last-lines

Значение avoid-short-last-lines стало самым новым в спецификации CSS Text Module Level 4. Оно ещё не реализовано ни в одном браузере. Оно будет заниматься устранением коротких последних строк, в то время как pretty выполняет множество других задач.

text-wrap: auto

Это значение text-wrap , используемое сейчас по умолчанию, делает ровно то, что делал веб с 1991 года: каждая строка текста выстраивается по отдельности, без учёта других. (Часто это называется «first-fit», или «жадным» алгоритмом.)

Однако в будущем ситуация может поменяться! Может настать день, когда браузеры решат выбрать иное поведение по умолчанию и будут применять какой-то алгоритм многострочного выравнивания ко всему контенту веба. Это улучшит весь контент, даже старые веб-сайты и сайты, разработчики которых никогда не слышали о text-wrap: pretty.

text-wrap: stable

Если вы пробовали использовать text-wrap: stable, то можете задаться вопросом: «Это значение ничего не делает! Зачем оно нужно?» По сути, на данный момент stable делает ровно то же, что и auto. Оно применяет алгоритм переноса first-fit, при котором каждая строка выстраивается так, чтобы полностью заполнить себя контентом, а переносы добавляются только в необходимых местах.

Этот алгоритм переноса особенно хорош, когда сам контент можно редактировать. Если пользователь пишет текст, то ему не нужно, чтобы слова/слоги скакали по разным строкам, меняя переносы в процессе ввода. Если вы хотите, чтобы контент не сдвигался из-за изменений в последующих строках, или вам просто нужно применить стандартные переносы строк, то выберите text-wrap: stable.

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

Выбрав text-wrap: stable явным образом, вы гарантируете, что контент продолжит создавать переносы при помощи исходного алгоритма, даже если браузеры переопределят поведение auto.

Значение stable уже имеет очень хорошую поддержку.

text-wrap-mode и text-wrap-style

На самом деле, свойство text-wrap — это краткая запись двух длинных записей. Свойство text-wrap-style используется для выбора применяемого алгоритма переносов, а text-wrap-mode позволяет включать и отключать переносы.

text-wrap-style: auto | stable | balance | pretty | avoid-short-last-lines
text-wrap-mode: wrap | nowrap 

Благодаря наличию свойств text-wrap-mode и text-wrap-style мы можем гибко менять стиль переносов независимо от того, выполняет ли контент переносы, и позволяем этому выбору каскадно распространяться.

Это значит, что мы можем также использовать короткую запись, чтобы просто отключить переносы при помощи text-wrap: nowrap. Или использовать text-wrap: wrap, чтобы снова включить переносы. Протестировать работу этих значений можно в демо.

Поддержка длинных записей text-wrap-mode и text-wrap-style вместе со значениями nowrap и wrap получила статус «Baseline Newly Available» (то есть стала доступной во всех крупных браузерах) в октябре 2024 года, когда Chromium добавил её в Chrome/Edge 130. Чтобы обеспечить полную поддержку переносов у пользователей со старыми браузерами, всегда можно обеспечить fallback к старому white-space: nowrap | normal. (Однако когда вы будете это делать, проверьте, как ведёт себя удаление пробелов, потому что на него влияет white-space.)

Теги:
Хабы:
Если эта публикация вас вдохновила и вы хотите поддержать автора — не стесняйтесь нажать на кнопку
+17
Комментарии1

Публикации

Работа

Веб дизайнер
22 вакансии

Ближайшие события