Позвольте мне обрисовать вам картину: сейчас 3 часа ночи, ваш компонент React теряет стили, как зомби из «Ходячих мертвецов», и вы по уши в обёртках styled-component. Вдруг вас осеняет — возможно, CSS-in-JS не был той панацеей, которую обещали в статье на Medium с подозрительно идеальным примером кода. Добро пожаловать в мой мир, друг. Давайте разберёмся, когда CSS заслуживает своего места за столом взрослых.
Индустрия JavaScript объявляет очередную жертву
Я никогда не забуду тот день, когда я унаследовал кодовую базу, где для изменения цвета при наведении курсора на компонент кнопки потребовалось 17 вложенных ThemeProvider. Наша реализация CSS-in-JS стала программным эквивалентом матрешки, окунутой в эпоксидную смолу. Показатели производительности выглядели как проверка на полиграфе от неверного супруга.
// Место преступления:
<ThemeProvider theme={outerSpace}>
<ColorProvider palette={brandColors}>
<MobileFirstContext.Provider value={true}>
<Button
sx={{
'&:hover': {
color: 'inheritedFromSomewhereMaybe',
transform: 'rotateX(360deg)'
}
}}
/>
</MobileFirstContext.Provider>
</ColorProvider>
</ThemeProvider>
Вот как умирают благие намерения. Мы хотели иметь стили с ограниченной областью действия компонентов, но получили спагетти зависимостей. Пересчёты стилей в браузере заставили наше приложение работать медленнее, чем государственные сайты во время налогового сезона.
Когда простой CSS надевает плащ
Давайте пройдёмся по шумихе с помощью некоторых холодных и жёстких тестов из моего последнего проекта:
Показатель | CSS-модули | Стилизованные компоненты | Обычный CSS |
---|---|---|---|
FCP (мс) | 1200 | 2400 | 800 |
Размер пакета (КБ) | 150 | 210 | 90 |
Гидратация SSR | 1,2 с | 2,8 с | 0,4 с |
Увольнение разработчиков | 0 | 3 в неделю | 1 в месяц |
(Данные собраны из аудитов Lighthouse) Как только мы переключили основную разметку на CSS Grid с использованием собственных переменных, наш продуктовый менеджер заплакал от радости. Оказывается, браузеры отлично справляются с CSS, если мы позволяем им делать свою работу.
Возрождение каскада
Помните, когда мы все высмеивали CSS за его букву «К»? Оказывается, каскад похож на того странного дядюшку, который знает навыки выживания — он раздражает, пока не наступит конец света. Вот моя программа реабилитации каскадов из трёх шагов:
- Пространство имён со слоями
@layer base, components, utilities; @layer components { .card { /* изолированные стили */ } }
- Ограничьте ущерб
.user-profile { container-type: inline-size; /* Ваши стили не могут выйти за пределы этого Алькатраса */ }
- Переменные > Поставщики тем
:root { --accent-color: oklch(68.72% 0.147 358.04); } .callout { background: var(--accent-color); }
Нужна динамическая тематика? Вот интересный подход: пользовательские свойства CSS + classList.toggle() могут справиться с 90% случаев использования без загрузки среды выполнения CSS-in-JS размером 15 КБ.
Искусство стратегического отступления
Когда следует отказаться от CSS-in-JS? Давайте визуализируем:
Оказались в красной зоне? Вот как выбраться из чистилища CSS-in-JS:
- Создайте аварийный выход
npx codemod --parser css-modules --extensions js,jsx ./src
- Удалите стили времени выполнения
/* styles.module.css */ .enterpriseForm { --input-border: 2px solid; border: var(--input-border) hotpink; }
- Используйте PostCSS как талисман
// postcss.config.js module.exports = { plugins: { 'postcss-jit-props': {}, 'postcss-nesting': {}, 'cssnano': {} } }
Правдивая история: мы сократили количество ошибок, связанных со стилями, на 40%, перейдя от проверки состояния формы к чистым псевдоклассам CSS. Оказывается, :invalid работает лучше, чем отслеживание 15 полей формы с помощью React useEffect.
Парадокс обслуживания
Сторонники CSS-in-JS любят кричать «совмещение!», но видели ли вы оформленный компонент через 6 месяцев после добавления функций? Это всё равно что найти в своей кодовой базе гостевую книгу GeoCities 1998 года:
const StyledButton = styled(Button).attrs(({ theme }) => ({
// 😱 ПОЧЕМУ ЗДЕСЬ ЭМОДЗИ В ВИДЕ РЫБКИ?
hoverColor: theme.mode === 'dark' ? '#00ff9d' : '👩🍳'
}))`
background: ${p => p.hoverColor};
animation: ${pulse} 2s infinite;
${({ variant }) => variant === 'cta' && css`
box-shadow: 0 0 10px #ff00ff;
`}
`;
Сравните это с CSS-модулями, где вашим худшим грехом может быть слишком умное имя класса:
/* login.module.css */
.t-rex-theme-conqueror {
/* По крайней мере, это деградирует изящно */
background: linear-gradient(to right, #fff 0%, #dino-mix 100%);
}
Неприятная правда
После работы над 7+ производственными приложениями на 3 континентах (да, даже в Антарктиде теперь есть разработчики React), вот моё спорное мнение:
CSS-in-JS — это блокчейн разработки интерфейса — революционный для определённых вариантов использования, но катастрофический при неизбирательном применении. Давайте оставим CSS-in-JS для того, в чём он хорош: дизайн-системы со сложными динамическими требованиями, переключение тем в реальном времени и прототипирование. Для вашего маркетингового сайта, панели администратора или платформы с большим количеством контента — CSS не враг, а ваш друг, выпивший слишком много кофе, который доводит дело до конца. В следующий раз, когда кто-то потребует CSS-in-JS, потому что «это делает Facebook», напомните ему, что Марк Цукерберг тоже считал бежевый цвет хорошим для веб-сайта. Некоторые решения заслуживают тщательного изучения.
/* Потому что иногда нужно просто бросить микрофон */
.old-school-rules {
content: "🔥";
}