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

Как изменить количество колонок через Props в CSS-in-JS?

2.0 Middle🔥 151 комментариев
#HTML и CSS

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

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

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

Изменение количества колонок через Props в CSS-in-JS

Это классическая задача, когда нужно сделать компонент гибким, позволяя родителю контролировать количество колонок в Grid или многоколонном макете. Рассмотрим несколько подходов для разных CSS-in-JS решений.

1. Tailwind CSS с условными классами (рекомендуется)

В современной разработке часто используют Tailwind CSS, который может генерировать динамические классы.

// components/Grid.tsx
interface GridProps {
  children: React.ReactNode;
  columns?: 1 | 2 | 3 | 4 | 6;
}

export function Grid({ children, columns = 2 }: GridProps) {
  const colsClass = {
    1: grid-cols-1,
    2: grid-cols-2,
    3: grid-cols-3,
    4: grid-cols-4,
    6: grid-cols-6
  }[columns];

  return (
    <div className={`grid gap-4 ${colsClass}`}>
      {children}
    </div>
  );
}

// Использование
<Grid columns={3}>
  <div>Item 1</div>
  <div>Item 2</div>
  <div>Item 3</div>
</Grid>

Проблема: нельзя просто вставить grid-cols-${columns}, потому что Tailwind требует статических класс-имен для оптимизации.

2. CSS Variables (самый современный способ)

Используем CSS переменные (custom properties) для динамического контроля.

// components/Grid.tsx
interface GridProps {
  children: React.ReactNode;
  columns?: number;
}

export function Grid({ children, columns = 2 }: GridProps) {
  return (
    <div
      style={{
        display: grid,
        gridTemplateColumns: `repeat(${columns}, 1fr)`,
        gap: 1rem
      }}
    >
      {children}
    </div>
  );
}

// Или через CSS переменную
export function Grid({ children, columns = 2 }: GridProps) {
  return (
    <div
      style={{
        --cols: columns
      } as React.CSSProperties}
      className="grid"
    >
      {children}
    </div>
  );
}

// В CSS файле или <style>
// .grid {
//   display: grid;
//   grid-template-columns: repeat(var(--cols), 1fr);
//   gap: 1rem;
// }

3. Emotion (CSS-in-JS библиотека)

Эмоция позволяет писать CSS прямо в JavaScript с поддержкой переменных.

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

const GridWrapper = styled.div<{ columns: number }>`
  display: grid;
  grid-template-columns: repeat(${props => props.columns}, 1fr);
  gap: 1rem;
`;

interface GridProps {
  children: React.ReactNode;
  columns?: number;
}

export function Grid({ children, columns = 2 }: GridProps) {
  return (
    <GridWrapper columns={columns}>
      {children}
    </GridWrapper>
  );
}

// Использование
<Grid columns={4}>
  <div>Item 1</div>
  <div>Item 2</div>
  <div>Item 3</div>
  <div>Item 4</div>
</Grid>

4. Styled Components

Популярная библиотека для CSS-in-JS в React.

import styled from styled-components;

const GridWrapper = styled.div<{ columns: number }>`
  display: grid;
  grid-template-columns: repeat(${props => props.columns}, 1fr);
  gap: 1rem;
  width: 100%;
`;

interface GridProps {
  children: React.ReactNode;
  columns?: number;
}

export function Grid({ children, columns = 2 }: GridProps) {
  return (
    <GridWrapper columns={columns}>
      {children}
    </GridWrapper>
  );
}

5. Vanilla CSS с CSS-in-JS объектом

Прямое применение стилей через style prop в React.

interface GridProps {
  children: React.ReactNode;
  columns?: number;
  gap?: number;
}

export function Grid({ children, columns = 2, gap = 16 }: GridProps) {
  const gridStyle: React.CSSProperties = {
    display: grid,
    gridTemplateColumns: `repeat(${columns}, 1fr)`,
    gap: `${gap}px`,
    width: 100%
  };

  return <div style={gridStyle}>{children}</div>;
}

// Использование
<Grid columns={3} gap={20}>
  {items.map(item => (
    <div key={item.id}>{item.name}</div>
  ))}
</Grid>

6. Responsive Grid (разное количество колонок на разных экранах)

Очень часто нужно менять количество колонок в зависимости от размера экрана.

interface ResponsiveGridProps {
  children: React.ReactNode;
  columns?: {
    mobile: number;
    tablet: number;
    desktop: number;
  };
}

export function ResponsiveGrid({
  children,
  columns = { mobile: 1, tablet: 2, desktop: 3 }
}: ResponsiveGridProps) {
  return (
    <div
      style={{
        display: grid,
        gridTemplateColumns: `repeat(${columns.mobile}, 1fr)`
      }}
      className="
        grid gap-4
        sm:grid-cols-2 tablet:grid-cols-2
        lg:grid-cols-3 desktop:grid-cols-3
      "
    >
      {children}
    </div>
  );
}

// Или с CSS переменными
const styles = `
  @media (max-width: 640px) {
    .responsive-grid {
      grid-template-columns: repeat(var(--cols-mobile), 1fr);
    }
  }
  @media (min-width: 641px) and (max-width: 1024px) {
    .responsive-grid {
      grid-template-columns: repeat(var(--cols-tablet), 1fr);
    }
  }
  @media (min-width: 1025px) {
    .responsive-grid {
      grid-template-columns: repeat(var(--cols-desktop), 1fr);
    }
  }
`;

interface ResponsiveGridProps {
  children: React.ReactNode;
  mobileColumns?: number;
  tabletColumns?: number;
  desktopColumns?: number;
}

export function ResponsiveGrid({
  children,
  mobileColumns = 1,
  tabletColumns = 2,
  desktopColumns = 3
}: ResponsiveGridProps) {
  return (
    <div
      style={{
        --cols-mobile: mobileColumns,
        --cols-tablet: tabletColumns,
        --cols-desktop: desktopColumns
      } as React.CSSProperties}
      className="responsive-grid gap-4"
    >
      {children}
    </div>
  );
}

7. Практический пример с обработкой edge cases

interface GridProps {
  children: React.ReactNode;
  columns?: number;
  minWidth?: number;  // Минимальная ширина колонки
  gap?: number;
}

export function Grid({
  children,
  columns = 2,
  minWidth = 200,
  gap = 16
}: GridProps) {
  // Валидация
  const validColumns = Math.max(1, Math.floor(columns));
  const validGap = Math.max(0, gap);

  const gridStyle: React.CSSProperties = {
    display: grid,
    gridTemplateColumns: `repeat(auto-fit, minmax(${minWidth}px, 1fr))`,
    gap: `${validGap}px`,
    width: 100%
  };

  return (
    <div style={gridStyle} role="grid">
      {children}
    </div>
  );
}

Сравнение подходов

ПодходПлюсыМинусы
Tailwind + MapПростой, предсказуемыйМного кода для каждого значения
CSS VariablesДинамичный, гибкийНужна поддержка CSS переменных
Inline stylesБыстро, нет зависимостейСложнее с мобильностью
Emotion/StyledМощный, типизированныйДополнительная библиотека
CSS Grid auto-fitАдаптивный без медиа-запросовМеньше контроля над макетом

Лучшая практика

Для современной разработки рекомендуется:

  1. Используй CSS Variables для простоты и гибкости
  2. Твой стиль должен быть типизирован в TypeScript
  3. Валидируй props перед использованием
  4. Используй auto-fit для адаптивности когда возможно
  5. Документируй допустимые значения в интерфейсе

Самый универсальный и современный способ — это комбинация CSS Variables и inline styles, которая работает везде и не требует дополнительных библиотек.

Как изменить количество колонок через Props в CSS-in-JS? | PrepBro