FluentUI的mergeStyles为何无法通过父类名+子ID选择器设置样式?
问题原因
FluentUI的mergeStyles工具底层基于@uifabric/merge-styles实现,核心规则是:调用mergeStyles时会自动生成一个唯一的CSS类名,你在配置中编写的所有选择器,默认都会作为这个生成类名的后代选择器拼接输出。
你编写的代码:
const RedLabelStyles = mergeStyles({ ".example #label": { color: "red" } });
最终生成的实际CSS规则为:
.css-xxxx .example #label { color: red; }
其中.css-xxxx是mergeStyles自动生成的唯一类名。当你把RedLabelStyles对应的类名挂载到.example节点上时,DOM结构为<div class="example css-xxxx">,生成的选择器要求.css-xxxx的内部包含.example节点,显然无法匹配,因此样式不生效。
而你直接使用#label作为选择器时,生成的规则为.css-xxxx #label,匹配的是.css-xxxx后代的#label节点,和你的DOM结构完全匹配,因此可以正常生效。
解决方法
有两种可行的写法:
方法1:使用&指代当前生成的类名
如果你需要保留.example的父类匹配限制,可以用&符指代mergeStyles自动生成的类名,和.example做类名组合:
const RedLabelStyles = mergeStyles({ "&.example #label": { color: "red" } });
该写法生成的CSS规则为.css-xxxx.example #label,可以正确匹配挂载了生成类名的.example节点下的#label元素。
方法2:使用:global()标记全局选择器
如果你不需要mergeStyles给选择器自动加生成类的前缀,可以将选择器包裹在:global()中,输出的规则和原生CSS完全一致:
const RedLabelStyles = mergeStyles({ ":global(.example #label)": { color: "red" } });
该写法生成的CSS规则就是你原本写的.example #label,和原生CSS效果完全相同。
内容的提问来源于stack exchange,提问作者user6118986
相关产品推荐
相关产品推荐

