Вёрстка сайта с использованием Chakra UI
Chakra UI — React-компонентная библиотека, ориентированная на accessibility-first подход и style props API. Каждый компонент — это styled div с Emotion под капотом. Сильные стороны: responsive props прямо в JSX, встроенная тёмная тема, строгая WCAG-совместимость из коробки.
Установка (Chakra v3)
В версии 3.x архитектура изменилась — провайдер упрощён, снята зависимость от ChakraBaseProvider:
npm install @chakra-ui/react @emotion/react
// src/main.tsx
import { ChakraProvider, defaultSystem } from '@chakra-ui/react';
import system from './theme/system';
function Root() {
return (
<ChakraProvider value={system}>
<App />
</ChakraProvider>
);
}
// src/theme/system.ts
import { createSystem, defaultConfig, defineConfig } from '@chakra-ui/react';
const customConfig = defineConfig({
theme: {
tokens: {
fonts: {
heading: { value: '"Inter", sans-serif' },
body: { value: '"Inter", sans-serif' },
mono: { value: '"JetBrains Mono", monospace' },
},
colors: {
brand: {
50: { value: '#eff6ff' },
100: { value: '#dbeafe' },
500: { value: '#3b82f6' },
600: { value: '#2563eb' },
700: { value: '#1d4ed8' },
800: { value: '#1e40af' },
},
},
radii: {
card: { value: '12px' },
button: { value: '8px' },
},
},
semanticTokens: {
colors: {
'bg.canvas': {
value: { base: '#f9fafb', _dark: '#0f172a' },
},
'bg.surface': {
value: { base: '#ffffff', _dark: '#1e293b' },
},
'text.primary': {
value: { base: '#111827', _dark: '#f1f5f9' },
},
'text.muted': {
value: { base: '#6b7280', _dark: '#94a3b8' },
},
'border.default': {
value: { base: '#e5e7eb', _dark: '#334155' },
},
},
},
},
});
const system = createSystem(defaultConfig, customConfig);
export default system;
Style props API — основа вёрстки
Chakra UI передаёт CSS-свойства прямо через props с поддержкой адаптивных объектов:
import { Box, Flex, Grid, Text, Heading, Button, Stack } from '@chakra-ui/react';
const HeroSection = () => (
<Box
as="section"
bg="bg.canvas"
py={{ base: '12', md: '20', lg: '28' }}
px={{ base: '4', md: '8', lg: '12' }}
>
<Flex
maxW="7xl"
mx="auto"
direction={{ base: 'column', lg: 'row' }}
align="center"
gap={{ base: '10', lg: '16' }}
>
<Box flex="1">
<Heading
as="h1"
size={{ base: '2xl', md: '3xl', lg: '4xl' }}
color="text.primary"
mb="4"
fontWeight="700"
lineHeight="1.2"
>
Заголовок вашего продукта
</Heading>
<Text
fontSize={{ base: 'md', md: 'lg' }}
color="text.muted"
mb="8"
maxW="480px"
>
Подзаголовок с описанием ключевой ценности для потенциального клиента.
</Text>
<Stack direction={{ base: 'column', sm: 'row' }} gap="3">
<Button
colorPalette="brand"
size="lg"
borderRadius="button"
px="8"
>
Начать бесплатно
</Button>
<Button
variant="outline"
size="lg"
borderRadius="button"
px="8"
>
Посмотреть демо
</Button>
</Stack>
</Box>
<Box flex="1">
<Box
as="img"
src="/img/hero.webp"
alt="Product screenshot"
w="100%"
borderRadius="card"
shadow="2xl"
/>
</Box>
</Flex>
</Box>
);
Сетка карточек
import { SimpleGrid, Card, Icon } from '@chakra-ui/react';
import { LuCode, LuCloud, LuShield } from 'react-icons/lu';
const features = [
{ icon: LuCode, title: 'Разработка', text: '...' },
{ icon: LuCloud, title: 'Облако', text: '...' },
{ icon: LuShield, title: 'Безопасность', text: '...' },
];
const FeaturesGrid = () => (
<SimpleGrid columns={{ base: 1, sm: 2, lg: 3 }} gap="6">
{features.map(({ icon, title, text }) => (
<Card.Root
key={title}
bg="bg.surface"
border="1px solid"
borderColor="border.default"
borderRadius="card"
_hover={{ shadow: 'md', transform: 'translateY(-2px)' }}
transition="all 200ms ease"
>
<Card.Body p="6">
<Box
w="10"
h="10"
bg="brand.50"
borderRadius="lg"
display="flex"
alignItems="center"
justifyContent="center"
mb="4"
>
<Icon as={icon} boxSize="5" color="brand.600" />
</Box>
<Heading as="h3" size="md" mb="2">
{title}
</Heading>
<Text color="text.muted" fontSize="sm">
{text}
</Text>
</Card.Body>
</Card.Root>
))}
</SimpleGrid>
);
Форма с валидацией (React Hook Form + Zod)
import { Field, Input, Textarea, Button } from '@chakra-ui/react';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
const schema = z.object({
name: z.string().min(2, 'Минимум 2 символа'),
email: z.string().email('Некорректный email'),
message: z.string().min(10, 'Минимум 10 символов'),
});
type FormData = z.infer<typeof schema>;
const ContactForm = () => {
const { register, handleSubmit, formState: { errors, isSubmitting } } = useForm<FormData>({
resolver: zodResolver(schema),
});
return (
<Box as="form" onSubmit={handleSubmit(onSubmit)}>
<Stack gap="5">
<Field.Root invalid={!!errors.name}>
<Field.Label>Имя</Field.Label>
<Input {...register('name')} placeholder="Иван Иванов" />
{errors.name && <Field.ErrorText>{errors.name.message}</Field.ErrorText>}
</Field.Root>
<Field.Root invalid={!!errors.email}>
<Field.Label>Email</Field.Label>
<Input {...register('email')} type="email" placeholder="[email protected]" />
{errors.email && <Field.ErrorText>{errors.email.message}</Field.ErrorText>}
</Field.Root>
<Field.Root invalid={!!errors.message}>
<Field.Label>Сообщение</Field.Label>
<Textarea {...register('message')} rows={4} />
{errors.message && <Field.ErrorText>{errors.message.message}</Field.ErrorText>}
</Field.Root>
<Button type="submit" colorPalette="brand" loading={isSubmitting} w="full">
Отправить
</Button>
</Stack>
</Box>
);
};
Цветовой режим
Chakra v3 управляет тёмным режимом через семантические токены — _dark вариант задаётся при определении токена:
import { useColorMode } from '@chakra-ui/react';
const ThemeToggle = () => {
const { colorMode, toggleColorMode } = useColorMode();
return (
<Button onClick={toggleColorMode} variant="ghost" size="sm">
{colorMode === 'light' ? 'Тёмная тема' : 'Светлая тема'}
</Button>
);
};
Сроки
Настройка системы и темы: 3–4 часа. Chakra UI особенно эффективен при разработке сайтов с формами, дашбордами и SaaS-интерфейсами — адаптивные props в JSX исключают переключение файлов. Посадочная страница: 1–2 дня. Полный продуктовый сайт с несколькими разделами: 4–7 дней.







