Skip to content
On this page

Chakra-UI

Chakra UI 是一个简单的,模块化的易于理解的 UI 组件库,提供了丰富的构建 React 应用所需的 UI 组件。

文档:https://next.chakra-ui.com/docs/getting-started

  • Chakra UI 内置 Emotion,是 CSS-IN-JS 解决方案的集大成者
  • 基于 Styled-Systems https://styled-system.com/
  • 支持开箱即用的主题功能
  • 默认支持白天和黑夜两种模式
  • 拥有大量功能丰富且有用的组件
  • 使响应式设计变的轻而易举
  • 文档清晰且全面,查找 API 更加容易
  • 适用于构建用于展示的给用户的界面
  • 框架正在变得越来越完善

快速开始

js
npm i @chakra-ui/react @emotion/react@^11 @emotion/styled@^11 framer-motion@^4

index.js

jsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { theme, ChakraProvider, CSSReset } from '@chakra-ui/react';

ReactDOM.render(
  <ChakraProvider>
    <CSSReset />
    <App theme={ theme } />
  </ChakraProvider>,
  document.getElementById('root')
);

App.js

jsx
import React from 'react';
import { Button } from '@chakra-ui/react';

function App () {
  return (
    <div>
      <Button>按钮</Button>
    </div>
  );
}

export default App;

样式属性

Style Props 是用来更改组件样式的,通过为组件传递属性的方式实现。通过传递简化的样式属性以达到提升开发效率的目的。

也可以查看文档:https://chakra-ui.com/docs/features/style-props。

样式属性css属性主题
m,marginmarginspace
mxmargin-left & margin-rightspace
p,paddingpaddingspace
pypadding-top & padding-bottomspace
bgbackgroundcolors
bgColorbackground-colorcolors
colorcolorcolors
borderborderborders
textAligntext-aliginnone
w,widthwidthsizes
boxSizewidth & heightsizes
d,displaydisplaynone
pos,positionpostionnone
leftleftspace
shadow,boxShadowbox-shdowshadows
jsx
import React from 'react';
import { Button, Box } from '@chakra-ui/react';

function App () {
  return (
    <Box w={ 200 } h={ 100 } bgColor="orange">
      <Button>按钮</Button>
    </Box>
  );
}

export default App;

颜色模式(color mode)

chakra-ui 提供的组件都支持两种颜色模式,浅色模式(light)和暗色模式(dark),可以通过 useColorMode 进行颜色模式的更改。

Chakra 将颜色模式存储在 localStorage 中,并使用类名策略来确保颜色模式是持久的。

jsx
import React from 'react';
import { Button, Box, Text, useColorMode } from '@chakra-ui/react';

function App () {
  const { colorMode, toggleColorMode } = useColorMode();

  console.log(colorMode);

  return (
    <Box w={ 200 } h={ 100 } bgColor={ colorMode === 'light' ? 'tomato' : 'skyblue' }>
      <Text>{ colorMode }</Text>
      <Button onClick={ toggleColorMode }>按钮</Button>
    </Box>
  );
}

export default App;

useColorModelValue

根据颜色模式设置样式。

chakra 允许在为元素设置样式时根据颜色模式产生不同值,通过 useColorModeValue 钩子函数实现。

jsx
import React from 'react';
import { Button, Box, Text, useColorMode, useColorModeValue } from '@chakra-ui/react';

function App () {
  const { colorMode, toggleColorMode } = useColorMode();
  const bgColor = useColorModeValue('tomato', 'skyblue');

  return (
    <Box w={ 200 } h={ 100 } bgColor={ bgColor }>
      <Text>{ colorMode }</Text>
      <Button onClick={ toggleColorMode }>按钮</Button>
    </Box>
  );
}

export default App;

强制组件的颜色模式

使组件不受颜色模式的影响,始终保持在某个颜色模式下的样式。

jsx
import React from 'react';
import { Button, Box, Text, useColorMode, useColorModeValue, LightMode } from '@chakra-ui/react';

function App () {
  const { colorMode, toggleColorMode } = useColorMode();
  const bgColor = useColorModeValue('tomato', 'skyblue');

  return (
    <Box w={ 200 } h={ 100 } bgColor={ bgColor }>
      <Text>{ colorMode }</Text>
      <Button onClick={ toggleColorMode }>按钮</Button> <br />
      <LightMode>
        <Button onClick={ toggleColorMode }>按钮</Button>
      </LightMode>
    </Box>
  );
}

export default App;

颜色模式通用设置

设置默认颜色模式

通过 theme.config.initialColorMode 可以设置应用使用的默认主题

jsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { theme, ChakraProvider, CSSReset } from '@chakra-ui/react';

theme.config.initialColorMode = 'dark';

ReactDOM.render(
  <ChakraProvider>
    <CSSReset />
    <App theme={ theme } />
  </ChakraProvider>,
  document.getElementById('root')
);

使用操作系统所使用的颜色模式

通过 theme.config.useSystemColorMode 可以设置将应用的颜色模式设置为操作系统所使用的颜色模式

jsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { theme, ChakraProvider, CSSReset } from '@chakra-ui/react';

theme.config.useSystemColorMode = true;

ReactDOM.render(
  <ChakraProvider>
    <CSSReset />
    <App theme={ theme } />
  </ChakraProvider>,
  document.getElementById('root')
);

主题对象

颜色

设置颜色时,可以但不限于取主题中提供的颜色值。

js
console.log(theme.colors); 
jsx
console.log(JSON.stringify(theme.colors.red));

//{"50":"#FFF5F5","100":"#FED7D7","200":"#FEB2B2","300":"#FC8181","400":"#F56565","500":"#E53E3E","600":"#C53030","700":"#9B2C2C","800":"#822727","900":"#63171B"}
jsx
import React from 'react';
import { Box, Text } from '@chakra-ui/react';

function App () {
  return (
    <Box w={ 200 } h={ 100 } bgColor="orange.200">
      <Text>Test</Text>
    </Box>
  );
}

export default App;

间距和大小

Space

使用 Space 可以自定义项目间距,这些间距值可以由 padding、margin 和 top、left、right、bottom 样式引用。

jsx
console.log(theme.space); 

//{"1":"0.25rem","2":"0.5rem","3":"0.75rem","4":"1rem","5":"1.25rem","6":"1.5rem","7":"1.75rem","8":"2rem","9":"2.25rem","10":"2.5rem","12":"3rem","14":"3.5rem","16":"4rem","20":"5rem","24":"6rem","28":"7rem","32":"8rem","36":"9rem","40":"10rem","44":"11rem","48":"12rem","52":"13rem","56":"14rem","60":"15rem","64":"16rem","72":"18rem","80":"20rem","96":"24rem","px":"1px","0.5":"0.125rem","1.5":"0.375rem","2.5":"0.625rem","3.5":"0.875rem"}
jsx
import React from 'react';
import { Box, Text } from '@chakra-ui/react';

function App () {
  return (
    <Box mt="6" w="2xs" h="10" bgColor="orange.200">
      <Text>Test</Text>
    </Box>
  );
}

export default App;

Sizes

使用 Sizes 可以自定义元素大小,这些值可以由 width、height 和 maxWidth、minWidth 等样式引用。

jsx
console.log(theme.sizes); 

//{"1":"0.25rem","2":"0.5rem","3":"0.75rem","4":"1rem","5":"1.25rem","6":"1.5rem","7":"1.75rem","8":"2rem","9":"2.25rem","10":"2.5rem","12":"3rem","14":"3.5rem","16":"4rem","20":"5rem","24":"6rem","28":"7rem","32":"8rem","36":"9rem","40":"10rem","44":"11rem","48":"12rem","52":"13rem","56":"14rem","60":"15rem","64":"16rem","72":"18rem","80":"20rem","96":"24rem","px":"1px","0.5":"0.125rem","1.5":"0.375rem","2.5":"0.625rem","3.5":"0.875rem","max":"max-content","min":"min-content","full":"100%","3xs":"14rem","2xs":"16rem","xs":"20rem","sm":"24rem","md":"28rem","lg":"32rem","xl":"36rem","2xl":"42rem","3xl":"48rem","4xl":"56rem","5xl":"64rem","6xl":"72rem","7xl":"80rem","8xl":"90rem","container":{"sm":"640px","md":"768px","lg":"1024px","xl":"1280px"}}

响应式断点

Breakpoints。配置响应数组值中使用的默认断点,这些值将用于生成移动优先(即最小宽度)的媒体查询。

jsx
import React from 'react';
import { Box, Text } from '@chakra-ui/react';

function App () {
  return (
    <Box mt="6" w={["100px", "300px", "500px", "700px", "1000px"]} h="10" bgColor="orange.200">
      <Text>Test</Text>
    </Box>
  );
}

export default App;

标准 chakra-ui 组件

jsx
import React from 'react';
import { chakra } from '@chakra-ui/react';

const MyButton = chakra('button', {
  baseStyle: {
    borderRadius: 'lg',
    px: 4,
    py: 2,
    fontSize: '12px',
    bgColor: 'blue.500',
    color: 'white'
  }
});

function App () {
  return (
    <div>
      <MyButton>按钮</MyButton>
    </div>
  );
}

export default App;

全局化 chakra-ui 组件样式

  • src 文件夹中创建 component-styles 文件夹用于放置自定义 Chakra-UI 组件
  • 在 component-styles 文件夹中创建 button.js 文件并将组件样式放置于当前文件并进行默认导出
js
const ButtonStyle = {
  baseStyle: {
    borderRadius: 'lg'
  },
  sizes: {
    sm: {
      px: 3,
      py: 1,
      fontSize: '12px'
    },
    md: {
      px: 4,
      py: 2,
      fontSize: '14px'
    }
  },
  variants: {
    primary: {
      bgColor: 'blue.500',
      color: 'white'
    },
    danger: {
      bgColor: 'red.500',
      color: 'white'
    }
  },
  defaultProps: {
    size: 'sm',
    variant: 'primary'
  }
}

export default ButtonStyle;
  • 在 component-styles 文件夹中创建 index.js 文件用于导入导出所有的自定义组件
js
import Button from './button';

export {
  Button
}
  • 在 src 文件夹中的 index.js 文件中导入自定义 Chakra-UI 组件并和 components 属性进行合并
jsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { ChakraProvider, CSSReset, extendTheme } from '@chakra-ui/react';
import { Button } from './component-styles/index';

const theme = extendTheme({
  components: {
    Button
  }
});

ReactDOM.render(
  <ChakraProvider theme={ theme } >
    <CSSReset />
    <App />
  </ChakraProvider>,
  document.getElementById('root')
);
  • 在组件中使用样式化组件
jsx
import React from 'react';
import { Button } from '@chakra-ui/react';

function App () {
  return (
    <div>
      <Button variant="danger" size="md">按钮</Button>
    </div>
  );
}

export default App;

构建注册表单

js
npm install react-icons --save

index.js

jsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { ChakraProvider, CSSReset, theme } from '@chakra-ui/react';

ReactDOM.render(
  <ChakraProvider theme={ theme } >
    <CSSReset />
    <App />
  </ChakraProvider>,
  document.getElementById('root')
);

App.js

jsx
import React from 'react';
import { Box } from '@chakra-ui/react';
import Form from './components/form';

function App () {
  return (
    <Box w={ 500 } h={ 500 } margin="30px auto">
      <Form />
    </Box>
  );
}

export default App;

components/form.js

jsx
import React from "react";
import {
  Input,
  InputGroup,
  InputLeftAddon,
  InputRightAddon,
  Stack,
  FormControl,
  FormHelperText,
  RadioGroup,
  Radio,
  Select,
  Switch,
  FormLabel,
  Flex,
  Button
} from "@chakra-ui/react";
import { FaUserAlt, FaLock, FaCheck } from 'react-icons/fa';

export default function Form () {
  return (
    <form>
      <Stack spacing="6">
        <FormControl isDisabled isInvalid>
          <InputGroup>
            <InputLeftAddon children={ <FaUserAlt /> } />
            <Input placeholder="请输入用户名" />
          </InputGroup>
          <FormHelperText fontSize="xs">用户名是必填项</FormHelperText>
        </FormControl>
        <InputGroup>
          <InputLeftAddon children={ <FaLock /> } />
          <Input type="password" placeholder="请输入密码" />
          <InputRightAddon children={ <FaCheck /> } />
        </InputGroup>
        <RadioGroup defaultValue="0">
          <Stack direction="row" spacing="4">
            <Radio value="0"></Radio>
            <Radio value="1"></Radio>
          </Stack>
        </RadioGroup>
        <Select placeholder="请选择学科">
          <option value="Java">Java</option>
          <option value="大前端">大前端</option>
        </Select>
        <Flex>
          <Switch id="deal" mr="3" />
          <FormLabel htmlFor="deal">是否同意协议</FormLabel>
        </Flex>
        <Button _hover={{ bgColor: 'tomato' }} colorScheme="teal">注册</Button>
      </Stack>
    </form>
  )
}

选项卡组件的使用

components/Form.js

jsx
import React from "react";
import { Box, Tabs, Tab, TabList, TabPanels, TabPanel, Image } from "@chakra-ui/react";
import SignUp from "./SignUp";
import SignIn from "./SignIn";

import chakraUILight from '../assets/images/chakra-ui-light.png';

export default function Form () {
  return (
    <Box bgColor="gray.200" p={3} boxShadow="lg" borderRadius="lg">
      <Image w={ 250 } mx="auto" mt="2" mb="6" src={ chakraUILight } />
      <Tabs isFitted>
        <TabList>
          <Tab _focus={{ boxShadow: 'none' }}>注册</Tab>
          <Tab _focus={{ boxShadow: 'none' }}>登录</Tab>
        </TabList>
        <TabPanels>
          <TabPanel>
            <SignUp />
          </TabPanel>
          <TabPanel>
            <SignIn />
          </TabPanel>
        </TabPanels>
      </Tabs>
    </Box>
  )
}

components/SignIn.js

jsx
import React from "react";
import {
  Input,
  InputGroup,
  InputLeftAddon,
  InputRightAddon,
  Stack,
  FormControl,
  FormHelperText,
  Button
} from "@chakra-ui/react";
import { FaUserAlt, FaLock, FaCheck } from 'react-icons/fa';

export default function SignIn () {
  return (
    <form>
      <Stack spacing="6">
        <FormControl isDisabled isInvalid>
          <InputGroup>
            <InputLeftAddon children={ <FaUserAlt /> } />
            <Input bgColor="white" placeholder="请输入用户名" />
          </InputGroup>
          <FormHelperText fontSize="xs">用户名是必填项</FormHelperText>
        </FormControl>
        <InputGroup>
          <InputLeftAddon children={ <FaLock /> } />
          <Input bgColor="white" type="password" placeholder="请输入密码" />
          <InputRightAddon children={ <FaCheck /> } />
        </InputGroup>
        <Button _hover={{ bgColor: 'tomato' }} colorScheme="teal">登录</Button>
      </Stack>
    </form>
  )
}

components/SignUp.js

jsx
import React from "react";
import {
  Input,
  InputGroup,
  InputLeftAddon,
  InputRightAddon,
  Stack,
  FormControl,
  FormHelperText,
  RadioGroup,
  Radio,
  Select,
  Switch,
  FormLabel,
  Flex,
  Button
} from "@chakra-ui/react";
import { FaUserAlt, FaLock, FaCheck } from 'react-icons/fa';

export default function SignUp () {
  return (
    <form>
      <Stack spacing="6">
        <FormControl isDisabled isInvalid>
          <InputGroup>
            <InputLeftAddon children={ <FaUserAlt /> } />
            <Input bgColor="white" placeholder="请输入用户名" />
          </InputGroup>
          <FormHelperText fontSize="xs">用户名是必填项</FormHelperText>
        </FormControl>
        <InputGroup>
          <InputLeftAddon children={ <FaLock /> } />
          <Input bgColor="white" type="password" placeholder="请输入密码" />
          <InputRightAddon children={ <FaCheck /> } />
        </InputGroup>
        <RadioGroup defaultValue="0">
          <Stack direction="row" spacing="4">
            <Radio bgColor="white" value="0"></Radio>
            <Radio bgColor="white" value="1"></Radio>
          </Stack>
        </RadioGroup>
        <Select bgColor="white" placeholder="请选择学科">
          <option value="Java">Java</option>
          <option value="大前端">大前端</option>
        </Select>
        <Flex>
          <Switch id="deal" mr="3" />
          <FormLabel htmlFor="deal">是否同意协议</FormLabel>
        </Flex>
        <Button _hover={{ bgColor: 'tomato' }} colorScheme="teal">注册</Button>
      </Stack>
    </form>
  )
}

布局组件的使用

components/Card.js

jsx
import React from 'react';
import {
  Box,
  Image,
  Badge,
  Text,
  Stack,
  Flex,
  Button
} from '@chakra-ui/react';
import ChakraUI from '../assets/images/chakra-ui.png';
import { AiFillStar } from 'react-icons/ai';

export default function Card () {
  return (
    <Box
      w={ 400 }
      margin="0 auto"
      borderRadius="lg"
      boxShadow="lg"
      bgColor="gray.200"
      overflow="hidden"
    >
      <Image src={ ChakraUI } />
      <Box
        p={ 3 }
      >
        <Stack direction="row" align="center">
          <Badge variant="solid" colorScheme="teal" borderRadius="full" px="2">New</Badge>
          <Badge variant="solid" colorScheme="teal" borderRadius="full" px="2">React</Badge>
          <Badge variant="solid" colorScheme="teal" borderRadius="full" px="2">Chakra-UI</Badge>
          <Text>月落</Text>
        </Stack>
        <Text as="h3" pt={ 3 } pb={ 2 } color="gray.500" fontSize="xl" fontWeight="semibold">Chakra-UI 框架专题课程</Text>
        <Text fontWeight="light" fontSize="sm" lineHeight="tall">
          xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
          xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
          xxxxxxxxxxxxxxxxxxxxxxx
          xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        </Text>
        <Flex align="center" mt={ 2 }>
          <Flex color="teal.500">
            <AiFillStar />
            <AiFillStar />
            <AiFillStar />
            <AiFillStar />
          </Flex>
          <AiFillStar />
          <Text ml={ 1 }>100 评论</Text>
        </Flex>
      </Box>
      <Button w="100%" colorScheme="teal"> 登录</Button>
    </Box>
  )
}

App.js

jsx
import React from 'react';
import { Box } from '@chakra-ui/react';
import Card from './components/Card';

function App () {
  return (
    <Box w={ 500 } h={ 500 } margin="30px auto">
      <Card />
    </Box>
  );
}

export default App;

表单和卡片的颜色兼容

App.js

jsx
import React from 'react';
import { Box, Button, useColorMode, Flex } from '@chakra-ui/react';
import Form from './components/Form';
import Card from './components/Card';

function App () {
  const { toggleColorMode } = useColorMode();

  return (
    <Box>
      <Button
        colorScheme="teal"
        mt="10px"
        ml="10px"
        mb="30px"
        onClick={toggleColorMode}
      >
        切换模式
      </Button>
      <Flex width="100%">
        <Box width={ 400 }>
          <Form />
        </Box>
        <Box width={ 400 } ml="30px">
          <Card />
        </Box>
      </Flex>
    </Box>
  );
}

export default App;

components/Card.js

jsx
import React from 'react';
import {
  Box,
  Image,
  Badge,
  Text,
  Stack,
  Flex,
  Button,
  useColorModeValue
} from '@chakra-ui/react';
import ChakraUI from '../assets/images/chakra-ui.png';
import { AiFillStar } from 'react-icons/ai';

export default function Card () {
  const bgColor = useColorModeValue('gray.200', 'gray.700');
  const textColor = useColorModeValue('gray.700', 'gray.100');

  return (
    <Box
      w={ 400 }
      borderRadius="lg"
      boxShadow="lg"
      bgColor={ bgColor }
      overflow="hidden"
    >
      <Image src={ ChakraUI } />
      <Box
        p={ 3 }
      >
        <Stack direction="row" align="center">
          <Badge variant="solid" colorScheme="teal" borderRadius="full" px="2">New</Badge>
          <Badge variant="solid" colorScheme="teal" borderRadius="full" px="2">React</Badge>
          <Badge variant="solid" colorScheme="teal" borderRadius="full" px="2">Chakra-UI</Badge>
          <Text color={ textColor }>月落</Text>
        </Stack>
        <Text as="h3" pt={ 3 } pb={ 2 } color={ textColor } fontSize="xl" fontWeight="semibold">Chakra-UI 框架专题课程</Text>
        <Text fontWeight="light" fontSize="sm" color={ textColor } lineHeight="tall">
          xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
          xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
          xxxxxxxxxxxxxxxxxxxxxxx
          xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        </Text>
        <Flex align="center" mt={ 2 }>
          <Flex color="teal.500">
            <AiFillStar />
            <AiFillStar />
            <AiFillStar />
            <AiFillStar />
          </Flex>
          <AiFillStar />
          <Text color={ textColor } ml={ 1 }>100 评论</Text>
        </Flex>
      </Box>
      <Button w="100%" colorScheme="teal"> 登录</Button>
    </Box>
  )
}

components/Form.js

jsx
import React from "react";
import {
  Box,
  Tabs,
  Tab,
  TabList,
  TabPanels,
  TabPanel,
  Image,
  useColorModeValue
} from "@chakra-ui/react";
import SignUp from "./SignUp";
import SignIn from "./SignIn";

import chakraUILight from '../assets/images/chakra-ui-light.png';
import chakraUIDark from '../assets/images/chakra-ui-dark.png';

export default function Form () {
  const bgColor = useColorModeValue('gray.200', 'gray.700');
  const chakraUI = useColorModeValue(chakraUILight, chakraUIDark);


  return (
    <Box bgColor={ bgColor } p={3} boxShadow="lg" borderRadius="lg">
      <Image w={ 250 } mx="auto" mt="2" mb="6" src={ chakraUI } />
      <Tabs isFitted>
        <TabList>
          <Tab _focus={{ boxShadow: 'none' }}>注册</Tab>
          <Tab _focus={{ boxShadow: 'none' }}>登录</Tab>
        </TabList>
        <TabPanels>
          <TabPanel>
            <SignUp />
          </TabPanel>
          <TabPanel>
            <SignIn />
          </TabPanel>
        </TabPanels>
      </Tabs>
    </Box>
  )
}