Вёрстка сайта с использованием Emotion CSS-in-JS

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.
Разработка и обслуживание любых видов сайтов:
Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Вёрстка сайта с использованием Emotion CSS-in-JS
Простая
~2-3 рабочих дня
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    874
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    851

Вёрстка сайта с использованием Emotion CSS-in-JS

Emotion — CSS-in-JS библиотека с двумя API: @emotion/css для vanilla JS и @emotion/react для React. Используется как styling engine в MUI, Chakra UI и ряде других библиотек. Среди CSS-in-JS инструментов показывает лучшую производительность: поддерживает статическую экстракцию через Babel-плагин, что устраняет runtime-overhead для статических стилей.

Установка

# Для React
npm install @emotion/react @emotion/styled
# Опционально: Babel-плагин для оптимизации
npm install -D @emotion/babel-plugin
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [
    react({
      jsxImportSource: '@emotion/react',
      babel: {
        plugins: ['@emotion/babel-plugin'],
      },
    }),
  ],
});

При использовании jsxImportSource: '@emotion/react' можно использовать css prop напрямую без /** @jsxImportSource @emotion/react */ в каждом файле.

Два подхода: css prop и styled

css prop — инлайн стили с полной мощностью CSS

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

// Статический блок — вычислится один раз
const heroStyles = css`
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100svh;
  padding: 2rem;
  text-align: center;

  @media (min-width: 1024px) {
    flex-direction: row;
    text-align: left;
    padding: 4rem;
    gap: 5rem;
  }
`;

const HeroSection = () => (
  <section css={heroStyles}>
    <div>
      <h1 css={css`
        font-size: clamp(1.75rem, 4vw, 3rem);
        font-weight: 700;
        margin-bottom: 1rem;
        line-height: 1.2;
      `}>
        Заголовок страницы
      </h1>
    </div>
  </section>
);

styled — компонентный API

import styled from '@emotion/styled';

interface CardProps {
  elevated?: boolean;
  interactive?: boolean;
}

const Card = styled.article<CardProps>`
  background: var(--color-surface);
  border-radius: 0.75rem;
  padding: 1.5rem;
  border: 1px solid var(--color-border);
  box-shadow: ${({ elevated }) =>
    elevated ? '0 10px 15px -3px rgb(0 0 0 / 0.1)' : '0 1px 2px rgb(0 0 0 / 0.05)'};

  ${({ interactive }) =>
    interactive &&
    `
    cursor: pointer;
    transition: transform 200ms ease, box-shadow 200ms ease;
    &:hover {
      transform: translateY(-3px);
      box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1);
    }
  `}
`;

const CardTitle = styled.h3`
  font-size: 1.125rem;
  font-weight: 600;
  margin-bottom: 0.5rem;
  color: var(--color-text-primary);
`;

const CardBody = styled.p`
  font-size: 0.875rem;
  color: var(--color-text-secondary);
  line-height: 1.6;
`;

Тема через ThemeProvider

// src/theme/emotion-theme.ts
export const theme = {
  colors: {
    primary: '#2563eb',
    primaryDark: '#1d4ed8',
    primaryLight: '#eff6ff',
    background: '#f9fafb',
    surface: '#ffffff',
    textPrimary: '#111827',
    textSecondary: '#6b7280',
    border: '#e5e7eb',
  },
  space: (n: number) => `${n * 0.25}rem`,
  radius: {
    sm: '4px',
    md: '8px',
    lg: '12px',
  },
  shadow: {
    sm: '0 1px 2px rgb(0 0 0 / 0.05)',
    md: '0 4px 6px -1px rgb(0 0 0 / 0.1)',
  },
} as const;

export type Theme = typeof theme;

// Добавить в типы Emotion
declare module '@emotion/react' {
  export interface Theme {
    colors: typeof theme.colors;
    space: typeof theme.space;
    radius: typeof theme.radius;
    shadow: typeof theme.shadow;
  }
}
// src/App.tsx
import { ThemeProvider, Global, css } from '@emotion/react';
import { theme } from './theme/emotion-theme';

const globalStyles = css`
  *, *::before, *::after { box-sizing: border-box; }
  body {
    font-family: 'Inter', system-ui, sans-serif;
    background: ${theme.colors.background};
    color: ${theme.colors.textPrimary};
    -webkit-font-smoothing: antialiased;
  }
`;

const App = () => (
  <ThemeProvider theme={theme}>
    <Global styles={globalStyles} />
    <Router />
  </ThemeProvider>
);

Использование темы в styled-компонентах:

import styled from '@emotion/styled';

const PrimaryButton = styled.button`
  background: ${({ theme }) => theme.colors.primary};
  color: #fff;
  padding: ${({ theme }) => `${theme.space(2)} ${theme.space(4)}`};
  border-radius: ${({ theme }) => theme.radius.md};
  box-shadow: ${({ theme }) => theme.shadow.sm};

  &:hover {
    background: ${({ theme }) => theme.colors.primaryDark};
  }
`;

keyframes для анимаций

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

const fadeInUp = keyframes`
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
`;

const AnimatedCard = styled.div<{ delay?: number }>`
  animation: ${fadeInUp} 400ms ease both;
  animation-delay: ${({ delay = 0 }) => `${delay}ms`};
`;

// Использование
const FeaturesList = ({ features }) => (
  <>
    {features.map((feature, index) => (
      <AnimatedCard key={feature.id} delay={index * 80}>
        {/* ... */}
      </AnimatedCard>
    ))}
  </>
);

cx() для условных классов

import { css, cx } from '@emotion/css';

const base = css`
  padding: 1rem;
  border-radius: 8px;
`;

const active = css`
  background: #eff6ff;
  color: #2563eb;
  font-weight: 600;
`;

const MenuItem = ({ label, isActive }) => (
  <a className={cx(base, isActive && active)}>
    {label}
  </a>
);

Сравнение с Styled Components

Emotion Styled Components
Размер ~8 KB ~15 KB
Производительность Выше Чуть ниже
SSR Встроенная Требует ServerStyleSheet
css prop Да Нет (только через babel)
Популярность Растёт Устоявшаяся
Babel-плагин Да Да

Сроки

Настройка Emotion с ThemeProvider и типизацией: 2–3 часа. Вёрстка посадочной страницы: 1–2 дня. Emotion особенно хорош в проектах, где Styled Components не хватает производительности или нужен css prop для динамических стилей.