Tailwind Merge 与 CSS Modules 兼容异常问题求助
问题:Tailwind Merge 与 CSS Modules @apply 样式不兼容
在Next.js项目中使用Tailwind CSS时,尝试通过Tailwind Merge处理组件样式优先级,但发现当CSS Modules中用@apply整合Tailwind类时,Tailwind Merge无法正确合并样式,导致传入的自定义className无法覆盖组件默认样式。
解决方案
方案1:用原生Tailwind类替代CSS Modules @apply
直接在组件内定义默认样式映射,让Tailwind Merge能识别所有原生Tailwind类,正确处理优先级:
import type { FC, PropsWithChildren } from 'react'; import type { TextProps } from './props'; import { twMerge } from "tailwind-merge"; // 定义默认样式映射 const variantStyles = { h1: 'text-6xl font-semibold text-text-hover sm:text-2xl', h2: 'text-4xl font-semibold text-text-hover sm:text-xl', h3: 'text-3xl font-semibold sm:text-base', h4: 'text-xl font-semibold', h5: 'text-lg font-semibold', h6: 'text-base font-semibold', p: 'text-base text-text-main', span: 'text-base text-text-main', }; const colorStyles = { primary: 'text-primary-main', text: 'text-text-main', }; const Text: FC<PropsWithChildren & TextProps> = ({ color, variant = 'p', className, children, }) => { const HTMLTAG = variant; return ( <HTMLTAG className={twMerge(variantStyles[variant], color && colorStyles[color], className)} > {children} </HTMLTAG> ); }; export default Text;
此方案可直接删除原styles.module.scss文件,避免CSS Modules与Tailwind Merge的兼容性问题。
方案2:扩展Tailwind Merge配置识别CSS Modules类
若必须保留CSS Modules,可通过自定义Tailwind Merge配置,映射CSS Modules类到对应的Tailwind规则:
- 创建自定义merge函数:
import { extendTailwindMerge } from 'tailwind-merge'; const customTwMerge = extendTailwindMerge({ extend: { classGroups: { 'text-size': [ { 'h1': ['text-6xl', 'sm:text-2xl'] }, { 'h2': ['text-4xl', 'sm:text-xl'] }, { 'h3': ['text-3xl', 'sm:text-base'] }, { 'h4': ['text-xl'] }, { 'h5': ['text-lg'] }, { 'h6': ['text-base'] }, { 'p': ['text-base'] }, { 'span': ['text-base'] }, ], 'text-color': [ { 'primary': ['text-primary-main'] }, { 'text': ['text-text-main'] }, { 'h1': ['text-text-hover'] }, { 'h2': ['text-text-hover'] }, ], 'font-weight': [ { 'h1': ['font-semibold'] }, { 'h2': ['font-semibold'] }, { 'h3': ['font-semibold'] }, { 'h4': ['font-semibold'] }, { 'h5': ['font-semibold'] }, { 'h6': ['font-semibold'] }, ], }, }, }); export default customTwMerge;
- 在组件中使用自定义merge函数:
import classes from './styles.module.scss'; import type { FC, PropsWithChildren } from 'react'; import type { TextProps } from './props'; import customTwMerge from './customTwMerge'; const Text: FC<PropsWithChildren & TextProps> = ({ color, variant = 'p', className, children, }) => { const HTMLTAG = variant; return ( <HTMLTAG className={customTwMerge(`${classes[variant]} ${classes[color || '']}`, className)} > {children} </HTMLTAG> ); }; export default Text;
需手动维护CSS Modules类与Tailwind类的映射,适合必须保留CSS Modules的场景。
方案3:降低CSS Modules样式优先级
利用:where()伪类降低CSS Modules样式的优先级,让传入的className自然覆盖默认样式:
修改styles.module.scss:
:where(.h1) { @apply text-6xl font-semibold text-text-hover sm:text-2xl; } :where(.h2) { @apply text-4xl font-semibold text-text-hover sm:text-xl; } :where(.h3) { @apply text-3xl font-semibold sm:text-base; } :where(.h4) { @apply text-xl font-semibold; } :where(.h5) { @apply text-lg font-semibold; } :where(.h6) { @apply text-base font-semibold; } :where(.p), :where(.span) { @apply text-base text-text-main; } :where(.primary){ @apply text-primary-main; } :where(.text) { @apply text-text-main; }
:where()会将选择器优先级降至0,传入的Tailwind类(优先级为1)可直接覆盖,组件代码无需修改。
内容的提问来源于stack exchange,提问作者Ali Ehyaie
相关产品推荐
相关产品推荐

