全局组件样式配置
官方文档:Component Style
基础样式和修改器样式
大多数组件的样式由基础样式和修改器样式组成,修改器样式根据某些特性或状态更改其大小或视觉样式。
- 基础样式:默认样式
- 修改器样式:可以根据
props
切换的样式- 常用的修改器样式包括:
- Size:组件的尺寸(例如 small medium large)
- 根据
props.size
切换
- 根据
- Variant:组件的视觉风格(例如 outline、solid、ghost)
- 根据
props.variant
切换
- 根据
- Color scheme:组件的配色方案
- 根据
props.colorSchmeme
切换
- 根据
- Color mode:组件根据当前颜色模式更改其视觉样式
- Size:组件的尺寸(例如 small medium large)
- 常用的修改器样式包括:
样式配置对象
一个样式配置对象可以配置以下属性:
baseStyle
:基础样式对象sizes
:为每个尺寸设置样式对象variants
:为每个风格设置样式对象defaultProps
:默认样式配置,可配置的属性:size
:尺寸variant
:风格colorScheme
:配色方案colorMode
:强制的颜色模式
parts
:用于配置复合组件的样式
设置样式的方式有两种:
- 对象字面量
- 函数
- 函数接收组件的
props
作为参数,最终返回一个样式对象 props
包含:defaultProps
配置的属性- 使用组件时手动设置的属性
- 主题对象
theme
- 颜色模式
colorMode
- 函数接收组件的
一个组件的样式配置对象示例:
const Button = {
// 基础样式
baseStyle: {
// 可以使用样式属性配置
fontWeight: 'bold',
borderRadius: 'base'
},
// 尺寸样式(注意是带`s`的复数名称)
sizes: {
// 修改已有的尺寸样式
xs: {
h: '20px'
fontSize: "12px",
},
// 新增一个尺寸样式
sl: {
h: "56px",
fontSize: "lg",
px: "32px",
}
},
// 风格样式(注意是带`s`的复数名称)
variants: {
// 使用函数定义样式对象
solid: props => ({
// 根据 colorScheme 生成边线颜色
borderColor: props.colorScheme === 'teal' ? 'blue' : 'black',
// 根据 colorMode 生成背景色
bgColor: props.colorMode === 'dark' ? 'white' : 'black'
}),
},
// 默认 props
defaultProps: {
// 默认尺寸(注意不带`s`)
size: 'sl',
// 默认风格(注意不带`s`)
variant: 'solid',
// 默认配色风格
colorScheme: 'teal',
// 强制颜色模式(配置后 `props.colorMode` 将不会改变)
colorMode: 'dark'
}
}
Chakra 组件样式配置
通过主题对象的 components
属性修改或扩展 Chakra 组件的全局样式配置。
通常创建一个 theme
目录管理主题配置:
📁 theme
📄 index.js # 主题主入口
📁 components # 组件样式配置
📄 button.js # Button 按钮的样式配置
// theme/components/button.js
const Button = {
baseStyle: {
px: '20px',
py: '10px'
},
sizes: {
small: {
fontSize: '14px',
},
big: {
fontSize: '30px'
}
}
}
export default Button
// theme/index.js
import { extendTheme } from '@chakra-ui/react'
import Button from './components/button'
const theme = extendTheme({
components: {
Button
}
})
export default theme
// index.js
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import { ChakraProvider } from '@chakra-ui/react'
import theme from './theme'
ReactDOM.render(
<React.StrictMode>
<ChakraProvider theme={theme}>
<App />
</ChakraProvider>
</React.StrictMode>,
document.getElementById('root')
)
import { Button } from '@chakra-ui/react'
function App() {
return (
<div>
<Button size="xs">默认配置的 xs 尺寸</Button>
<Button size="small">自定义的 small 尺寸</Button>
<Button size="big">自定义的 big 尺寸</Button>
</div>
)
}
export default App
自定义组件样式配置
在主题中扩展自定义组件的样式配置需要做几件事情:
- 像 Chakra 组件一样将样式配置对象扩展到主题对象,一般
key
设置为组件名 - 在组件中使用 Chakra 组件包裹
- 在组件中调用钩子函数获取样式配置,传递给 Chakra 组件的
__css
属性useStyleConfig(themeKey, props)
钩子函数用于获取主题对象中组件的样式配置- 返回一个样式对象,用于传递给 Chakra 组件的
__css
属性 __css
属性设置的样式优先级低于手动通过组件的样式属性设置的样式themeKey
:theme.components
对象中的对应组件的key
props
:配置默认方案
- 返回一个样式对象,用于传递给 Chakra 组件的
// theme/components/content.js
// 文章内容样式配置
const content = {
baseStyle: {
bgColor: 'gray.200',
mt: '40px',
mx: 'auto'
},
sizes: {
small: {
fontSize: '12px',
lineHeight: '18px',
w: '30%',
p: '10px'
},
large: {
fontSize: '20px',
lineHeight: '36px',
w: '80%',
p: '20px'
}
},
variants: {
solid: {
border: '1px solid',
borderColor: 'gray.800'
},
card: {
boxShadow: 'md'
}
},
defaultProps: {
size: 'large',
variant: 'solid'
}
}
export default content
// theme/index.js
import { extendTheme } from '@chakra-ui/react'
import Content from './components/content'
const theme = extendTheme({
components: {
Content
}
})
export default theme
// components/Content.js
// 文章内容组件
import { Box, useStyleConfig } from '@chakra-ui/react'
function Content(props) {
const { children, size, variant } = props
const styles = useStyleConfig('Content', {
size: size,
variant: variant
})
return <Box __css={ styles }>{ children }</Box>
}
export default Content
// App.js
import Content from './components/Content'
function App() {
return (
<>
<Content size="small" variant="card">这是用于展示文章内容的 Content 组件</Content>
</>
)
}
export default App
复合组件样式配置
上面是设置 single part components(单部分组件) 的样式配置,如果一个组件由多个组件组成,就称为 multipart components(多部份组件或复合组件)。
复合组件设置样式配置与单个组件类似,主要区别是:
- 需要在样式配置对象中的
parts
属性中定义每个部分的part
key。- 可以是组件名称,或其它自定义的
key
- 可以是组件名称,或其它自定义的
- 需要为每个
part
提供baseStyle
、sizes
和variants
。 - 使用
useMultiStyleConfig
钩子函数,获取复合组件的样式配置对象,useMultiStyleConfig
接收的参数与useStyleConfig
一样- 它返回一个包含每个
part
的样式配置的对象 - 使用时向对应的单部分组件传递对应的
__css
- 也可以在复合组件的最外层,使用
StylesProvider
组件向上下文共享样式配置对象- 下级组件通过
useStyles
钩子函数获取上下文中的样式配置对象
- 下级组件通过
复合组件示例
// components/Article.js
// 文章复合组件
import { Box, Heading } from '@chakra-ui/react'
// 复合组件
function Article(props) {
const { title, content } = props
return (
<Box>
<Heading>{title}</Heading>
<Box>{content}</Box>
</Box>
)
}
export default Article
// App.js
import Article from './components/Article'
function App() {
return <Article title="文章标题" content="文章内容" />
}
export default App
样式配置
// theme/components/article.js
// 文章样式配置
const article = {
parts: ['article', 'title', 'content'],
baseStyle: {
article: {
mt: '40px',
mx: 'auto'
},
title: {
textAlign: 'center',
fontFamily: 'Microsoft YaHei'
},
content: {
fontFamily: 'sans-serif'
}
},
sizes: {
small: {
article: {
w: '50%',
p: '5px'
},
title: {
my: '10px'
},
content: {
lineHeight: '1.2em'
}
},
large: {
article: {
w: '80%',
p: '20px'
},
title: {
my: '20px'
},
content: {
lineHeight: '1.8em'
}
}
},
variants: {
solid: {
article: {
border: '1px solid',
borderColor: 'gray.800'
}
},
card: {
article: {
boxShadow: 'md',
}
}
},
defaultProps: {
size: 'large',
variant: 'solid'
}
}
export default article
应用到组件
// components/Article.js
// 文章复合组件
import { Box, Heading, useMultiStyleConfig } from '@chakra-ui/react'
// 复合组件
function Article(props) {
const { title, content } = props
const styles = useMultiStyleConfig('Article', {
variant: 'card'
})
return (
<Box __css={styles.article}>
<Heading __css={styles.title}>{title}</Heading>
<Box __css={styles.content}>{content}</Box>
</Box>
)
}
export default Article
使用上下文组件的方式
// App.js
import { StylesProvider, useMultiStyleConfig } from '@chakra-ui/react'
import Article from './components/Article'
function App() {
const styles = useMultiStyleConfig('Article', {
variant: 'card'
})
return (
<StylesProvider value={styles}>
<Article title="文章标题" content="文章内容"></Article>
</StylesProvider>
)
}
export default App
// components/Article.js
// 文章复合组件
import { Box, Heading, useStyles } from '@chakra-ui/react'
// 复合组件
function Article(props) {
const { title, content } = props
const styles = useStyles()
return (
<Box __css={styles.article}>
<Heading __css={styles.title}>{title}</Heading>
<Box __css={styles.content}>{content}</Box>
</Box>
)
}
export default Article