단일 HTML 파일의 차크라 UI

Chakra UI는 React 구성 요소 집합이며 해당 문서는 npm 및 번들러로 시작됩니다. 하나의 HTML 파일(가져오기 맵, 모듈 스크립트 및 공급자)을 계속 실행할 수 있습니다.

영문 원문 보기

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>
jsDelivr에서 로드된 Chakra UI 3.37.0 및 React 19.2.8. 코드를 편집하면 예제가 다시 실행됩니다.

첫 번째 로드에서는 cdn.jsdelivr.net에서 작은 모듈 파일만큼 라이브러리를 가져오므로 잠시 동안 "Loading Chakra UI..."가 표시됩니다. 나중에 로드는 브라우저 캐시에서 발생합니다.

단일 파일 페이지가 구축되는 방식

빌드 단계가 없으므로 페이지는 번들러가 일반적으로 수행하는 네 가지 작업을 수행합니다.

단일 파일 차크라 페이지의 네 부분(머리부터 아래).
단일 파일 차크라 페이지의 네 부분(머리부터 아래).
  1. 가져오기 맵. <script type="importmap"> 블록은 react, react-dom/client 및 @chakra-ui/react 이름을 cdn.jsdelivr.net에 고정된 파일에 매핑합니다. 모듈 스크립트 앞에 와야 합니다.
  2. 모듈 스크립트. 코드는 <script type="module">에 있습니다. 일반 <script>는 "모듈 외부에서 import 문을 사용할 수 없습니다"로 중지됩니다.
  3. ChakraProvider. 모든 Chakra 구성 요소는 ChakraProvider에서 테마를 읽습니다. 사용자 정의 테마가 없으면 value: defaultSystem를 전달합니다.
  4. 구성 요소. 각 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이 될 수 있으므로 이 줄은 이탈된 버전을 동일한 파일로 보냅니다.

React의 두 사본은 페이지를 비워 둡니다. 하나의 재맵핑 라인이 문제를 해결합니다.
React의 두 사본은 페이지를 비워 둡니다. 하나의 재맵핑 라인이 문제를 해결합니다.

해당 줄이 없으면 페이지는 공백으로 유지되고 콘솔에는 "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>
Button의 colorPalette 및 변형, 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>
Field.Root는 검사가 실패하면 무효화되고 Field.ErrorText가 표시됩니다. 제출은 페이지에서 처리됩니다.
  • 오류: invalid를 Field.Root에 전달합니다. Field.ErrorText는 설정된 동안에만 나타납니다.
  • 값 읽기: 제출 핸들러는 preventDefault()를 호출하고 JavaScript의 FormData에서 다루는 FormData로 입력을 읽습니다.
  • 전송: 페이지에서 아무것도 남지 않습니다. 실제 가입은 아래와 같이 서버에 게시되지만 여기서는 실행되지 않습니다.
await fetch('https://api.example.com/signup', {
  method: 'POST',
  body: new FormData(form),
});

대신 npm 프로젝트가 필요한 경우

단일 파일은 보내려는 페이지, 프로토타입 또는 데모용입니다. 전체 앱의 경우 Chakra 문서는 번들러를 사용하여 프로젝트를 설정합니다.

하나의 HTML 파일에서 실행되는 항목 옆에 Chakra 문서가 사용하는 npm 경로입니다.
하나의 HTML 파일에서 실행되는 항목 옆에 Chakra 문서가 사용하는 npm 경로입니다.
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에서 로드되므로 링크가 있는 사람은 누구나 계정 없이 버튼을 누르고 양식을 작성할 수 있습니다.

나중에 코드를 변경하면 동일한 링크에 새 버전이 표시됩니다.

자주 묻는 질문

React 없이 Chakra UI를 사용할 수 있나요?

아니요. Chakra UI는 React 구성 요소 라이브러리이며, React, React-dom 및 @emotion/react는 피어 종속성입니다. 단일 HTML 파일에서 React는 Chakra 옆의 CDN에서 로드되므로 빌드 단계 없이도 React 구성 요소를 계속 작성할 수 있습니다.

Bootstrap과 같은 Chakra UI 스크립트 태그가 있습니까?

Chakra 문서는 이를 제공하지 않습니다. 그들은 npm으로 설치합니다. 하나의 HTML 파일에서 모듈 스크립트는 고정된 버전의 패키지 이름을 가리키는 가져오기 맵을 사용하여 jsDelivr의 ESM 번들에서 패키지를 가져옵니다.

HTML 파일에 JSX를 작성할 수 있나요?

직접적으로는 아닙니다. 브라우저는 JSX를 이해하지 못하므로 컴파일 단계가 필요합니다. React의 createElement는 문서화된 대안입니다. h(Button, props, children)는 JSX 태그와 동일한 요소를 생성합니다.

useContext에 대한 오류와 함께 내 차크라 페이지가 비어 있는 이유는 무엇입니까?

두 가지 메시지가 일반적입니다. "ChakraProvider 내에서 구성 요소를 래핑하는 것을 잊었습니다"는 공급자가 없음을 의미합니다. "null 속성을 읽을 수 없습니다(useContext 읽기)."는 두 개의 React 복사본이 로드되었음을 의미합니다. 가져오기 맵에서 두 번째 버전을 다시 매핑합니다.

차크라 UI는 무료인가요?

그렇습니다. 저장소에는 MIT 라이센스가 나열되어 있으며 npm의 패키지는 MIT에 게시되어 있습니다.