Skip to content
This page is not translated yet — the Russian text is shown.Open the Russian version

4. Стили и токены ​

Сюда попадают изменения CSS-токенов (2 уровня), CSS Layers (ITCSS), интеграции с Tailwind, публичных импортов ./styles/....

Цвета в CSS-переменных — готовые значения, а не каналы RGB ​

⚠️ BREAKING — --cds-color-* и --cds-alpha-* хранят готовый цвет (у встроенных тем — oklch()), обёртка rgb() делает свойство невалидным.

Было (CDS 3):

scss
// CDS 3
.my-block {
  color: rgb(var(--cds-color-content-primary));
  background: rgb(var(--cds-color-fill-secondary), 0.4);
}

Стало (CDS 4):

scss
// CDS 4
.my-block {
  color: var(--cds-color-content-primary);
  background: color-mix(in srgb, var(--cds-color-fill-secondary) 40%, transparent);
}

Действие: заменить rgb(var(--cds-X)) / rgba(var(--cds-X)) на var(--cds-X), альфу поверх — на color-mix(…, transparent). Замену делает скилл cds-migrate (LDS-218); проверка — grep -rnE "rgba?\(\s*var\(--cds-" src пуст. Своя тема может задавать цвета в hex, rgb() или oklch() — значение попадёт в CSS как написано. Палитра-примитивы (utils/colors) удалена.

Изменён путь импорта CSS ​

⚠️ BREAKING — собранный dist/cds.css больше не является публичной точкой входа.

Было (CDS 3):

ts
// CDS 3
import '@central-design-system/components/dist/cds.css';

Стало (CDS 4):

ts
// CDS 4
import '@central-design-system/components/styles';

Действие: заменить во всех приложениях-потребителях импорт @central-design-system/components/dist/cds.css на @central-design-system/components/styles. Поиск: grep -rn "@central-design-system/components/dist/cds.css" ..

Legacy reset вынесен в опциональный флаг ​

⚠️ BREAKING — styles/utilities/legacy/legacy.scss теперь содержит только утилитарные классы (display / layout / spacing / flexbox / typography); глобальный reset из CDS 3 больше не подключается по умолчанию.

Было (CDS 3):

scss
// CDS 3 — legacy.scss тянул за собой полный глобальный reset
// (box-sizing, обнуление margin, list-style, media-query'и и т.д.)
// автоматически при подключении стилей CDS.
@use '@central-design-system/components/styles';

Стало (CDS 4):

scss
// CDS 4 — legacy.scss содержит только утилиты; старый reset вынесен
// в generic/_legacy-reset.scss и выключен по умолчанию.
// Чтобы вернуть поведение CDS 3, передайте $legacy-reset через with():
@use '@central-design-system/components/styles' with (
  $legacy-reset: true
);

Действие: если приложение полагалось на глобальный reset из CDS 3 (обнулённые margin, list-style: none, box-sizing: border-box на * и т.д.) — включите его явно через $legacy-reset: true в settings (см. src/styles/settings/_variables.scss). Иначе — проверьте вёрстку и доверьтесь нативным дефолтам браузера.

CSS-архитектура переписана на ITCSS + CSS Layers ​

⚠️ BREAKING — порядок каскада теперь определяется нативными @layer. Глобальные переопределения стилей CDS, написанные без !important, могут сработать иначе.

Было (CDS 3):

scss
// CDS 3 — плоская структура без cascade layers.
// Все стили компонентов и утилит грузились в обычный каскад,
// побеждал последний по специфичности / порядку импорта.
@import '@central-design-system/components/dist/cds.css';

// Переопределение приходилось делать через повышение специфичности
// или !important:
.cds-button { color: red !important; }

Стало (CDS 4):

scss
// CDS 4 — ITCSS + нативные CSS Layers.
// Каскад: cds-core → cds-components → cds-overrides → cds-utilities,
// см. src/styles/generic/_layers.scss.
@use '@central-design-system/components/styles';

@layer cds-overrides {
  .cds-button { color: red; }
}

Действие: ознакомиться с ITCSS и порядком слоёв в src/styles/generic/_layers.scss (cds-core → cds-components → cds-overrides → cds-utilities c вложенными theme-base, helpers, grid, tailwind, theme-background, theme-foreground). Проверьте свои глобальные переопределения CDS — если они были написаны без !important и полагались на порядок импорта, теперь они гарантированно перебивают @layer cds-components. Для контролируемого переопределения используйте слой cds-overrides (через @include tools.layer('overrides') { … }) — он специально расположен между компонентами и утилитами.

Утилитарные классы CDS 3 отключены по умолчанию ​

⚠️ BREAKING — классы cds-flex, cds-flex-col, cds-px-4, cds-my-*, цветов, типографики и т. п. больше не подключаются автоматически.

Было (CDS 3):

ts
// CDS 3
import '@central-design-system/components/dist/cds.css';
import { createCds } from '@central-design-system/components';

app.use(createCds());
vue
<!-- CDS 3 -->
<div class="cds-flex cds-flex-col cds-px-4">…</div>

Стало (CDS 4):

ts
// CDS 4 — временно включить легаси-утилиты на период миграции
import '@central-design-system/components/styles';
import '@central-design-system/components/styles/legacy';
import { createCds } from '@central-design-system/components';

app.use(createCds({
  theme: { legacyClasses: true },
}));

Действие: мигрировать на Tailwind CSS v4 (см. запись «Интеграция с Tailwind CSS v4» ниже). На переходный период включите легаси-утилиты комбинацией theme: { legacyClasses: true } в createCds() + импорт @central-design-system/components/styles/legacy. Источник: src/styles/utilities/legacy/legacy.scss (display, layout, spacing, flexbox, typography).

Интеграция с Tailwind CSS v4 ​

✨ NEW — CDS из коробки поставляет конфигурацию Tailwind v4 с design-токенами как утилитарными классами.

Было (CDS 3):

vue
<!-- CDS 3 — собственные утилитарные классы CDS -->
<div class="cds-flex cds-flex-col cds-px-4 cds-text-surface-primary">…</div>

Стало (CDS 4):

css
/* CDS 4 — main.css */
@import "@central-design-system/components/styles/tailwind";
@import "tailwindcss/theme" layer(cds-utilities.tailwind);
@import "tailwindcss/utilities" layer(cds-utilities.tailwind);
vue
<!-- CDS 4 — Tailwind v4 + CDS-токены как утилиты -->
<div class="flex flex-col p-4 text-surface-primary">…</div>

Действие: установить Tailwind CSS v4 по официальной документации и подключить конфигурацию @central-design-system/components/styles/tailwind — она расширяет тему Tailwind токенами CDS (bg-surface-*, text-content-*, rounded-200, …) и автоматически реагирует на смену темы. Отступы пишутся стандартной числовой шкалой Tailwind (p-4, gap-2) — шкала отступов CDS с ней совпадает.

Семантика миксина cds-breakpoint-down выровнена с JS useDisplay ​

⚠️ BREAKING — в CDS 3 SCSS-миксин cds-breakpoint-down($name) следовал конвенции «строго ниже начала брейкпоинта», а JS-composable useDisplay — конвенции «брейкпоинт и всё, что ниже». Из-за этого cds-breakpoint-down('sm') и display.smDown покрывали разные диапазоны (сдвиг на один брейкпоинт). В CDS 4 CSS выровнен под JS: down('<name>') теперь означает «<name> и ниже».

Было (CDS 3):

scss
// CDS 3 — max-width = ширина САМОГО брейкпоинта − 0.02 («строго ниже sm»)
// down('sm')  → @media (max-width: 671.98px)   // только диапазон xs
// down('md')  → @media (max-width: 1055.98px)  // xs + sm
// down('lg')  → @media (max-width: 1311.98px)  // xs + sm + md
// НЕ совпадает с JS: display.smDown === (width < 1056)
.card { @include cds-breakpoint-down(sm) { display: none; } }

Стало (CDS 4):

scss
// CDS 4 — max-width = ширина СЛЕДУЮЩЕГО брейкпоинта − 0.02 («sm и ниже»)
// down('sm')  → @media (max-width: 1055.98px)  // xs + sm
// down('md')  → @media (max-width: 1311.98px)  // xs + sm + md
// down('lg')  → @media (max-width: 1583.98px)  // xs + sm + md + lg
// down('xl')  → без media query (все ширины)
// Совпадает с JS: display.smDown === (width < 1056)
.card { @include cds-breakpoint-down(sm) { display: none; } }

Действие: пройтись по использованиям cds-breakpoint-down(...) (и cds-breakpoint-between(...) с именованной нижней/верхней границей — она делегирует в тот же миксин). Если код полагался на старую логику «строго ниже названного брейкпоинта», сдвиньте аргумент на один вниз: старый down('md') ⇒ новый down('sm'), старый down('lg') ⇒ down('md') и т. д. Миксины cds-breakpoint-up / значения порогов (320 / 672 / 1056 / 1312 / 1584) не менялись. Поиск: grep -rnE "cds-breakpoint-down\(" src/.

Сетка и брейкпоинты заданы в px вместо rem ​

⚠️ BREAKING — в CDS 3 вся геометрия сетки ($grid-gutter, margin и width брейкпоинтов) прогонялась через convert.toRem и зависела от размера корневого шрифта. В CDS 4 значения намеренно заданы в px: каркас страницы не зависит от html { font-size } хоста, а CSS-медиазапросы гарантированно совпадают с px-порогами JS-композабла useDisplay (rem в медиазапросах считается от настройки шрифта браузера и расходится с window.innerWidth).

Было (CDS 3):

scss
// CDS 3 — rem от корневого шрифта: хост с html { font-size: 14px }
// получал gutter 28px вместо 32px, а rem-медиазапросы срабатывали
// не там, где JS-логика в px
$grid-gutter: convert.toRem(32px); // 2rem
$grid-breakpoints: (
  sm: (columns: 8, margin: convert.toRem(16px), width: convert.toRem(672px)),
  // …
);

Стало (CDS 4):

scss
// CDS 4 — px: геометрия сетки стабильна в любом хосте и совпадает
// с порогами useDisplay (320 / 672 / 1056 / 1312 / 1584)
$grid-gutter: 32px;
$grid-breakpoints: (
  sm: (columns: 8, margin: 16px, width: 672px),
  // …
);

Действие: в большинстве приложений ничего делать не нужно — браузерный зум масштабирует px-макет целиком. Если хост менял html { font-size } в расчёте на масштабирование сетки, этот механизм больше не работает: сетка и брейкпоинты фиксированы, масштабируемый слой — rem-токены --cds-spacing-* (отступы контента и типографика).

Переменные $standard-easing / $decelerated-easing / $accelerated-easing удалены ​

⚠️ BREAKING — кривые Material 2 из settings заменены кривыми шкалы движения Luma: standard, enter, exit. Вместе с ними из tools убраны $cds-duration-*, get-motion и cds-animation-motion.

Было (CDS 3):

scss
// CDS 3
@use '@central-design-system/components/styles/settings';

.panel {
  transition: transform 300ms settings.$decelerated-easing;
}

.panel--closing {
  transition: transform 200ms settings.$accelerated-easing;
}

Стало (CDS 4):

scss
// CDS 4
@use '@central-design-system/components/styles/motion';

.panel {
  transition: transform motion.duration(normal) motion.easing(enter);
}

.panel--closing {
  transition: transform motion.duration(fast) motion.easing(exit);
}

Действие: убрать $standard-easing, $decelerated-easing и $accelerated-easing из @use '…/styles/settings' with (…) и из styles.configFile vite-плагина: теперь это ошибка Sass (переменная не объявлена в модуле, переопределить её нельзя). Дальше заменить settings.$standard-easing на motion.easing(standard), $decelerated-easing (появление) на motion.easing(enter), $accelerated-easing (уход) на motion.easing(exit), а литеральные длительности — на motion.duration(<ступень>) (instant 50 … very-slow 500). Поиск: grep -rnE "standard-easing|decelerated-easing|accelerated-easing|cds-duration-|get-motion|cds-animation-motion" src/. Значения для JS — motion.easings.* и motion.durations.* из @central-design-system/components. Гайд — «Анимации».

Анимации компонентов переведены на шкалу движения Luma ​

✨ NEW — все анимации компонентов идут по одной шкале: семь длительностей и кривые standard / enter / exit вместо кривых Material 2. Публичные переменные вроде $select-transition или $badge-transition сохранили имя и форму значения (<длительность> <кривая>), поменялись значения по умолчанию. Не все $*-transition имеют такую форму: $list-subheader-transition, $responsive-sizer-transition и $progress-circle-overlay-transition перечисляют свойства.

Было (CDS 3):

scss
// CDS 3 — кривая Material 2 из settings
$select-transition: .2s settings.$standard-easing !default;

Стало (CDS 4):

scss
// CDS 4 — шкала Luma: ступень и кривая из модуля motion
@use '@central-design-system/components/styles/motion';

$select-transition: motion.duration(fast) motion.easing(standard);

Действие: миграция не требуется. Если вы переопределяли переменные $*-transition или подстраивали тайминги под старые кривые, сверьтесь с таблицами шкалы в гайде «Анимации» и по возможности берите ступени вместо литералов. Переходы CdsTransition*, модалка (появление normal вместо 225ms, уход fast), тултипы (появление fast вместо 100ms) и тосты перенесены на ступени шкалы: часть значений стала короче, часть длиннее, поэтому единой «скорости» у них больше нет. При prefers-reduced-motion сдвиг и масштаб заменяются затуханием, а декоративные полосы striped у CdsProgressBar останавливаются (цикл неопределённого прогресса идёт как раньше).

Форма значения у $list-subheader-transition (<длительность> min-height <кривая>), $responsive-sizer-transition (padding-bottom <длительность> <кривая>) и $progress-circle-overlay-transition (список из свойств) включает свойства. У последней переменной теперь три элемента вместо двух (stroke-dashoffset, stroke, stroke-width 0s), и CdsProgressCircle рассчитывает на три: переопределение из двух элементов, оставшееся от CDS 3, анимирует stroke-width во время появления круга. Переопределяйте её целиком, тремя элементами.

surface-overlay непрозрачный, подложку разбавляет компонент ​

⚠️ BREAKING — во всех темах --cds-color-surface-overlay стал непрозрачным: альфа (0.5 в светлых темах, 0.8 в тёмных) ушла из токена в компоненты. Это модель эталонной темы lumaLight.

Было (CDS 3):

scss
// CDS 3 — полупрозрачность приходила из токена
.my-backdrop {
  background: rgb(var(--cds-color-surface-overlay));
}

Стало (CDS 4):

scss
// CDS 4 — токен сплошной, долю задаёт потребитель
.my-backdrop {
  background: color-mix(in srgb, var(--cds-color-surface-overlay) 50%, transparent);
}

Действие: найти свои подложки на токене (grep -rn "surface-overlay" src) и разбавить их через color-mix(…, transparent) или opacity, иначе они закроют страницу сплошным цветом. Подложки CdsOverlay (модалки, диалоги), CdsDrawer, CdsLoader и кнопки CdsCarousel разбавляют токен сами, на общую долю $overlay-opacity (50%). У дровера она вынесена в $drawer-overlay-opacity. Вид меняется: подложка модалки в светлых темах темнее (50% вместо ~25%), подложки дровера и лоадера в тёмных темах светлее (50% вместо 80%).