FluentUI源码CSS变量生成位置及Emotion中生成该变量方法咨询
问题场景及代码
我希望基于Fluent Design System的Token,使用Emotion实现自定义UI组件库,以下是组件库的部分代码:
import { css } from '@emotion/react'; import { tokens } from '@fluentui/react-theme'; const smallSizeCss = css({ padding: buttonSpacingSmall + ' ' + tokens.spacingHorizontalM}); export const Button = (props: ButtonProps) => { const { size = 'medium', shape = 'rounded', appearence = 'default', disabled = false, iconOnly = false, iconPosition = 'before', children, } = props; if(size == 'small'){ buttonCss = { ...buttonCss, ...smallSizeCss } } return <button css={buttonCss}>{children}</button>; };
运行时出现var(--spacingHorizontalM) is not set的报错,现咨询两个问题:
- FluentUI源码中CSS变量的生成位置在哪里?
- 如何从源码获取这些Token的具体值,并在Emotion中生成对应的CSS变量?
解答
1. FluentUI源码中CSS变量的生成位置
FluentUI的CSS变量生成逻辑核心集中在@fluentui/react-theme包内:
- 基础Token的默认值定义在包内
src/theme.ts文件中,这里包含了间距、颜色、字体等所有核心设计Token的初始配置。 - Token转CSS变量的映射逻辑由
src/generateCSSVariables.ts中的generateCSSVariables函数处理,它会将Theme对象中的Token名称转换为对应的CSS变量名(比如spacingHorizontalM转为--spacingHorizontalM)。 - 最终这些CSS变量会通过
ThemeProvider组件注入到DOM中,通常挂载到根元素(:root)或ThemeProvider指定的容器节点,只有在ThemeProvider包裹的范围内,这些CSS变量才会生效。
2. 在Emotion中正确使用FluentUI Token并生成CSS变量
方式一:用ThemeProvider包裹应用(推荐)
tokens对象返回的是CSS变量引用(比如var(--spacingHorizontalM)),必须让ThemeProvider包裹整个应用,才能确保对应的CSS变量被注入到DOM:
import { ThemeProvider, tokens } from '@fluentui/react-theme'; import { Button } from './your-button-component'; function App() { return ( <ThemeProvider> <Button size="small">测试按钮</Button> </ThemeProvider> ); }
这样组件中使用tokens.spacingHorizontalM时,对应的CSS变量已存在,不会出现未定义报错。
方式二:直接获取Token的具体数值
如果不需要主题动态切换能力,可以直接从默认Theme对象中提取Token的原始值:
import { css } from '@emotion/react'; import { createTheme } from '@fluentui/react-theme'; const defaultTheme = createTheme(); // 直接拿到具体值,比如"16px" const smallSizeCss = css({ padding: `${buttonSpacingSmall} ${defaultTheme.spacingHorizontalM}` });
方式三:手动在Emotion中生成CSS变量
如果需要在局部注入CSS变量,可通过Emotion的css函数直接定义全局样式:
import { css } from '@emotion/react'; import { createTheme } from '@fluentui/react-theme'; const defaultTheme = createTheme(); const themeVariables = css` :root { --spacingHorizontalM: ${defaultTheme.spacingHorizontalM}; // 按需添加其他需要的Token变量 } `; // 在应用入口注入全局样式 function App() { return ( <> <style jsx global>{themeVariables}</style> <Button size="small">测试按钮</Button> </> ); }
内容的提问来源于stack exchange,提问作者hilodfulaidien
相关产品推荐
相关产品推荐

