Chakra UI는 React용 구성 요소 라이브러리입니다. 버튼, 입력, 카드, 대화 상자 및 p={6} 또는 colorPalette="teal"와 같은 소품을 통해 설정하는 스타일 시스템입니다.
프로젝트 페이지에서는 "고품질 웹 앱 및 디자인 시스템 구축을 위한 접근 가능한 React 구성 요소"라고 설명하고 있으며 MIT 라이선스를 받았습니다.
공식 설정에서는 npm과 프로젝트를 사용합니다. 원하는 것이 하나의 작동하는 HTML 파일이라면 아래 예는 전체 페이지입니다. 버튼을 클릭하세요.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Chakra UI in one HTML file</title>
<!-- Map package names to pinned jsDelivr ESM bundles -->
<script type="importmap">
{
"imports": {
"react": "https://cdn.jsdelivr.net/npm/react@19.2.8/+esm",
"react-dom/client": "https://cdn.jsdelivr.net/npm/react-dom@19.2.8/client/+esm",
"@chakra-ui/react": "https://cdn.jsdelivr.net/npm/@chakra-ui/react@3.37.0/+esm",
"https://cdn.jsdelivr.net/npm/react@19.0.0/+esm": "https://cdn.jsdelivr.net/npm/react@19.2.8/+esm"
}
}
</script>
</head>
<body>
<div id="root"><p style="font-family: system-ui, sans-serif; padding: 24px; margin: 0;">Loading Chakra UI...</p></div>
<script type="module">
import { createElement as h, useState } from 'react';
import { createRoot } from 'react-dom/client';
import { ChakraProvider, defaultSystem, Box, Heading, Text, Button } from '@chakra-ui/react';
function App() {
const [count, setCount] = useState(0);
// h(Component, props, ...children) is what JSX compiles to
return h(Box, { p: 6, maxW: 'sm' },
h(Heading, { size: 'xl', mb: 2 }, 'Hello from Chakra UI'),
h(Text, { color: 'fg.muted', mb: 4 }, 'One HTML file, no build step.'),
h(Button, { colorPalette: 'teal', onClick: () => setCount(count + 1) }, 'Clicked ' + count + ' times')
);
}
// Every Chakra component must sit inside ChakraProvider
createRoot(document.getElementById('root')).render(
h(ChakraProvider, { value: defaultSystem }, h(App))
);
</script>
</body>
</html>
첫 번째 로드에서는 cdn.jsdelivr.net에서 작은 모듈 파일만큼 라이브러리를 가져오므로 잠시 동안 "Loading Chakra UI..."가 표시됩니다. 나중에 로드는 브라우저 캐시에서 발생합니다.
단일 파일 페이지가 구축되는 방식
빌드 단계가 없으므로 페이지는 번들러가 일반적으로 수행하는 네 가지 작업을 수행합니다.

- 가져오기 맵.
<script type="importmap">블록은react,react-dom/client및@chakra-ui/react이름을 cdn.jsdelivr.net에 고정된 파일에 매핑합니다. 모듈 스크립트 앞에 와야 합니다. - 모듈 스크립트. 코드는
<script type="module">에 있습니다. 일반<script>는 "모듈 외부에서 import 문을 사용할 수 없습니다"로 중지됩니다. - ChakraProvider. 모든 Chakra 구성 요소는
ChakraProvider에서 테마를 읽습니다. 사용자 정의 테마가 없으면value: defaultSystem를 전달합니다. - 구성 요소. 각 JSX 태그는
createElement호출이 되며, 짧게 유지하기 위해h로 가져옵니다.
가져오기 맵(한 줄씩)
예제에서 사용하는 네 가지 항목은 다음과 같습니다.
<script type="importmap">
{
"imports": {
"react": "https://cdn.jsdelivr.net/npm/react@19.2.8/+esm",
"react-dom/client": "https://cdn.jsdelivr.net/npm/react-dom@19.2.8/client/+esm",
"@chakra-ui/react": "https://cdn.jsdelivr.net/npm/@chakra-ui/react@3.37.0/+esm",
"https://cdn.jsdelivr.net/npm/react@19.0.0/+esm": "https://cdn.jsdelivr.net/npm/react@19.2.8/+esm"
}
}
</script>
/+esm 엔딩은 jsDelivr에 브라우저 지원 모듈을 요청합니다. 해당 파일 내에는 react@19.2.8와 같은 정확한 버전의 전체 jsDelivr 주소로 종속성이 이미 기록되어 있습니다.
마지막 줄이 이상해 보이지만 이것이 가장 중요합니다. Chakra가 스타일을 지정하는 Emotion 번들은 react@19.0.0를 가져오고, Chakra 및 React DOM은 react@19.2.8를 가져옵니다. 가져오기 맵 키는 전체 URL이 될 수 있으므로 이 줄은 이탈된 버전을 동일한 파일로 보냅니다.

해당 줄이 없으면 페이지는 공백으로 유지되고 콘솔에는 "null의 속성을 읽을 수 없습니다('useContext' 읽기)"가 표시됩니다. 버전 번호를 변경하는 경우 번들 URL을 열고 해당 import 행을 다시 확인하세요.
컴파일러가 없는 JSX
Chakra의 문서에는 <Button colorPalette="teal">와 같은 JSX가 표시됩니다. 브라우저는 JSX를 읽을 수 없으며 대신 React 문서 createElement를 읽을 수 있습니다. 번역은 기계적입니다.
// JSX: <Button colorPalette="teal" onClick={add}>Add</Button>
h(Button, { colorPalette: 'teal', onClick: add }, 'Add')
// JSX: <Card.Root><Card.Body>Hi</Card.Body></Card.Root>
h(Card.Root, null, h(Card.Body, null, 'Hi'))
p, mb, maxW 및 bg와 같은 차크라 스타일 소품을 포함한 소품은 동일하게 유지됩니다. Card.Root 및 Field.Label와 같은 부품이 포함된 구성요소도 동일한 방식으로 전달됩니다.
변형, 색상 팔레트 및 다크 모드
버튼은 스타일에 variant 소품을, 색상에 colorPalette 소품을 사용합니다. HStack와 같은 상위 항목에 colorPalette를 설정하면 내부 버튼으로 전달됩니다. 팔레트를 선택한 다음 어두운 모드로 전환하세요.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Chakra UI variants, palettes and dark mode</title>
<script type="importmap">
{
"imports": {
"react": "https://cdn.jsdelivr.net/npm/react@19.2.8/+esm",
"react-dom/client": "https://cdn.jsdelivr.net/npm/react-dom@19.2.8/client/+esm",
"@chakra-ui/react": "https://cdn.jsdelivr.net/npm/@chakra-ui/react@3.37.0/+esm",
"https://cdn.jsdelivr.net/npm/react@19.0.0/+esm": "https://cdn.jsdelivr.net/npm/react@19.2.8/+esm"
}
}
</script>
</head>
<body>
<div id="root"><p style="font-family: system-ui, sans-serif; padding: 24px; margin: 0;">Loading Chakra UI...</p></div>
<script type="module">
import { createElement as h, useState } from 'react';
import { createRoot } from 'react-dom/client';
import { ChakraProvider, defaultSystem, Box, Stack, HStack, Button, Text } from '@chakra-ui/react';
const palettes = ['teal', 'blue', 'purple', 'red'];
const variants = ['solid', 'subtle', 'outline', 'ghost'];
function App() {
const [palette, setPalette] = useState('teal');
const [dark, setDark] = useState(false);
function toggleDark() {
// Chakra's dark styles apply under a .dark class on a parent
document.documentElement.classList.toggle('dark', !dark);
setDark(!dark);
}
return h(Box, { p: 5, bg: 'bg', color: 'fg', minH: '100vh' },
h(Stack, { gap: 4 },
h(Text, { fontWeight: 'semibold' }, 'colorPalette'),
h(HStack, { wrap: 'wrap' }, palettes.map((p) =>
h(Button, { key: p, size: 'sm', variant: p === palette ? 'solid' : 'outline',
onClick: () => setPalette(p) }, p))),
h(Text, { fontWeight: 'semibold' }, 'variant'),
// colorPalette on a parent is inherited by the buttons inside
h(HStack, { wrap: 'wrap', colorPalette: palette }, variants.map((v) =>
h(Button, { key: v, variant: v }, v))),
h(Button, { alignSelf: 'start', variant: 'surface', onClick: toggleDark },
dark ? 'Light mode' : 'Dark mode')
)
);
}
createRoot(document.getElementById('root')).render(
h(ChakraProvider, { value: defaultSystem }, h(App))
);
</script>
</body>
</html>
프로젝트에서 Chakra 문서는 next-themes 패키지에 구축된 Provider 스니펫을 통해 다크 모드를 추가합니다. Chakra의 어두운 스타일은 상위 요소의 .dark 클래스 아래에 적용되므로 단일 파일이 <html> 자체에서 해당 클래스를 전환할 수 있습니다.
document.documentElement.classList.toggle('dark');
bg, fg 및 fg.muted와 같은 예제의 색상 토큰이 함께 전환됩니다. white와 같은 고정 색상은 그렇지 않습니다. 라이브러리가 없는 다크 모드에 대해서는 CSS의 다크 모드를 참조하세요.
완성된 예: 가입 카드
양식은 Card, Field 및 Input를 사용합니다. 필드를 비운 상태에서 가입을 누른 다음 내용을 입력하세요.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Chakra UI sign-up card</title>
<script type="importmap">
{
"imports": {
"react": "https://cdn.jsdelivr.net/npm/react@19.2.8/+esm",
"react-dom/client": "https://cdn.jsdelivr.net/npm/react-dom@19.2.8/client/+esm",
"@chakra-ui/react": "https://cdn.jsdelivr.net/npm/@chakra-ui/react@3.37.0/+esm",
"https://cdn.jsdelivr.net/npm/react@19.0.0/+esm": "https://cdn.jsdelivr.net/npm/react@19.2.8/+esm"
}
}
</script>
</head>
<body>
<div id="root"><p style="font-family: system-ui, sans-serif; padding: 24px; margin: 0;">Loading Chakra UI...</p></div>
<script type="module">
import { createElement as h, useState } from 'react';
import { createRoot } from 'react-dom/client';
import { ChakraProvider, defaultSystem, Box, Card, Field, Input, Button, Stack, Text } from '@chakra-ui/react';
function App() {
const [errors, setErrors] = useState({});
const [sent, setSent] = useState(null);
function onSubmit(e) {
e.preventDefault(); // handle it in the page, send nothing
const data = Object.fromEntries(new FormData(e.target));
const next = {};
if (!data.name.trim()) next.name = 'Enter your name.';
if (!/^\S+@\S+\.\S+$/.test(data.email)) next.email = 'Enter a valid email.';
setErrors(next);
setSent(Object.keys(next).length ? null : data);
}
// Field.Root gets invalid; Field.ErrorText only shows when it is set
const field = (name, label, type) =>
h(Field.Root, { invalid: !!errors[name] },
h(Field.Label, null, label),
h(Input, { name, type, placeholder: label }),
h(Field.ErrorText, null, errors[name]));
return h(Box, { p: 4, bg: 'bg.muted', minH: '100vh' },
h(Card.Root, { maxW: 'sm', mx: 'auto' },
h(Card.Header, null,
h(Card.Title, null, 'Join the beta'),
h(Card.Description, null, 'Two fields, checked in the page.')),
h(Card.Body, null,
h('form', { id: 'signup', onSubmit, noValidate: true },
h(Stack, { gap: 4 }, field('name', 'Name', 'text'), field('email', 'Email', 'email')))),
h(Card.Footer, { flexDirection: 'column', alignItems: 'stretch', gap: 3 },
h(Button, { type: 'submit', form: 'signup', colorPalette: 'teal' }, 'Sign up'),
sent && h(Text, { id: 'result', color: 'green.fg', fontSize: 'sm' },
'Thanks, ' + sent.name + '. We would write to ' + sent.email + '.'))
)
);
}
createRoot(document.getElementById('root')).render(
h(ChakraProvider, { value: defaultSystem }, h(App))
);
</script>
</body>
</html>
- 오류:
invalid를Field.Root에 전달합니다.Field.ErrorText는 설정된 동안에만 나타납니다. - 값 읽기: 제출 핸들러는
preventDefault()를 호출하고 JavaScript의 FormData에서 다루는FormData로 입력을 읽습니다. - 전송: 페이지에서 아무것도 남지 않습니다. 실제 가입은 아래와 같이 서버에 게시되지만 여기서는 실행되지 않습니다.
await fetch('https://api.example.com/signup', {
method: 'POST',
body: new FormData(form),
});
대신 npm 프로젝트가 필요한 경우
단일 파일은 보내려는 페이지, 프로토타입 또는 데모용입니다. 전체 앱의 경우 Chakra 문서는 번들러를 사용하여 프로젝트를 설정합니다.

npm i @chakra-ui/react @emotion/react
npx @chakra-ui/cli snippet add
문서에는 Vite, Next.js 및 기타 프레임워크에 대한 가이드와 함께 Node.js 20이 최소로 나열되어 있습니다.
빌드는 정적 파일을 생성하며 빌드된 프런트 엔드 호스팅이 해당 파일이 이동할 수 있는 위치를 다룹니다. React 없이 미리 만들어진 스타일만 원하는 경우 Tailwind HTML 템플릿에 스크립트 태그가 하나 필요합니다.
| HTML 파일 1개 | npm 프로젝트 | |
|---|---|---|
| 설치 | 아무것도 | Node.js와 npm |
| 구성 요소 작성 | h(Button, props) |
JSX |
| 공급자 | ChakraProvider + defaultSystem |
Provider 스니펫 |
| 다크 모드 | dark 클래스 전환 |
다음 테마를 사용하는 스니펫 |
| 결과 | 파일 자체 | 호스트할 내장 폴더 |
작동하지 않을 때
| 당신이 보는 것 | 원인 | 수정 |
|---|---|---|
| "모듈 외부에서 import 문을 사용할 수 없습니다" | 일반 <script> 태그 |
type="module" 사용 |
| "모듈 지정자를 확인하지 못했습니다." | 모듈 스크립트 뒤에 가져오기 맵이 누락되었거나 JSON이 유효하지 않습니다. | 먼저 입력하고 쉼표를 확인하세요. |
| 빈 페이지, "'useContext'를 읽는 중" | 두 가지 React 버전이 로드되었습니다. | 가져오기 맵에서 react@19.0.0를 다시 매핑합니다. |
| "ChakraProvider 내에서 구성 요소를 래핑하는 것을 잊었습니다" | 제공업체 없음 | ChakraProvider 내부 렌더링 |
| "예기치 않은 토큰 '<'" | 브라우저의 JSX | h(...) 사용 |
| 다크 모드에서는 일부 부분이 밝게 유지됩니다. | 토큰 대신 고정 색상 | bg 및 fg 토큰 사용 |
마지막 가져오기 맵 항목 뒤에 오는 쉼표로 인해 JSON이 유효하지 않게 됩니다. 다른 빈 페이지 원인에 대해서는 HTML JavaScript가 작동하지 않음을 참조하세요.
링크로 공유하세요
차크라 페이지는 설명하는 것보다 보여주는 것이 더 쉽습니다. 스크린샷을 클릭할 수 없으며 .html 첨부 파일이 전화기에서 일반 코드로 열릴 수 있습니다.
작업 버전을 보내려면 페이지를 NOS 문서에 붙여넣고 공유 링크 만들기를 선택하세요. 링크할 HTML이 이를 안내합니다.
페이지는 작성된 대로 렌더링되고 스크립트가 실행되며 라이브러리는 cdn.jsdelivr.net에서 로드되므로 링크가 있는 사람은 누구나 계정 없이 버튼을 누르고 양식을 작성할 수 있습니다.
나중에 코드를 변경하면 동일한 링크에 새 버전이 표시됩니다.