Как фронтенд-разработчик вы строите блоки и помещаете в них текст. Множество сайтов и множество нативных приложений по своей сути являются именно набором блоков с текстом. Это наследие типографики с ее сотней веков истории со времен Гутенберга, буквы и блоки продолжают переизобретать себя и находить себе новое применение в материалах и технологиях, которые когда-то казались отдаленным будущим.

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

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

И пусть эта статья будет вашим руководством на основе четырех простых принципов.

1. Шрифт не любит обрезку

Во времена металлических шрифтов буквы, как и пробелы были физической материей, которую вы могли только добавить и никогда не могли убрать:

Ручной набор литер с текстом

Но даже тогда творческие люди находили способы обходить ограничения, задаваемые прямоугольниками из свинца с помощью методов, которые сейчас называют хаками:

Кернинг при ручном наборе сложного шрифта

Хак с кернингом при ручном наборе сложного шрифта

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

Слово type, выведенное простым шрифтомСлово type, выведенное рукописным шрифтом

Вы можете легко представить пример слева (в нем используется шрифт Stag) в виде четырех прямоугольников, размещенных подряд друг за другом. Но справа у нас y не только пытается захватить пространство у t, но даже выползает за пределы начала текста.

Такое выползание не является чем-то необычным в типографике и случается не только при использовании вычурных гарнитур типа Zapfino. Вот четыре примера с Medium, в которых обрезка текста ровно по краям блока также обрежет и буквы:

Выносные элементы в наклонном шрифте

Висячие кавычки

Маркеры упорядоченных списков

Заголовки со скорректированным выравниванием по левому краю

И что из этого следует?

  • Блок это не клетка. Вы не можете ожидать, что в него сможет вписаться все. Шрифты норовят вылезти любым возможным способом (особенно влево или вправо).
  • Вам нужно дать тексту пространство для маневра. Не обрезайте блок с текстом и, если вам нужно, оставьте внутренние отступы со всех сторон (по грубым расчетам должно хватить горизонтального внутреннего отступа длиной в ⅓ от размера шрифта).
  • В HTML по умолчанию браузеры позволяют содержимому выходить за пределы блоков, если только контейнеру или одному из его родительских блоков не задано overflow: hidden вместо visible. Если по какой-либо причине применено такое ограничение, важно добавить горизонтальный и вертикальный внутренние отступы, чтобы текст не обрезался.
  • В нативных приложениях iOS есть горизонтальная обрезка по умолчанию, за счет свойства, которое задает внутренний отступ для текстовых элементов — lineFragmentPadding. Это значение (5 пунктов по умолчанию) не должно быть слишком маленьким или же внутренний отступ должен делаться другими средствами. Также опасайтесь свойства lineHeightMultiple  — при значении меньше 1.0 оно может обрезать верхушки букв.
  • В нативных приложениях Android — я слышал, что clipChildren и clipToPadding могут повлечь проблемы, но вы можете обмануть TextView используя слой тени вокруг текста с прозрачным цветом, радиусом 1 и dx –60 (эта информация может быть уже устаревшей).

2. Шрифт не любит, когда его меряют

Я уверен, что вы сталкивались с этим по крайней мере раз в жизни.

Вы открываете Microsoft Word, выбираете размер шрифта, например, 50 пикселей и начинаете с шрифта Helvetica:

Текст, набранный гельветикой

Да, смотрится неплохо. Helvetica это эпоха. Но мы же продолжаем исследование, играем со шрифтами и все такое? Итак, переключаемся на другой шрифт, предположим, Clan, и внезапно все выглядит совсем по другому:

Текст со шрифтом того же размера, набранный Clan

Конечно, этот шрифт совершенно другой, но он также кажется…большим в сравнении с Helvetica. Этого не должно быть — мы ведь только поменяли шрифт. а не его размер. Но можно проверить еще раз. Все так, у него по прежнему размер 50 пикселей. Вы переключаете шрифты для уверенности:

Переключение с Helvetica на Clan

Однозначно, Clan больше. Почему?

Когда вы выбираете размер шрифта, вы выбираете только размер блока, в котором живет шрифт. Происходящее внутри этого блока полностью во власти дизайнера шрифта (и не только внутри, в случае с некоторыми шрифтами типа упомянутого Zapfino).

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

Наложение Helvetica на Clan

Итак, это правда: одинаковый размер шрифта не всегда будет одинаковым на самом деле.

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

Шрифт, прижатый к верхней части блока

Этот шрифт располагается выше большинства шрифтов.

Другой момент: внутри каждого блока есть немного пространства сверху и снизу от текста. Поэтому соблюдение последовательных интервалов может оказаться сложнее, чем кажется.

Когда вы раздвигаете два изображения, вы можете быть уверены, что ваши 20 пикселей это ровно 20 пикселей. Но в случае с текстом, к этим 20 пикселям добавятся немного вертикального отступа сверху и снизу каждого блока текста — и текст будет казаться дальше, чем задано.

20 пикселей между изображениями и 20 пикселей между текстом

Чтобы расстояние от текста ощущалось идентичным расстоянию от изображений, вам надо приблизить текст (несколько странно упоминать про ощущения в технической статье, но мы к этому еще несколько раз вернемся).

Изменение отступа от текста дает правильное выравнивание

Одинаковые отступы между всеми блоками в сравнении со специально отрегулированными различающимися отступами для текста и изображений.

Но ведь мы можем хотя бы расчитывать на то, что шрифты выравниваются горизонтально?

Да!?

Посмотрите на текст ниже. Здесь используется одинаковый шрифт и каждая линия начинается с одинаковой позиции по горизонтали. Однако вы можете видеть, что точка начала отдаляется от левого края по мере увеличения размера шрифта:

С увеличением размера шрифта первый символ отдаляется от левого края

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

И что из этого следует?

  • Блок это не клетка, еще раз. Шрифты не только любят выползать за пределы блока — еще меньше они любят выравниваться по какой-либо стороне блока с текстом. И это будет более заметным при увеличении шрифта.
  • Размеры шрифта работают внутри шрифта, но не гарантируют идентичность размеров разных шрифтов. Вы можете предполагать, что увеличение размера шрифта в два раза даст увеличение размера символов в два раза. Однако два шрифта с одинаковым размером могут значительно отличаться.
  • Горизонтальные и вертикальные внутренние отступы у текста намного сложнее аналогичных отступов у изображений. Если вам нужно точное выравнивание, вам надо учитывать пустые пространства по вертикали и горизонтали, которые имеются у каждого символа в шрифте.

3. Шрифт не любит стоять на месте

Режим перемешивания при прослушивании музыки был в свое время таким откровением, что Стивен Леви написал целую книгу об этом.

Для меня одной из самых интересных сторон этого стали люди, жалующиеся, что их iPod проигрывает две или больше песен подряд от одного автора. “Я только что слышал Фила Коллинза. Почему я слышу его еще раз? Режим перемешивания поломался?”

Это точно такая же мотивация, как у моей мамы, смеющейся после моего совета выбрать числа “1 2 3 4 5 6 7” в национальной лотерее. Apple не мог исправить такой недостаток, но чтобы решить проблему по таким жалобам, функция перемешивания была немного улучшена: они сделали перемешивание менее случайным, чтобы оно казалось более случайным.

Типографика работает похожим образом. Шрифт выровнен, когда он кажется выровненным, а не когда он действительно выровнен.

В следующем примере, верхушки букв с завитками выходят выше линии, установленной прямыми буквами так, что они все выглядят идеально выровненными:

Верхние выносные элементы синхронно выходят выше роста строчных букв

А вот строчная буква y находится под шляпкой T, чтобы казаться также близко как и прописная Y, которая на самом деле расположена дальше:

Строчная y сдвинута под шляпку T, чтобы расстояние между ними казалось идентичным среднему расстоянию

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

Двойка верхнего индекса это отдельный глиф

2 в степени 2 · 2 верхнего индекса, увеличенная до обычной 2 · Их наложение

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

Обычный шрифт, синтезированный и нормальный жирный шрифты

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

Обычный, сжатый и синтезированный сжатый шрифты

Шрифт на второй строке такой же, как и на первой, только сжатый по горизонтали. Не делайте так никогда.

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

И со всем этим вы заметите повторение уже знакомой темы — все эти значения будут изменяться, чтобы шрифт смотрелся одинаково.

Вот текст в двух размерах: 50 и 500 пикселей с выровненным расстоянием между буквами так, чтобы оно смотрелось одинаковым. У текста меньшего размера расстояние между символами -30, у большего — -60.

Межбуквенный интервал, уменьшенный с ростом размера шрифта

Межбуквенный интервал: –30 сверху, –60 снизу

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

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

Неизменный межбуквенный интервал на разных размерах шрифта

Межбуквенный интервал –30 в обоих случаях. Шрифт большего размера кажется разреженным по сравнению со шрифтом меньшего размера.

Из той же темы. С увеличением размера шрифта межбуквенный интервал и высота строки должны уменьшаться быстрее, чем увеличивается шрифт. С увеличением длины строки высота строки должна увеличиваться, чтобы зрительно компенсировать это. Иногда вам надо настраивать только высоту строки при простом изменении начертания шрифта (например от тонкого к жирному) и ничего больше.

И что из этого следует?

  • Многократно использовать значения надо с осторожностью. Вы не можете просто копировать и вставлять значения для межбуквенного интервала и высоты строки, это также верно для значениях в величинах, которые зависят от размера шрифта (например, em в CSS).
  • Убедитесь, что у вас есть все нужные начертания выбранного шрифта. Если вы не предоставляете жирный или наклонный шрифт, верхний индекс или уменьшенные прописные, ваш браузер или операционная система синтезирует свой вариант (если вы так сделаете, то вы заслуживаете провести вечность в типографическом аду).
  • В нативных приложениях iOS. Межбуквенный интервал и кернинг это разные вещи. Но по каким-то причинам в iOS эквивалент межбуквенного интервала называется NSKernAttributeName. Учитывайте это.

4. Шрифт не знает никаких пределов

Удивлялись ли вы когда-нибудь тому, что некоторые тексты на большом экране сложнее читать? Например, в чем проблема со следующей страницей?

Страница из википедии с текстом на всю ширину

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

Иногда это приводит к катастрофе.

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

Есть точка, на которой строка становится слишком длинной для комфортного чтения. Это именно то, что происходит с текстом на скриншоте. Строки слишком растянуты и в результате глазам становится утомительно это читать.

В параграфе выше я упомянул “точку” и нужно понимать, что я не смогу вам дать конкретное число в качестве рекомендации так как типографика просто не работает таким образом. Все зависит от выбранного шрифта, высоты строки и т.д. Но у нас есть ориентир в виде диапазона — 45-75 символов, для глаз оптимально приблизительно 65 (в случае использования западной типографики).

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

Вы можете сказать “это уже не имеет значения, ведь все читают на маленьких экранах”. Но здесь у нас также возникают свои проблемы, так как строки получаются слишком короткими для комфортного просмотра. Вот, например, текст сбоку от изображения, строки в нем слишком узкие для комфорта:

Текст рядом с картинкой на экране телефона слишком узкий

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

Длинное слово не помещается в пространство рядом с изображением

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

Как наборщик, вы должны знать о других наборщиках. Среди них есть один известный человек немецкого происхождения, родившийся в 1904 году. Его вклад в наборное дело не слишком ясен, так как все это затмило его невероятно длинное имя. Готовы? Вот оно:

Hubert Blaine Wolfe­schlegel­stein­hausen­berger­dorff, Sr.

Безумно. Но это даже близко не полное имя Хьюберта. Его имя включало 26 имен (на каждую букву алфавита), за которыми следовала очень длинная фамилия из одного слова. Полная версия будет чуть ниже, под портретом героя:

Hubert_Blaine_Wolfeschlegelsteinhausenbergerdorff

Adolph Blaine Charles David Earl Frederick Gerald Hubert Irvin John Kenneth Lloyd Martin Nero Oliver Paul Quincy Randolph Sherman Thomas Uncas Victor William Xerxes Yancy Zeus Wolfe­schlegel­stein­hausen­berger­dorff­welche­vor­altern­waren­gewissen­haft­schafers­wessen­schafe­waren­wohl­gepflege­und­sorg­faltig­keit­be­schutzen­vor­an­greifen­durch­ihr­raub­gierig­feinde­welche­vor­altern­zwolf­hundert­tausend­jah­res­voran­die­er­scheinen­von­der­erste­erde­mensch­der­raum­schiff­genacht­mit­tung­stein­und­sieben­iridium­elek­trisch­motors­ge­brauch­licht­als­sein­ur­sprung­von­kraft­ge­start­sein­lange­fahrt­hin­zwischen­stern­artig­raum­auf­der­suchen­nach­bar­schaft­der­stern­welche­ge­habt­be­wohn­bar­planeten­kreise­drehen­sich­und­wo­hin­der­neue­rasse­von­ver­stand­ig­mensch­lich­keit­konnte­fort­pflanzen­und­sicher­freuen­an­lebens­lang­lich­freude­und­ru­he­mit­nicht­ein­furcht­vor­an­greifen­vor­anderer­intelligent­ge­schopfs­von­hin­zwischen­stern­art­ig­raum, Senior.

Вы может больше прочитать о Hubert B. Wolfe + 666, Sr. в Википедии (русский вариант), среди прочих анекдотов выделяется история о компьютере IBM 7074, который просто не мог обработать имя из-за его длины, вследствие чего дело Хьюберта в страховой компании John Hancock Mutual Life Insurance было единственным, над которым работали вручную.

Сейчас, более чем через полвека после той истории, вы можете взять имя Хьюберта и вставить на сайт и не факт, что все пройдет гладко. Конечно, абсурдно длинные имена не слишком распространены, но представьте сложную конструкцию соединенную слэшами или чистый URL — эта ситуация совершенно реальна:

Текст ссылки не вмещается на экране смартфона

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

И что из этого следует?

  • Строкам надо задавать максимальную длину. Она должна быть сравнительно простой для расчета и не обязана быть очень точной — просто убедитесь, что вашему тексту не позволено растягиваться так, чтобы напрягать глаза.
  • Строкам надо задавать минимальную длину. На маленьких экранах очень легко выйти за пределы пространства. Если у вас есть иной контент, смешанный с текстом или отступы — тестируйте возможные случаи и старайтесь располагать элементы друг над другом, а не рядом.
  • Слова должны иметь возможность разбиваться. Иначе они могут не влезть в экран (это особо важно, когда вы создаете контейнеры для текста, заполнять которые будут другие люди).
  • В HTML вы можете вручную вставлять мягкие дефисы, невидимые пробелы и теги wbr, которые будут инертными, кроме случаев приближения слова к правому краю, позволяя разбивать его в этой точке. Вы также можете использовать свойство CSS word-break: break-all (хотя оно дает вам меньше контроля) или, если вам проще утратить часть текста, вам поможет text-overflow . Также есть автоматические переносы, но они поддерживаются не слишком хорошо. И ограничение числа строк.
  • В нативных приложениях iOS. К счастью, iOS по умолчанию умеет разбираться со слэшами и длинными словами. Обратите внимание на переносы слов. Вы можете использовать невидимые пробелы и мягкие переносы, но их надо экранировать: \u200B и \u00AD. Для меток, а не фрагментов текста может помочь NSLineBreakMode.
  • В нативных приложениях Android. Начиная с Lollipop появились опции для переносов hyphenationFrequency и breakStrategy, специальные символы вставляются и экранируются также как и в iOS.

Заключение

Итак, теперь вы знаете это. Добро пожаловать в мир верстки, в котором числам нельзя верить, линейки только имитируют выравнивание, а границе такие же, как в Шенгенской зоне.

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

Но я надеюсь, что после чтения этих четырех принципов, некоторые тайны верстки вы сможете контролировать лучше. И также сможете добавить “наборщик” в свой профиль в Твиттере. Верьте мне. Это отличное чувство, даже если ваше имя короче 666 символов.

Дополнительные материалы
  1. Шрифт не любит обрезку: Space yourself · A photo essay of physical typesetting · Hanging punctuation
  2. Шрифт не любит, когда его меряют: Difference between kerning, letter spacing, and sidebearings · On em, rem, and ch CSS units
  3. Шрифт не любит стоять на месте: On optical adjustments · What is kerning · How to choose the right line height · Say no to faux bold · Why distorting type is a crime
  4. Шрифт не знает никаких пределов: Type measure · Space yourself