Typography

Полный набор типографических утилит: размеры абсолютные и относительные, насыщенность, выравнивание, трансформация, межстрочный интервал, декор, переносы и шрифтовые семейства. Классы имеют адаптивные варианты с суффиксами -sm, -md, -lg, -xl — кроме относительных размеров.

Опциональный модуль packages/utils/scss/_typography.scss ~230 классов

CSS-переменные

ПеременнаяЗначениеНазначение
--gr-font-sans system-ui, -apple-system, sans-serif Семейство без засечек
--gr-font-serif Georgia, Cambria, serif Семейство с засечками
--gr-font-mono SFMono-Regular, Menlo, Consolas, monospace Моноширинное семейство
--gr-font-size-base 1rem Базовый размер шрифта

Размер шрифта

10 размеров от 12px до 60px. Генерируются SCSS-циклом по карте (xs: 0.75rem, sm: 0.875rem, ...).

КлассREMPX
.gr-text-xs0.75rem12px
.gr-text-sm0.875rem14px
.gr-text-base1rem16px
.gr-text-lg1.125rem18px
.gr-text-xl1.25rem20px
.gr-text-2xl1.5rem24px
.gr-text-3xl1.875rem30px
.gr-text-4xl2.25rem36px
.gr-text-5xl3rem48px
.gr-text-6xl3.75rem60px
<p class="gr-text-xs">12px — подписи, сноски</p>
<p class="gr-text-sm">14px — вспомогательный текст</p>
<p class="gr-text-base">16px — основной текст</p>
<h3 class="gr-text-2xl">24px — подзаголовок</h3>
<h1 class="gr-text-5xl">48px — крупный заголовок</h1>
Результат
.gr-text-xs (12px)

Подписи, сноски, мелкий вспомогательный текст

.gr-text-sm (14px)

Вспомогательный текст, описания полей

.gr-text-base (16px)

Основной текст документа, body

.gr-text-lg (18px)

Укрупнённый текст, лиды

.gr-text-xl (20px)

Подзаголовки

.gr-text-2xl (24px)

Заголовки разделов

.gr-text-3xl (30px)

Крупные заголовки

.gr-text-4xl (36px)

Герой-секции

.gr-text-5xl (48px)

Главный заголовок страницы

.gr-text-6xl (60px)

Лендинги, промо

Относительный размер

Базовые .gr-text-* считают размер в rem — от корня документа, независимо от окружения. Для страницы это правильно, но неудобно для блока, который показывают в разных местах шаблона: виджет в шапке и он же в подвале должны отличаться размером, а содержимое у них одно. То же с текстом, подгружаемым из БД: на этапе вёрстки неизвестно, куда его вставят.

.gr-text-rel-* не задают размер, а сдвигают текущий на фиксированный шаг в пикселях. Шаг взят в пикселях, а не долей em, намеренно: от базовых 16px четыре младшие ступени попадают в базовую шкалу ровно, без округлений.

КлассЗначениеПри родителе 16px
.gr-text-rel-xscalc(1em - 4px)12px — как .gr-text-xs
.gr-text-rel-smcalc(1em - 2px)14px — как .gr-text-sm
.gr-text-rel-lgcalc(1em + 2px)18px — как .gr-text-lg
.gr-text-rel-xlcalc(1em + 4px)20px — как .gr-text-xl
.gr-text-rel-2xlcalc(1em + 6px)22px
.gr-text-rel-3xlcalc(1em + 8px)24px

Ступени base в наборе нет: класс, не меняющий размер, не нужен — его роль играет отсутствие класса. Шкала обрывается на 3xl: крупнее — это уже не подстройка блока под окружение, а отдельный заголовок, для которого есть базовый набор.

<!-- разметка виджета одна, размер задаёт только класс на корне -->
<article class="gr-text-sm">
  <h4 class="gr-text-rel-xl">Заголовок виджета</h4>
  <p>Текст из БД</p>
  <p class="gr-text-rel-xs">Сноска</p>
</article>
Один виджет, два места в шаблоне
корень: .gr-text-sm (14px)

Заголовок виджета

Текст, подгружаемый из БД. Размер сдвигается вместе с корнем блока.

Сноска

корень: .gr-text-xl (20px)

Заголовок виджета

Текст, подгружаемый из БД. Размер сдвигается вместе с корнем блока.

Сноска

Четыре особенности, о которых стоит помнить:

Насыщенность

9 значений font-weight от 100 до 900. Генерируются SCSS-циклом по карте.

КлассЗначениеРоль
.gr-font-thin100Сверхтонкий
.gr-font-extralight200Очень тонкий
.gr-font-light300Тонкий
.gr-font-normal400Нормальный (по умолчанию)
.gr-font-medium500Средний
.gr-font-semibold600Полужирный
.gr-font-bold700Жирный
.gr-font-extrabold800Очень жирный
.gr-font-black900Сверхжирный
<span class="gr-font-light">Тонкий текст</span>
<span class="gr-font-semibold">Полужирный текст</span>
<span class="gr-font-bold">Жирный текст</span>
Результат
.gr-font-thin (100)

Griffincss — модульная типографика

.gr-font-light (300)

Griffincss — модульная типографика

.gr-font-normal (400)

Griffincss — модульная типографика

.gr-font-medium (500)

Griffincss — модульная типографика

.gr-font-semibold (600)

Griffincss — модульная типографика

.gr-font-bold (700)

Griffincss — модульная типографика

.gr-font-extrabold (800)

Griffincss — модульная типографика

.gr-font-black (900)

Griffincss — модульная типографика

Выравнивание

Четыре класса text-align: центр, ширина и логические стороны строки.

КлассЗначениеВ RTL
.gr-text-centertext-align: centerпо центру
.gr-text-justifytext-align: justifyпо ширине
.gr-text-starttext-align: startсправа
.gr-text-endtext-align: endслева

start и end — начало и конец строки, а не сторона экрана: в LTR это левый и правый край, в RTL они меняются местами сами. Физические .gr-text-left / .gr-text-right удалены: сторона текста следует за направлением письма, а буквальная сторона задаётся своим CSS.

<p class="gr-text-start">По началу строки</p>
<p class="gr-text-center">По центру</p>
<p class="gr-text-end">По концу строки</p>
<p class="gr-text-justify">По ширине с растяжением пробелов</p>
Результат
.gr-text-center
Этот текст выровнен по центру. Используется для заголовков и коротких блоков.
.gr-text-justify
Этот текст выровнен по ширине. Слова растягиваются так, чтобы заполнить всю строку от левого до правого края. Хорошо для газетных колонок.
.gr-text-start
Выравнивание по началу строки. Здесь, в русском тексте, — слева; в блоке с dir="rtl" тот же класс выровняет текст справа.
.gr-text-start в dir="rtl"
النص محاذى إلى بداية السطر — على اليمين في الكتابة من اليمين إلى اليسار.

Трансформация

КлассЗначение
.gr-uppercasetext-transform: uppercase
.gr-lowercasetext-transform: lowercase
.gr-capitalizetext-transform: capitalize
<span class="gr-uppercase">все буквы заглавные</span>
<span class="gr-lowercase">ВСЕ БУКВЫ СТРОЧНЫЕ</span>
<span class="gr-capitalize">каждое слово с заглавной</span>
Результат
.gr-uppercase

griffincss typography module — все буквы заглавные

.gr-lowercase

GRIFFINCSS TYPOGRAPHY MODULE — ВСЕ БУКВЫ СТРОЧНЫЕ

.gr-capitalize

griffincss typography module — каждое слово с заглавной

Межстрочный интервал

5 значений line-height.

КлассЗначениеПрименение
.gr-leading-tight1.25Крупные заголовки
.gr-leading-snug1.375Подзаголовки
.gr-leading-normal1.5Основной текст
.gr-leading-relaxed1.625Длинные тексты, статьи
.gr-leading-loose2Разреженный текст, поэзия
<p class="gr-text-sm gr-leading-tight">Плотный интервал — для заголовков</p>
<p class="gr-text-sm gr-leading-normal">Нормальный интервал — для основного текста</p>
<p class="gr-text-sm gr-leading-loose">Свободный интервал — для разреженного текста</p>
Результат
.gr-leading-tight (1.25)

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

.gr-leading-normal (1.5)

Нормальный межстрочный интервал — стандарт для основного текста. Обеспечивает комфортное чтение. Несколько строк с нормальным интервалом.

.gr-leading-loose (2)

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

Текстовый декор

КлассЗначение
.gr-underlinetext-decoration: underline
.gr-no-underlinetext-decoration: none
.gr-line-throughtext-decoration: line-through
.gr-italicfont-style: italic
.gr-not-italicfont-style: normal
.gr-tabular-numsfont-variant-numeric: tabular-nums — цифры одной ширины, разряды в колонке чисел стоят друг под другом
<span class="gr-underline">Подчёркнутый текст</span>
<span class="gr-line-through">Зачёркнутый текст</span>
<em>Курсив, и только <span class="gr-not-italic">эта часть</span> прямая</em>
<span class="gr-italic">Курсивный текст</span>
<a class="gr-no-underline">Ссылка без подчёркивания</a>
Результат
.gr-underline

Подчёркнутый текст — для ссылок и акцентов

.gr-line-through

Зачёркнутый текст — старая цена, удалённое

.gr-italic

Курсивный текст — цитаты, термины, акцент

.gr-not-italic

Весь этот текст в <em> — курсив, и только эти три слова выпрямлены

.gr-tabular-nums

1 111 111 ₽ и 8 888 888 ₽ — одной ширины; в колонке сумм таблицы разряды не гуляют

Переносы и пробелы

КлассСвойства
.gr-break-wordsoverflow-wrap: break-word
.gr-truncateoverflow: hidden; text-overflow: ellipsis; white-space: nowrap
.gr-whitespace-nowrapwhite-space: nowrap
.gr-whitespace-prewhite-space: pre
.gr-whitespace-normalwhite-space: normal
<p class="gr-break-words">
  ДлинныйURLилиСловоБезПробеловКотороеНеПомещаетсяВКонтейнер
</p>

<p class="gr-truncate">
  Очень длинный текст который обрезается многоточием когда не помещается в одну строку
</p>
Результат
.gr-break-words

SuperLongUnbreakableWordWithoutSpacesThatWrapsAutomatically

.gr-truncate

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

.gr-whitespace-nowrap

Текст не переносится на новую строку никогда

Перенос строк

КлассCSSГде уместен
.gr-text-balancetext-wrap: balanceЗаголовки: браузер выравнивает длину строк, последняя не остаётся из одного слова
.gr-text-prettytext-wrap: prettyАбзацы: убираются висячие слова в конце

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

<h2 class="gr-text-balance">Заголовок в две строки, разбитый поровну</h2>
<p class="gr-text-pretty">Длинный абзац без висячих слов…</p>

Обрезка по числу строк

.gr-line-clamp-{1…6} обрезает текст после указанного числа строк и ставит многоточие. В отличие от .gr-truncate, который работает только на одной строке, здесь текст переносится нормально.

КлассРезультат
.gr-line-clamp-1.gr-line-clamp-6Не больше N строк, дальше — многоточие
.gr-line-clamp-noneСнять обрезку
.gr-line-clamp-2 в карточке

Заголовок карточки

Описание товара, которое в исходнике занимает четыре строки, а в карточке должно занимать ровно две — иначе карточки в ряду разъедутся по высоте и сетка перестанет читаться как сетка. Вот эта часть текста уже не видна.

<p class="gr-line-clamp-2">Описание товара…</p>

Списки

Ресет снимает маркеры только со списков, размеченных как role="list" — обычный <ul> в тексте сохраняет и маркеры, и отступ. Эти классы меняют оформление там, где разметку трогать нельзя.

КлассCSS
.gr-list-nonelist-style: none; padding-inline-start: 0
.gr-list-disclist-style: disc
.gr-list-decimallist-style: decimal
.gr-list-insidelist-style-position: inside
.gr-list-outsidelist-style-position: outside

Безусловный list-style: none лишает <ul> роли списка в VoiceOver, а вместе с ней — озвучки «список из N элементов». Атрибут role="list" возвращает роль, оставляя оформление снятым: <ul role="list" class="gr-flex gr-gap"> — то, что нужно навигации.

Шрифтовые семейства

Три класса, ссылающиеся на CSS-переменные --gr-font-*. Переопределите переменные для кастомных шрифтов.

КлассЗначение
.gr-font-sansvar(--gr-font-sans)
.gr-font-serifvar(--gr-font-serif)
.gr-font-monovar(--gr-font-mono)
<p class="gr-font-sans">system-ui, -apple-system, sans-serif</p>
<p class="gr-font-serif">Georgia, Cambria, serif</p>
<p class="gr-font-mono">SFMono-Regular, Menlo, Consolas, monospace</p>
Результат
.gr-font-sans

Griffincss — The quick brown fox jumps over the lazy dog. 1234567890.

.gr-font-serif

Griffincss — The quick brown fox jumps over the lazy dog. 1234567890.

.gr-font-mono

Griffincss — The quick brown fox jumps over the lazy dog. 1234567890.

Адаптивные варианты

Классы выше имеют варианты с суффиксом брейкпоинта: -sm (≥640px), -md (≥768px), -lg (≥1024px), -xl (≥1280px). Размер шрифта, насыщенность, выравнивание, трансформация, интервал, декор, переносы и семейство — любые свойства можно менять на разных разрешениях. Исключение — относительные размеры .gr-text-rel-*: у них вариантов нет, размер там задаёт вложенность, а не ширина окна.

<!-- Базовый размер sm, от 768px становится lg, от 1024px — xl -->
<p class="gr-text-sm gr-text-lg-md gr-text-xl-lg">
  Адаптивный размер шрифта
</p>

<!-- На мобильных — по началу строки, от 1024px — по центру -->
<h2 class="gr-text-start gr-text-center-lg">
  Адаптивное выравнивание
</h2>

<!-- Нормальная насыщенность, от 768px — жирный -->
<span class="gr-font-normal gr-font-bold-md">
  Адаптивная насыщенность
</span>
Результат (измените ширину окна)
.gr-text-sm .gr-text-lg-md .gr-text-xl-lg

Этот текст меняет размер на разных разрешениях: 14px → 18px (≥768px) → 20px (≥1024px)

.gr-text-start .gr-text-center-lg
На мобильных — по началу строки. На десктопе (≥1024px) — по центру.
.gr-font-normal .gr-font-bold-md

Нормальная насыщенность на мобильных, жирный от 768px

SCSS-реализация

// _typography.scss — все утилиты генерируются циклами

// Размеры
$gr-text-sizes: (
  xs: 0.75rem, sm: 0.875rem, base: 1rem,
  lg: 1.125rem, xl: 1.25rem, 2xl: 1.5rem,
  3xl: 1.875rem, 4xl: 2.25rem, 5xl: 3rem, 6xl: 3.75rem
);
@each $name, $size in $gr-text-sizes {
  .gr-text-#{$name} { font-size: $size; }
}

// Относительные размеры — шаг в px от текущего размера
$gr-text-rel-steps: (
  xs: -4px, sm: -2px, lg: 2px,
  xl: 4px, 2xl: 6px, 3xl: 8px
);
@each $gr-name, $gr-delta in $gr-text-rel-steps {
  .gr-text-rel-#{$gr-name} {
    @if $gr-delta < 0 {
      font-size: calc(1em - #{math.abs($gr-delta)});
    } @else {
      font-size: calc(1em + #{$gr-delta});
    }
  }
}

// Насыщенность
$gr-weights: (
  "thin": 100, "extralight": 200, "light": 300,
  "normal": 400, "medium": 500, "semibold": 600,
  "bold": 700, "extrabold": 800, "black": 900
);
@each $name, $weight in $gr-weights {
  .gr-font-#{$name} { font-weight: $weight; }
}

// Адаптивные варианты генерируются для всех групп
@each $bp-name, $bp-value in $gr-breakpoints {
  @media (width >= $bp-value) {
    @each $name, $size in $gr-text-sizes {
      .gr-text-#{$name}-#{$bp-name} { font-size: $size; }
    }
    // ... остальные группы аналогично
  }
}

Советы

Комбинируйте классы. gr-text-lg gr-font-bold gr-leading-tight — три класса дают готовый заголовок. Не нужно писать отдельные CSS-правила для каждого элемента.

Переопределяйте переменные. Хотите кастомный шрифт? --gr-font-sans: 'Inter', sans-serif; на :root — и все .gr-font-sans подхватят его автоматически.

Аккуратно с gr-truncate. Класс обрезает текст и скрывает его. Не используйте на элементах, где важна полная доступность контента. Для многострочного усечения есть .gr-line-clamp-1…6 — см. «Обрезка по числу строк».

Примеры использования

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

Hero: заголовок, подводка, кнопки

Первый экран лендинга держится на контрасте трёх ступеней. Заголовок — крупный и плотный: .gr-text-4xl .gr-text-5xl-md (на телефоне меньше), .gr-font-extrabold, .gr-leading-tight, а .gr-text-balance просит браузер разбить строки поровну, чтобы последняя не осталась из одного слова. Ключевое слово выделяется простым span с .gr-text-primary — градиентной заливки текста в библиотеке нет, акцент делается цветом. Подводка — тише и ýже: .gr-text-lg .gr-text-ink-secondary с пределом .gr-max-w-[55ch], чтобы строка оставалась читаемой. Ряд кнопок — .gr-flex .gr-gap-sm .gr-flex-center.

<section class="gr-text-center gr-py-12">
  <h1 class="gr-text-4xl gr-text-5xl-md gr-font-extrabold gr-leading-tight gr-text-balance gr-mb-4">
    Вёрстка <span class="gr-text-primary">без борьбы</span> с CSS
  </h1>
  <p class="gr-text-lg gr-text-ink-secondary gr-text-pretty gr-max-w-[55ch] gr-mx-auto gr-mb-6">
    Модульная библиотека утилит: подключаете только нужное,
    собираете интерфейс из готовых классов.
  </p>
  <div class="gr-flex gr-gap-sm gr-flex-center">
    <button class="gr-btn gr-btn-primary gr-btn-lg">Начать</button>
    <button class="gr-btn gr-btn-ghost gr-btn-lg">Документация</button>
  </div>
</section>
Hero: контраст ступеней .gr-text-* + .gr-text-balance на заголовке

Вёрстка без борьбы с CSS

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

Список фич с галочками

Список преимуществ в прайсинге или feature-секции — это <ul role="list"> (ресет снимает маркеры, роль остаётся для скринридеров), где каждый пункт — мини медиа-объект: .gr-flex .gr-gap-sm .gr-flex-items-start. Галочка — обычный символ с .gr-text-success .gr-font-bold; выравнивание по верху не даёт второй строке текста залезть под неё. Текст пунктов приглушён токеном .gr-text-ink-secondary — цвет чернил из темы, а не серый из палитры.

<ul role="list" class="gr-flex gr-flex-col gr-gap-sm">
  <li class="gr-flex gr-gap-sm gr-flex-items-start">
    <span class="gr-text-success gr-font-bold">✓</span>
    <span class="gr-text-ink-secondary">Все модули независимы</span>
  </li>
  <li class="gr-flex gr-gap-sm gr-flex-items-start">
    <span class="gr-text-success gr-font-bold">✓</span>
    <span class="gr-text-ink-secondary">Тёмная тема из коробки</span>
  </li>
</ul>
Пункт = .gr-flex .gr-gap-sm .gr-flex-items-start, галочка не пускает текст под себя
  • Все модули независимы — подключается только нужное
  • Тёмная тема из коробки: цвета — токены, а не константы, и длинный пункт списка переносится ровно по своей вертикали, не залезая под галочку
  • Логические свойства для RTL

Цитата с цветной линией

Редакционная цитата собирается из трёх модулей: линия слева — .gr-border-s-4 .gr-border-primary из бордеров (логическая сторона s — в RTL линия сама перейдёт направо), воздух от линии — .gr-ps-4 из спейсинга, а голос цитаты — курсив .gr-italic с укрупнённым .gr-text-lg. Подпись автора — ступенькой ниже и тише: .gr-text-sm .gr-text-ink-secondary .gr-not-italic, чтобы выйти из курсива родителя.

<blockquote class="gr-border-s-4 gr-border-primary gr-ps-4 gr-italic gr-text-lg">
  <p class="gr-mb-2">Хорошая типографика незаметна — замечают только плохую.</p>
  <footer class="gr-not-italic gr-text-sm gr-text-ink-secondary">— Анна Ковалёва, дизайнер</footer>
</blockquote>
Цитата: бордер + отступ + курсив; подпись выходит из курсива через .gr-not-italic

Хорошая типографика незаметна — замечают только плохую.

— Анна Ковалёва, дизайнер

Статистика крупными цифрами

Stats-секция строится на контрасте кеглей в паре «число — подпись»: число в три-четыре раза крупнее (.gr-text-4xl .gr-font-extrabold), подпись — мелкая и разреженная (.gr-text-xs .gr-uppercase .gr-text-ink-secondary). Ряд из трёх пар держит грид .gr-grid-1 .gr-grid-3-sm. Утилиты табличных цифр в библиотеке нет: она нужна только «тикающим» счётчикам, а там font-variant-numeric: tabular-nums задаётся обычным CSS.

<div class="gr-grid-1 gr-grid-3-sm gr-gap gr-text-center">
  <div>
    <p class="gr-m-0 gr-text-4xl gr-font-extrabold gr-text-primary">12 000+</p>
    <p class="gr-m-0 gr-mt-1 gr-text-xs gr-uppercase gr-text-ink-secondary">Проектов</p>
  </div>
  …
</div>
Пара «число — подпись»: контраст кеглей делает всю работу

12 000+

Проектов

99,9 %

Аптайм

4,8

Средняя оценка

Карточка статьи: рубрика, анонс, метастрока

Карточка блога — концентрат модуля: рубрика-надзаголовок (.gr-text-xs .gr-uppercase .gr-font-semibold цветом акцента), заголовок с плотным интервалом, анонс, обрезанный на второй строке .gr-line-clamp-2, — благодаря ему карточки в сетке остаются одной высоты. Метастрока внизу — флекс с аватаром из ui и разделителями: мелкий кегль и приглушённый цвет отделяют служебное от главного.

<article>
  <span class="gr-text-xs gr-uppercase gr-font-semibold gr-text-accent">Дизайн</span>
  <h3 class="gr-text-2xl gr-font-bold gr-leading-tight gr-mt-2 gr-mb-3">
    Как типографика влияет на восприятие
  </h3>
  <p class="gr-line-clamp-2 gr-text-sm gr-text-ink-secondary">Анонс, обрезанный на второй строке…</p>
  <footer class="gr-flex gr-flex-items-center gr-gap-sm gr-mt-4 gr-text-xs gr-text-ink-secondary">
    <span class="gr-avatar gr-avatar-sm">ИП</span>
    <span class="gr-font-medium">Иван Петров</span>
    <span>·</span>
    <span>5 мин чтения</span>
  </footer>
</article>
Анонс держит .gr-line-clamp-2 — карточки в сетке не разъезжаются
Дизайн

Как типографика влияет на восприятие

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

ИП Иван Петров · 5 мин чтения

Ценовой блок: цена, старая цена, размер скидки

Три величины в одной строке, и каждая своим приёмом. Цена — крупная и плотная: .gr-text-3xl .gr-font-bold .gr-leading-tight. Старая — тише и зачёркнута: <s> с .gr-line-through .gr-text-ink-secondary. Размер скидки — плашка .gr-badge .gr-badge-danger, то есть слово «−25 %», а не только красный цвет. Ряд — .gr-flex с выравниванием по базовой линии: цифры разного кегля обязаны стоять на одной линии, а не по центру своих коробок.

<s>, а не <span>: элемент означает «уже не актуально» — ровно то, что случилось со старой ценой. Зачёркивание при этом остаётся признаком для глаза, поэтому перед числом стоит .gr-sr-only со словом «старая цена»: скринридер линию не объявляет, и без него обе цены прозвучали бы подряд без разницы.

<p class="gr-flex gr-flex-items-baseline gr-flex-wrap gr-gap-sm gr-m-0">
  <span class="gr-text-3xl gr-font-bold gr-leading-tight">12 990 ₽</span>
  <s class="gr-line-through gr-text-ink-secondary">
    <span class="gr-sr-only">Старая цена </span>17 320 ₽
  </s>
  <span class="gr-badge gr-badge-danger">−25 %</span>
</p>
Кегль, приглушённый цвет и плашка — три разных приёма на трёх величинах

12 990 ₽ Старая цена 17 320 ₽ −25 %

2 450 ₽ за упаковку

Классов .gr-price и .gr-price-old здесь нет намеренно. Обе строки собираются из кегля, веса, цвета чернил и плашки — всё это уже есть и работает в обеих темах. Новое имя не добавило бы ни одного свойства, зато завело бы второй способ сказать «крупный полужирный текст» и потребовало бы решать, что такое цена в валюте без копеек, в рассрочку и за килограмм.