Как попадают стили из одного компонента в другой без Scope?
Компоненты
Стили «протекают» между компонентами, потому что в браузере CSS глобален по умолчанию: React никакой изоляции не добавляет.
Механика протечки
- Селектор
.button { … }из одного файла применяется ко всем.buttonна странице — независимо от того, какой компонент его объявил. - Импорт CSS-файла (
import './Card.css') лишь добавляет правила в общий документ; привязки к компоненту нет. - Каскад и специфичность: правила с большей специфичностью или объявленные позже перекрывают чужие — отсюда «почему у меня кнопка вдруг красная».
- Наследуемые свойства (font, color, line-height) передаются вниз по DOM-дереву от родителей.
- Глобальные и «дырявые» селекторы:
div > span, теговые селекторы,!important,:global.
Дополнительно про порядок
Порядок вставки <style>-тегов определяется сборщиком и порядком импортов — при одинаковой специфичности выигрывает последний. Отсюда нестабильные баги «в проде стили другие».
Как изолируют
- CSS Modules — классы хешируются (
.card__a1b2), коллизии исключены. - CSS-in-JS (styled-components/Emotion) — генерируемые уникальные классы.
- Tailwind — атомарные утилиты, конфликтов имён нет.
- BEM — дисциплина именования без инструментов.
- Shadow DOM — единственная настоящая браузерная изоляция (Web Components), в React используется редко (встраиваемые виджеты).
Что всё равно течёт
Глобальные стили (reset, typography), CSS-переменные (по замыслу), наследуемые свойства, стили из сторонних библиотек — их нужно контролировать осознанно.
Коротко для собеседования
React не изолирует CSS: правила глобальны, работают каскад, специфичность и наследование, а порядок импортов решает конфликты — отсюда протечки. Изоляция достигается инструментами (CSS Modules, CSS-in-JS, Tailwind, BEM); настоящая браузерная — только Shadow DOM. Глобальные стили и наследуемые свойства текут всегда.