← Назад к вопросам

Используешь ли scoped styles

2.0 Middle🔥 261 комментариев
#HTML и CSS#Оптимизация и производительность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Scoped Styles в современной разработке

Это отличный вопрос, так как выбор между scoped styles, CSS-in-JS и Tailwind определяет архитектуру стилей всего проекта.

Мой подход

В разных проектах используются разные подходы, в зависимости от требований:

1. Tailwind CSS (75% проектов)

В большинстве современных проектов использую Tailwind CSS. Это не scoped styles в классическом смысле, но обеспечивает аналогичный результат.

// components/Button.tsx
export function Button({ variant = 'primary', children }) {
  return (
    <button className={cn(
      "px-4 py-2 rounded-lg font-medium transition-colors",
      variant === 'primary' && "bg-blue-500 text-white hover:bg-blue-600",
      variant === 'secondary' && "bg-gray-200 text-gray-900 hover:bg-gray-300"
    )}>
      {children}
    </button>
  );
}

Преимущества:

  • Нет конфликтов имён классов
  • Предсказуемые стили
  • Легко переиспользовать компоненты
  • Отличная производительность
  • Utility-first подход

Недостатки:

  • Классы могут быть многословными
  • Требует привыкания к подходу
  • Не подходит для очень сложных анимаций

2. CSS Modules (15% проектов)

Для проектов, где нужна большая гибкость в стилях или работа с legacy кодом, использую CSS Modules.

/* styles/Button.module.css */
.button {
  padding: 0.5rem 1rem;
  border-radius: 0.5rem;
  font-weight: 500;
  transition: all 0.3s ease;
}

.primary {
  background-color: #3b82f6;
  color: white;
}

.primary:hover {
  background-color: #2563eb;
}
// components/Button.tsx
import styles from '@/styles/Button.module.css';

export function Button({ variant = 'primary', children }) {
  return (
    <button className={`${styles.button} ${styles[variant]}`}>
      {children}
    </button>
  );
}

Преимущества:

  • Истинные scoped styles (генерируются уникальные классы)
  • Разделение HTML и CSS
  • Легко работать с сложными селекторами
  • Типизация стилей в TypeScript

Недостатки:

  • Больше файлов (CSS + JS)
  • Сложнее с динамическими стилями
  • Нужно писать CSS

3. CSS-in-JS / Emotion (10% проектов)

Для сложных систем дизайна с динамическими стилями.

import { css } from '@emotion/react';
import styled from '@emotion/styled';

const buttonStyles = css`
  padding: 0.5rem 1rem;
  border-radius: 0.5rem;
  transition: all 0.3s ease;
  
  &:hover {
    opacity: 0.9;
  }
`;

const PrimaryButton = styled.button`
  ${buttonStyles}
  background-color: #3b82f6;
  color: white;
  
  &:hover {
    background-color: #2563eb;
  }
`;

export function Button({ children }) {
  return <PrimaryButton>{children}</PrimaryButton>;
}

Преимущества:

  • Полная мощь JavaScript в стилях
  • Динамические стили на основе пропсов
  • Автоматические префиксы
  • Оптимизация критического CSS

Недостатки:

  • Runtime overhead
  • Сложнее отлаживать
  • Медленнее, чем статические стили

Компаратив подходов

// Scenario: Кнопка с динамическим цветом

// Tailwind (рекомендуемый вариант)
const colorClass = {
  red: 'bg-red-500',
  blue: 'bg-blue-500',
  green: 'bg-green-500'
}[color] || 'bg-gray-500';

<button className={cn('px-4 py-2 rounded', colorClass)} />

// CSS Modules (не очень удобно для этого)
// Нужно предопределить все комбинации

// CSS-in-JS (оптимален для этого)
const StyledButton = styled.button`
  background-color: ${props => colorMap[props.color]};
`;
<StyledButton color="red" />

Лучшие практики для каждого подхода

Tailwind:

  • Используй cn() для условных классов
  • Создавай компоненты для повторяющихся комбинаций
  • Не переусложняй классы
import { cn } from '@/lib/utils';

export function Card({ variant = 'default', children }) {
  return (
    <div className={cn(
      'rounded-lg border',
      variant === 'default' && 'border-gray-200 bg-white',
      variant === 'elevated' && 'border-none bg-white shadow-lg'
    )}>
      {children}
    </div>
  );
}

CSS Modules:

  • Группируй связанные стили
  • Используй camelCase для селекторов
  • Экспортируй объект стилей

CSS-in-JS:

  • Кэшируй создание стилей
  • Избегай создания новых объектов в render
// Плохо
const StyledButton = styled.button`
  color: ${props => props.color}; // Создаёт новый стиль при каждом рендере
`;

// Хорошо
const colorMap = { red: '#f56565', blue: '#3182ce' };
const StyledButton = styled.button`
  color: ${props => colorMap[props.color]};
`;

Мой выбор для новых проектов

Стандартный стек: Tailwind CSS + TypeScript + React

// Типичный компонент
export interface CardProps {
  title: string;
  variant?: 'default' | 'elevated';
  children: React.ReactNode;
}

export function Card({ title, variant = 'default', children }: CardProps) {
  return (
    <div className={cn(
      'rounded-lg p-4 border',
      variant === 'default' && 'border-gray-200 bg-white',
      variant === 'elevated' && 'border-none shadow-lg bg-white'
    )}>
      <h2 className="text-lg font-semibold mb-2">{title}</h2>
      <div className="text-gray-700">{children}</div>
    </div>
  );
}

Почему Tailwind:

  • Скорость разработки
  • Нет конфликтов CSS
  • Встроенная система дизайна
  • Отличная производительность
  • Современный стандарт индустрии

Когда выбираю CSS Modules:

  • Очень сложная стилизация
  • Legacy проекты
  • Нужна полная изоляция стилей

Когда выбираю CSS-in-JS:

  • Системы дизайна с большим числом вариаций
  • Динамические темы (light/dark mode)
  • Высокая сложность стилей

Вывод: scoped styles — это необходимость в современном frontend, но форма их реализации зависит от проекта. Tailwind CSS — лучший выбор в 90% случаев.

Используешь ли scoped styles | PrepBro