Публичный контракт вместо внутренних формул в typographics 5

03 Сен 2026

Выпустил typographics@5.0.0. Изменение в самом CSS небольшое: блоки кода теперь по умолчанию используют ту же плавную базу, что и основной текст. После 3.0.0 постепенно упрощаю настройку и подключение пакета, чтобы пользователю не приходилось разбираться во внутренних формулах и путях к собранным файлам.

В 3.0.0 убрал html { font-size: 10px } и разделил основной текст и заголовки на две плавные шкалы. Модель стала аккуратнее. Теперь её можно настраивать на нескольких уровнях. Иногда нужно просто сделать типографику чуть меньше внутри статьи. Иногда — задать точные размеры одному заголовку на границах адаптивного диапазона. А подключение пакета не должно требовать знания пути к собранному CSS.

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

Масштаб без копирования формулы

В 3.0.0 размер основного текста вычислялся через --t-body-font-size-clamp, а заголовков — через --t-heading-font-size-clamp. Чтобы уменьшить всю типографику, можно было переопределить исходные min/max. Но для обычной задачи “сделать этот блок на 5% компактнее” это слишком сложная настройка.

В 3.1.0 добавил две переменные:

:root {
  --t-body-scale: 1;
  --t-heading-scale: 1;
}

Они масштабируют уже рассчитанную плавную базу:

font-size: calc(
  var(--t-heading-font-size-clamp)
  * var(--t-heading-scale, 1)
  * #{$k}
);

Для ролей основного текста схема такая же:

font-size: calc(
  var(--t-body-font-size-clamp)
  * var(--t-body-scale, 1)
  * #{$k}
);

CSS-переменные наследуются и участвуют в каскаде, поэтому коэффициенты можно задавать и для всего документа, и для отдельного блока:

:root {
  --t-body-scale: 0.9;
  --t-heading-scale: 0.9;
}

.article {
  --t-body-scale: 0.95;
}

.hero {
  --t-heading-scale: 0.9;
}

В .article локальное значение --t-body-scale: 0.95 заменяет унаследованное от корня 0.9. Для заголовков продолжает действовать коэффициент 0.9. Правило .hero явно задаёт тот же масштаб заголовков в этой области.

Чтобы изменить масштаб группы текста, достаточно задать коэффициент. Копировать clamp() и внутренние calc() больше не нужно.

Патч 3.0.1 перед этим ничего глобально в CSS не менял — я только исправил примеры в README.

Общего масштаба заголовков недостаточно

Общий коэффициент подходит для многих задач, но реальные макеты показали его ограничение. Иногда разным ролям заголовков нужны разные адаптивные диапазоны. Умножить размеры всех заголовков на 0.9 недостаточно, если, например, только .headline-medium должен быть 28px на узком экране и 34px на широком.

В 3.2.0 добавил необязательные границы для каждой роли заголовка:

.headline-medium {
  --t-headline-medium-min: 28px;
  --t-headline-medium-max: 34px;
}

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

--t-heading-resolved-min: var(
  --t-#{$fluid-key}-min,
  calc(
    var(--t-heading-font-size-min)
    * var(--t-heading-scale, 1)
    * #{$k}
  )
);

--t-heading-resolved-max: var(
  --t-#{$fluid-key}-max,
  calc(
    var(--t-heading-font-size-max)
    * var(--t-heading-scale, 1)
    * #{$k}
  )
);

Дальше эти два значения становятся границами clamp(). Явно заданная граница используется напрямую, без умножения на --t-heading-scale и коэффициент роли. Можно задать одну границу, оставив вторую из общей шкалы.

Новый API не заставляет настраивать каждую роль вручную. По умолчанию всё продолжает следовать общей шкале. Точные min/max нужны только там, где макет действительно этого требует.

Перед стабильным релизом опубликовал 3.2.0-dev.0 для обкатки. В стабильном 3.2.0 общая шкала заголовков осталась вариантом по умолчанию, а отдельные роли получили возможность использовать собственные границы.

Подключение пакета тоже часть API

В 4.0.0 типографический CSS относительно 3.2.0 не изменился. Мажорный релиз был связан со сборкой и подключением пакета.

К этому моменту я привёл npm-пакеты своего портфолио к общему стандарту сборки и публикации. В typographics, в частности, добавил экспорт CSS из корня пакета:

{
  "style": "./dist/index.css",
  "exports": {
    ".": {
      "style": "./dist/index.css",
      "default": "./dist/index.css"
    },
    "./dist/*": "./dist/*"
  }
}

В README основной способ подключения теперь указан через имя пакета. Этот вариант рассчитан на сборщик с поддержкой CSS-импортов:

import 'typographics';

Прямой путь к CSS внутри dist остаётся доступен. Корневой экспорт проверяется вместе с собранным пакетом, а пользователю для подключения достаточно имени пакета.

Мажорная версия понадобилась из-за изменения публичного способа подключения и требований пакета. CSS при этом остался прежним.

Блок кода следует основному тексту

Перед 5.0.0 в плавной модели оставалось заметное исключение. Абзацы и списки уже зависели от --t-body-font-size-clamp, а для блока кода по умолчанию использовалось 1.4rem:

font-size: calc(
  var(--t-code-block-font-size, 1.4rem)
  * var(--t-body-scale, 1)
);

В 5.0.0 значение по умолчанию берётся из базы основного текста:

:root {
  --t-code-block-scale: 1;
}

@mixin typography-code-block() {
  font-size: var(
    --t-code-block-font-size,
    calc(
      var(--t-body-font-size-clamp)
      * var(--t-body-scale, 1)
      * var(--t-code-block-scale, 1)
    )
  );
}

По умолчанию блок кода использует плавную базу основного текста и коэффициент --t-body-scale. Чтобы изменить масштаб только кода, достаточно --t-code-block-scale:

.article {
  --t-code-block-scale: 0.9;
}

Размер можно задать и напрямую:

.article {
  --t-code-block-font-size: 13px;
}

В 5.0.0 явный --t-code-block-font-size заменяет плавный расчёт целиком. Коэффициенты --t-body-scale и --t-code-block-scale к нему не применяются. При --t-code-block-font-size: 13px и --t-body-scale: 0.9 прежняя формула даёт 11.7px, новая — 13px.

Такой API для typographics оказался удобнее, чем настройка через внутренние формулы.

К 5.0.0 публичный API выглядит достаточно цельно. --t-body-scale и --t-heading-scale позволяют масштабировать группы текста, min/max конкретной роли — задать точные границы. Блок кода использует общую плавную базу, а для импорта достаточно имени пакета. Внутри по-прежнему есть clamp(), коэффициенты и резервные формулы, но пользоваться библиотекой можно, почти не разбираясь в этих расчётах.

Материалы