Next.js搭配styled-components时Less/CSS变量随机未定义问题
你现在混用了三套完全独立的变量机制,才会出现「变量随机生效」的假象,不存在随机失效,所有现象都有明确对应规则:
- Less的
@前缀变量是编译时变量,只在Less编译阶段生效,编译后会被直接替换为静态值,不会自动注入到浏览器运行时环境,也不会自动转成原生CSS支持的--前缀自定义属性。 - 你在
theme.ts里写的var(--bold-font)这类语法,调用的是浏览器原生CSS自定义属性,和你在Less里定义的@bold-font没有任何默认关联。 - styled-components的
theme对象是React Context注入的运行时JS对象,本身和Less、原生CSS变量也没有默认绑定关系。
你遇到的@white生效、@asd不生效本质原因:
Less编译时会自动删除所有未在Less样式规则中实际使用的
@变量,且你从未手动将需要用到的@变量映射为:root下的原生CSS变量。@white能生效只是刚好其他代码(比如第三方UI库、其他全局样式文件)定义了同名的--white原生CSS变量碰巧命中,@asd没有对应的同名CSS变量被注入,自然识别失败。字体类变量偶发生效也是同理,全靠是否有同名CSS变量被其他资源偶然注入。
二选一即可,不要混写:
方案1:全量走styled-components theme传值(最省事,无兼容问题)
直接把字体、色值等样式常量直接定义在theme.ts里,完全绕开Less变量和原生CSS变量,不需要额外做映射:
// theme.ts 修正后示例 const theme = { font: { weight: { regular: 350 }, family: { bold: "'GothamRounded, Bold', Arial, sans-serif", medium: "'GothamRounded, Medium', Arial, sans-serif", light: "'GothamRounded, Light', Arial, sans-serif", book: "'GothamRounded, Book', Arial, sans-serif", roboto: 'Roboto, sans-serif', }, }, // 其他色值、尺寸变量直接写在这里 } export default theme
你原有styled组件里的调用写法font-family: ${({ theme }) => theme.font.family.book};不需要改,直接就能拿到正确值,不会出现undefined。
方案2:保留Less变量+原生CSS变量写法
如果要保留var()调用的写法,必须在global.less里手动把所有需要全局调用的Less变量显式映射为:root下的原生CSS变量,Less不会自动帮你做这个转换:
// global.less 引入variables.less后追加以下代码 :root { --bold-font: @bold-font; --medium-font: @medium-font; --light-font: @light-font; --book-font: @book-font; --white: @white; --asd: @asd; // 所有需要在styled组件里用var()调用的变量,都要在这里做显式映射 }
映射完成后,你theme里写的var(--xxx)就能准确找到对应值,不会出现识别失败的问题。
如果修复后仍有个别变量返回undefined,检查你的ThemeProvider是否完整包裹了所有业务组件,在Provider外层渲染的组件拿不到Context里的theme值,也会返回undefined。
内容的提问来源于stack exchange,提问作者kakakakakakakk

