text-wrap: balance — простой способ улучшить переносы заголовков

Бывает, что с заголовком всё вроде бы нормально: размер шрифта подходит, ширина блока задана, текст сам по себе короткий. Но после вёрстки он переносится неудачно.
Например, первая строка почти полностью заполнена, а на второй остаётся одно короткое слово:
Сайт для бизнеса, который
работает на результат
Или заголовок разбивается на строки так:
Создаём сайты для
серьёзного бизнеса
При изменении ширины экрана ситуация может измениться ещё сильнее. На десктопе заголовок выглядит аккуратно, а на другой ширине одно слово внезапно переезжает на отдельную строку.
Есть и другая распространённая проблема — короткие союзы и предлоги, которые остаются в конце строки:
Создаём сайты для бизнеса и
помогаем развивать его онлайн
В крупном заголовке такие переносы особенно заметны и могут ухудшать его композицию.
Первое желание — поставить <br> и вручную указать браузеру, где должен быть перенос:
<h1>
Создаём сайты для<br>
серьёзного бизнеса
</h1>
Но это решение привязано к конкретной ширине. На мобильном перенос может потребовать уже другого положения.
Для таких случаев в CSS есть text-wrap: balance.
Что делает text-wrap: balance
Значение balance позволяет браузеру учитывать текстовый блок целиком и подбирать более равномерное распределение текста между строками.
h1,
h2,
h3,
h4,
h5,
h6 {
text-wrap: balance;
}
Вместо простого последовательного переноса браузер пытается найти более сбалансированный вариант.
Это особенно заметно на заголовках из двух или трёх строк: строки становятся ближе по длине, а вероятность получить отдельное короткое слово уменьшается.
То же касается коротких слов вроде «и», «в», «на», «для» и других служебных слов. balance может выбрать другой вариант переноса и тем самым убрать такой «висящий» предлог или союз.
Важно понимать, что balance не задаёт конкретные места переносов. Браузер сам выбирает подходящий вариант, поэтому результат может немного отличаться в разных браузерах.
Почему balance не стоит применять ко всему
Балансировка строк требует от браузера дополнительных вычислений: ему приходится перебирать варианты переноса, чтобы найти более подходящий результат.
Поэтому браузеры ограничивают количество строк, для которых применяется этот алгоритм. В Chromium балансируются блоки максимум из шести строк, в Firefox — максимум из десяти. Safari/WebKit на данный момент такого ограничения по количеству строк не устанавливает.
Именно поэтому нет смысла писать:
* {
text-wrap: balance;
}
Гораздо логичнее применять balance к коротким текстовым элементам:
h1,
h2,
h3,
h4,
h5,
h6,
.card-title {
text-wrap: balance;
}
Это как раз тот сценарий, для которого свойство предназначено: заголовки, подзаголовки, подписи и другие небольшие текстовые блоки.
Особенно хорошо работает с центрированными заголовками
Эффект balance хорошо заметен, когда текст выровнен по центру:
h1 {
max-width: 20ch;
margin-inline: auto;
text-align: center;
text-wrap: balance;
}
При обычном переносе центрированный заголовок может получить очень короткую последнюю строку, которая визуально нарушает форму блока. Балансировка позволяет распределить текст между строками более равномерно.
Но text-align: center не является обязательным условием. balance работает и с левым выравниванием — просто визуальный эффект в таком случае часто менее очевиден.
А что с обычным текстом?
Применять balance ко всем абзацам не стоит. Для обычного текста в CSS существует значение pretty:
p {
text-wrap: pretty;
}
Оно предназначено для более аккуратной вёрстки длинного текста и использует другой алгоритм. В частности, оно может улучшать расположение строк в конце абзацев.
Поэтому для сайта можно использовать простой набор:
h1,
h2,
h3,
h4,
h5,
h6 {
text-wrap: balance;
}
p {
text-wrap: pretty;
}
Подробнее о pretty читайте в этом материале.
Поддержка браузерами
text-wrap: balance уже поддерживается современными браузерами: Chrome и Edge — начиная с версии 114, Firefox — с 121, Safari — с 17.5.
В браузерах без поддержки свойство просто не сработает, а текст продолжит переноситься обычным способом. То есть это безопасное прогрессивное улучшение: верстка не ломается, просто пользователи старых браузеров не получают улучшенную балансировку.
А если перенос должен быть строго определённым?
Здесь balance не заменяет ручное управление переносами.
Если конкретные слова принципиально нельзя разделять, можно использовать неразрывный пробел:
дизайн и разработка
Но использовать для каждого предлога и союза по всему сайту неудобно. text-wrap: balance позволяет решить значительную часть подобных ситуаций автоматически.
Кроме того, balance не заменяет max-width. Если заголовок должен занимать определённую ширину в композиции страницы, ширину блока всё равно нужно контролировать отдельно.
В результате получается довольно простой подход: задаём нормальную ширину текстового блока, для коротких элементов используем text-wrap: balance, а там, где нужен абсолютно конкретный перенос, применяем ручное управление.
h1,
h2,
h3,
h4,
h5,
h6 {
text-wrap: balance;
}
Всего одна строка CSS, которая часто позволяет убрать несколько мелких типографических проблем без <br> и без отдельных правил для разных разрешений экрана.