diff --git a/src/pages/css/index.md b/src/pages/css/index.md index 2d19d6d..c5eb288 100644 --- a/src/pages/css/index.md +++ b/src/pages/css/index.md @@ -5489,9 +5489,48 @@ CSS methodology — это набор правил для организации **Полный ответ** -CSS methodology — это набор правил для организации CSS: например BEM, SMACSS, OOCSS, CSS Modules или utility-first -подход. Методология помогает договориться, как называть классы, где хранить styles и как ограничивать область влияния. -Важно не название методологии, а консистентность, понятные границы и documented exceptions. +CSS methodology — это не конкретная библиотека, а **командный contract** о том, как строить и изменять styles так, чтобы +локальное изменение не превращалось в поиск случайных overrides по всему приложению. + +Методология обычно отвечает сразу на несколько вопросов: + +- как именовать classes и состояния; +- где проходит boundary component/feature/global styles; +- как переиспользовать declarations и composition; +- какой уровень specificity считается нормальным; +- где допустимы global rules; +- как оформлять variants, themes и responsive states; +- как подключать third-party styles и делать исключения. + +Например, BEM делает связь block/element/modifier явной через имена: + +```css +.user-card { +} + +.user-card__title { +} + +.user-card--compact { +} +``` + +CSS Modules решают другую часть той же задачи — автоматически делают class names локальными для module. Utility-first +подход переносит значительную часть composition в markup. Эти подходы **не взаимоисключающие**: проект может +использовать CSS Modules для isolation, design tokens для values и utilities для частых layout primitives. + +Главная польза methodology проявляется не на первом компоненте, а после сотен изменений. Она снижает число неявных +зависимостей и дает разработчику ответ на вопрос: «куда положить style и чем я имею право его переопределить?». + +Но слишком жесткая методология тоже вредна. Если правило заставляет писать сложнее без реальной защиты invariant, +команда начинает обходить его через исключения. Поэтому полезнее небольшой набор проверяемых principles, чем десятки +naming rules без объяснения причин. + +Часть соглашений можно автоматизировать: stylelint, lint rules, code review, project boundaries. Остальное должно быть +описано как архитектурное решение с примерами и допустимыми exceptions. + +На интервью: **CSS methodology — это способ контролировать naming, scope, composition и cascade в большой кодовой базе; +ценность не в названии BEM/SMACSS, а в предсказуемости изменений и явных boundaries**. @@ -5509,9 +5548,66 @@ truth и преобразуют в CSS custom properties, platform constants и **Полный ответ** -Tokens — именованные design decisions: colors, spacing, typography, radii, motion. Их хранят в нейтральном source of -truth и преобразуют в CSS custom properties, platform constants и design-tool variables. Семантические tokens вроде -`--color-danger` устойчивее прямых названий оттенков. +Design tokens — это **именованные design decisions**, которые отделяют смысл значения от конкретной реализации. Вместо +того чтобы каждый component знал конкретный hex, radius или duration, он использует token с понятной ролью. + +Обычно выделяют несколько уровней. + +Primitive tokens описывают палитру/шкалу: + +```css +:root { + --blue-600: #2563eb; + --space-2: 0.5rem; +} +``` + +Semantic tokens описывают назначение: + +```css +:root { + --color-text-primary: #111827; + --color-action-primary: var(--blue-600); + --space-control-gap: var(--space-2); +} +``` + +Component может использовать именно semantic contract: + +```css +.button { + color: white; + background: var(--color-action-primary); + gap: var(--space-control-gap); +} +``` + +Это позволяет theme поменять palette, не переписывая component rules: + +```css +[data-theme='dark'] { + --color-text-primary: #f9fafb; + --color-action-primary: #60a5fa; +} +``` + +Важно: **token не равен CSS custom property**. Source of truth может храниться в JSON/дизайн-системе, а build pipeline +преобразует tokens в CSS variables, Sass values, Android/iOS constants или variables дизайн-инструмента. DTCG также +определяет vendor-neutral формат обмена tokens и aliases между инструментами. + +Aliases полезны, когда semantic token ссылается на primitive: `action.primary` может указывать на `palette.blue.600`. +Тогда смена brand palette не требует искать raw color по всему продукту. + +Антипаттерн — дать компонентам напрямую использовать только primitives вроде `--blue-600`. Такой код знает **как +выглядит** значение, но не **зачем оно нужно**, поэтому theme/refactoring сложнее. Другая крайность — создать token для +каждого одиночного числа и получить тысячи неуправляемых names. + +Хорошая token architecture фиксирует ownership и уровни: primitives → semantic decisions → при необходимости +component-specific tokens. + +На интервью: **design token — это переносимое именованное design decision; CSS custom property лишь один из возможных +runtime outputs. Semantic tokens уменьшают связь component с конкретной palette и упрощают themes/multi-platform design +systems**. @@ -5528,8 +5624,63 @@ Cascade layers задают явный порядок групп styles до с **Полный ответ** -Cascade layers задают явный порядок групп styles до сравнения specificity. Например, `reset`, `base`, `components` и -`utilities` можно упорядочить один раз, уменьшая войны selectors и `!important`. +Cascade layers позволяют явно задать **порядок приоритета групп author styles до сравнения specificity**. + +Например: + +```css +@layer reset, base, components, utilities, overrides; + +@layer components { + .button { + color: blue; + } +} + +@layer utilities { + .text-danger { + color: red; + } +} +``` + +Для обычных declarations более поздний layer имеет больший приоритет. Поэтому `.text-danger` из `utilities` может +победить `.button` из `components`, даже если selectors имеют одинаковую или меньшую specificity. Specificity +сравнивается уже **внутри одного cascade layer bucket**, а не между слоями. + +Это полезно для architecture: вместо гонки `.page .dialog .button.primary` можно заранее решить, какие группы styles +имеют право переопределять другие. + +Third-party CSS удобно намеренно опустить в ранний layer: + +```css +@import url('vendor.css') layer(vendor); + +@layer vendor, base, components, utilities; +``` + +Тогда собственные component styles могут переопределять library styles без искусственного повышения specificity. + +Есть два важных edge cases. + +**Unlayered normal styles** находятся после named layers и имеют больший приоритет, поэтому случайный global rule вне +`@layer` способен обойти всю layer architecture. + +Для `!important` порядок **инвертируется**: important declarations в более ранних layers имеют больший приоритет, а +layered important declarations побеждают unlayered important. Это сделано, чтобы ранний защитный layer мог сохранять +важные invariants и чтобы `!important` не превращался просто в «еще один поздний override». + +Порядок layer определяется моментом его первого создания. Поэтому его обычно объявляют один раз в начале: + +```css +@layer reset, base, components, utilities, overrides; +``` + +`@layer` не заменяет component isolation и не отменяет необходимость разумной specificity. Он решает другой уровень +задачи — **какая группа styles сильнее другой**. + +На интервью: **cascade layers добавляют явную ось приоритета между origin/importance и specificity; для normal rules +позже = сильнее, для important порядок layers обратный**. @@ -5547,9 +5698,73 @@ Shadow DOM создает отдельное tree boundary: обычные docum **Полный ответ** -Shadow DOM создает отдельное tree boundary: обычные document selectors не проникают внутрь, а внутренние styles не -выходят наружу. Наследуемые properties, CSS custom properties, `::part` и `::slotted` формируют контролируемые точки -настройки. +Shadow DOM создает отдельный **tree/style boundary**. Обычные selectors из document не выбирают descendants внутри +shadow tree, а внутренние selectors не начинают внезапно матчить элементы снаружи. + +```js +const root = element.attachShadow({mode: 'open'}); +root.innerHTML = ` + +