Заявляю: «Мы, как цивилизация, разучились использовать центрирование». Ну то есть мы, конечно, знаем, как это делать — очень просто:
display: flex;
justify-content: center; /* Горизонтальное центрирование */
align-items: center; /* Вертикальное центрирование */
Не спрашивайте, почему вам нужно запомнить четыре слова вместо просто горизонтальное/вертикальное; всё равно лучше, чем было до этого.
Ещё можно использовать сетку:
display: grid;
justify-items: center; /* Горизонтальное центрирование */
align-items: center; /* Вертикальное центрирование */
Также не спрашивайте, почему выражение justify-content
стало justify-items
.
Если вы не прочь немного вспомнить школу, то можем опереться на фундаментальные принципы:
Да даже ChatGPT умеет центрировать контент:
ChatGPT: Чтобы центрировать один прямоугольник внутри другого, нужно совместить их центры. Предположим, у нас есть два прямоугольника — одни внутри другого.
Выберем обозначения:
- (x1, y1) будут координатами центра внешнего прямоугольника.
- w1, h1 будут шириной и высотой внешнего прямоугольника.
- (x2, y2) будут координатами центра внутреннего прямоугольника.
- w2, h2 будут шириной и высотой внутреннего прямоугольника.
Чтобы центрировать внутренний прямоугольник во внешнем, нужно установить координаты его центра (x2, y2) равными координатам центра внешнего прямоугольника (x1, y1).
Значит, формулами для центрирования внутреннего прямоугольника во внешнем будут:
x2 = x1
y2 = y1
Это обеспечит совпадение центров внутреннего и внешнего прямоугольников по вертикали и горизонтали, а значит и центрирование внутреннего прямоугольника во внешнем.
Хорошо, пусть не сразу, но в конечном итоге он находит решение. Я лишь хочу сказать, что все знают, как делать центрирование. Это просто. И если вы запутаетесь, то информация всегда под рукой.
Тем не менее, когда мы смотрим на реальные приложения, то видим, что эти методы не используются. Вот пример:
Или вот:
Или даже такой:
То есть между «знанием как» и фактическим применением этого знания явно возникает какой-то пробел.
Теоретически между теорией и практикой разницы нет. К сожалению, мы живём в практическом мире. Так что же происходит? Будем разбираться.
▍ Шрифты
В шрифтах происходит одно из самых серьёзных нарушений. Плохо выровненный текст встречается повсюду. Приведу примеры.
Его не может выровнять ни Apple:
Ни Microsoft:
Ни GitHub:
Ни Valve:
Ни Slack:
Ни Telegram:
Ни Google Maps:
Честно говоря, я могу с ходу привести бесконечный список примеров криво выровненных надписей кнопок:
Думаю, смысл вы поняли. Многочисленные компании — крупные и малые, в нативной или веб-среде — имеют проблемы с выравниванием текста.
▍ Высота строки
Если вам недостаточно примеров со шрифтами, то очередной проблемой является высота строки.
Это довольно сложная тема, и для лучшего её понимания советую каноническую статью Винсента де Оливейры Deep dive CSS: font metrics, line-height and vertical-align.
Вот как это выглядит на практике. Slack:
Notion:
Airbnb:
YouTube:
Выровнять два элемента в разных контейнерах практически невозможно:
Многие пробовали:
Но немногие преуспели:
Помешать может CSS (разные элементы управления имеют разные значения, которые нужно отменить, прежде чем начать выравнивание):
И здесь нет лёгкого решения. Просто закатываем рукава и ныряем в спецификации.
▍ Иконки
Иконки подобны небольшим прямоугольникам, вставляемым в текст. Поэтому здесь актуальны все те же проблемы, которые связаны с текстом и высотой строки. Выравнивание иконок рядом с текстом реально непростая задача.
Atom:
Бывший Twitter:
iOS:
Mozilla:
YouTube:
Иногда иконка выигрывает у текста:
Иногда текст выигрывает у иконки:
Иногда оба проигрывают:
Некоторые иконки — это просто старые элементы управления HTML:
Некоторые стилизованы:
Спасибо bee за скриншот
Иногда люди достигают точного выравнивания креативным способом:
Но в целом это безнадёжная игра:
Проблема в том, что CSS нам тут не поможет. У свойства vertical-align
есть 13 возможных значений, но ни одно из них не выровняет иконку как следует:
Ближе всего text-align: middle
, но это свойство выравнивает по x-height
, а не cap-height
, которая по-прежнему выглядит криво:
Именно поэтому люди так любят веб-программирование. Здесь для них всегда есть вызов.
▍ Шрифты иконок
Выравнивать прямоугольники относительно легко, а вот текст — трудно. Иконки прямоугольные. А что получится, если поместить их в файл шрифтов?
Теперь мы ничего не сможем выровнять:
Равно как и установить размер иконок. В примере выше для всех иконок были установлены одинаковые размер шрифта и высота строки. Как видите, в итоге все они получились разных размеров с разными отступами, и ни одна не выровнена как следует.
Несмотря на множество их недостатков и практически полное отсутствие плюсов, компании стремятся использовать иконки повсюду. И вот что мы получаем в итоге:
macOS 10.14 → macOS 10.15
Обратите внимание, что операторы утратили вертикальное выравнивание и получились размытыми. Всё из-за переключения на иконочный шрифт.
В Apple были настолько привержены к использованию иконочных шрифтов, что даже испортили кнопку записи в QuickTime:
Только посмотрите на неё:
Да, так она и выглядит по сей день. Как и калькулятор. Но это далеко не единственный пример. Вот ещё один:
Второй:
Третий:
Четвёртый:
Пятый:
Шестой:
Седьмой:
То же, что и в случае выравнивания текста — бесконечное число примеров криво выровненных иконок.
▍ Недостаток навыков
Но с выравниванием проблемы наблюдаются не только у программистов. То же касается и дизайнеров:
Текущая версия/моё исправление
Проблема с иконками в том, что иногда для получения красивой картинки вам нужно учесть их форму:
Плохое выравнивание / хорошее выравнивание
Треугольники особенно проблематичны:
Иногда они уезжают влево:
Иногда вправо:
А могут оказаться задраны (здесь снова высота строки):
▍ Горизонтальное центрирование
Вы можете решить, что трудно добиться выравнивания только по вертикали. Но нет — по горизонтали тоже бывают сложности:
Я не думаю, что для этого есть какие-то глубокие причины, помимо банальной неаккуратности самих людей:
Ну серьёзно!
Разве так можно сделать намеренно?
Ну не знаю. Причём иконок это тоже касается:
Как и текста:
▍ Что делать: дизайнерам?
Итак, в чём проблема?
Всё начинается со шрифта. Сейчас рамка текстового блока выглядит так:
Проблема в том, что она может выглядеть и так:
Или так:
А что произойдёт, если попробовать выровнять текст, центрировав его рамку?
Текст сместится! Несмотря на то, что прямоугольники идеально отцентрованы. Но даже если метрики шрифта и могут исказиться, это не значит, что так и есть.
Что же происходит в реальности?
В реальности метрики большинства шрифтов слегка искажены. Во многих эти искажения значительны:
Проценты указаны для cap-height
И 10% — это немало. При размере шрифта 13 — это целый пиксель. А при двухкратном масштабировании уже два! Это легко заметить.
По сути, именно из-за Segoe UI интерфейс GitHub в Windows выглядит так:
Решение здесь простое: использовать рамки вокруг текста. Тогда центрировать шрифт будет легко.
Если вы используете сервис Figma, то он это умеет (хоть и не по умолчанию):
▍ Что делать: дизайнерам шрифтов?
Если вы дизайнер шрифтов, то можете упростить всем жизнь, настроив метрики так, чтобы ascender − cap-height = descender
:
Вот тот же принцип наглядно:
Важно! Вам не обязательно реально растягивать восходящие/спусковые элементы букв до этих границ. Как видно по картинке, у меня область под восходящую часть используется мало. Просто сделайте так, чтобы их размеры совпадали.
Как в веб-, так и в нативной разработке для избежания лишней головной боли выбирайте шрифт, который уже соответствует этому правилу. Например, SF Pro Text, Inter и Martian Mono ему следуют, значит, будут отлично центрироваться без дополнительных хлопот.
Подробнее читайте в статье: Font size is useless; let’s fix it.
▍ Что делать: веб-разработчикам?
С позиции разработки ситуация несколько сложнее.
Первым делом вам нужно понимать, какой шрифт вы будете использовать. К сожалению, предложенное мной решение не сработает, если вы планируете подстановочные шрифты.
Возьмём используемый на этой странице IBM Plex Sans. Вот его метрики:
Устанавливая font-size, вы устанавливаете UPM (это значение также будет равно 1em
). Тем не менее фактическое занимаемое текстовым блоком пространство находится между областями восхождения (ascender) и спуска (descender).
Путём простых расчётов мы выясняем, что нам поможет добавление padding-bottom: 0.052em
:
Должно получиться так:
Либо в реальном CSS (в оригинале можно выделить текст, чтобы увидеть окружающую его рамку, — прим. пер.):
Нужные метрики шрифтов можно найти по ссылке opentype.js.org/font-inspector.html (ascender, descender, sCapHeight).
Теперь, когда мы с этим разобрались, можно без особых проблем выравнивать и иконки. Вы устанавливаете vertical-align: baseline
и затем смещаете их вниз на (iconHeight - capHeight) / 2
:
К сожалению, для этого необходимо знать метрики шрифта и размер иконок. Но такое решение хотя бы работает:
Также в оригинале можно выделить текст, чтобы увидеть рамку, — прим. пер.
▍ Что делать: с иконочными шрифтами?
ПРЕКРАТИТЕ.
ИСПОЛЬЗОВАТЬ.
ШРИФТЫ.
ДЛЯ.
ИКОНОК.
Используйте обычный формат изображений. Тот самый — с шириной и высотой.
Я даже нарисовал для вас логическую блок-схему, чтобы было проще принять решение:
Вы только взгляните, как усердно в Apple стараются вписать галочку в прямоугольник, а прямоугольник разместить рядом с текстовой меткой:
И всё безуспешно!
Что может быть проще, чем выровнять два прямоугольника. Но что может быть сложнее, чем пытаться выровнять текст, вокруг которого есть произвольный объём пустого пространства.
Победить в этой игре невозможно.
▍ Что делать: с визуальной корректировкой?
Мы, как разработчики, можем математически выровнять лишь идеальные прямоугольники. Поэтому всё, что требует ручной подстройки, заключайте в достаточно большой прямоугольник и визуально выравнивайте иконку внутри:
▍ Что делать: всем?
Будьте внимательны. Будьте осторожны. Плохое выравнивание может испортить прекрасный интерфейс:
И напротив, с правильно выровненным текстом ваш интерфейс обретёт утончённую красоту:
Даже если это трудно. Даже если инструменты создают неудобства. Даже если приходится искать решения. Я верю, что вместе мы можем разобраться, как засунуть один прямоугольник в другой ровно.
Я, например, хочу жить в мире красиво выровненных пользовательских интерфейсов. И верю, что вы хотите того же.
В конце концов приложенные старания того стоят.
▍ Отдельная благодарность
Всех благ!
Автор: Дмитрий Брайт