如何基于html[lang]属性条件导入CSS字体(解决@import仅能顶层使用的限制)
嘿,这个问题我太熟悉了!你原来写的那种把@import嵌套在html[lang=ja]选择器里的代码,确实会因为@import必须放在CSS顶层的规则而失效。不过不用头疼,有几个完全不需要复杂构建流程的原生方案,既能满足“只下载当前语言所需字体”的需求,又符合CSS规范。
方案一:HTML中使用带media属性的<link>标签(最兼容)
这是我最常用的方案,简单直接,兼容性拉满。核心思路是利用<link>标签的media属性,让浏览器只有当文档匹配指定条件时才下载对应的字体样式表:
<!-- 仅当html的lang属性为ja时,才下载并应用这个字体样式表 --> <link rel="stylesheet" href="ja-font-styles.css" media="document(html[lang=ja])">
然后在ja-font-styles.css里只放日语字体的样式:
article { font-family: "Noto Sans JP", sans-serif; }
这样一来,只有当页面的<html lang="ja">时,浏览器才会下载ja-font-styles.css,进而触发字体的下载;其他语言环境下,这个<link>会被浏览器忽略,完全不会产生无用请求。
方案二:CSS顶层结合@import与属性选择器控制字体生效
如果你不想拆分多个CSS文件,想把所有逻辑放在一个CSS文件里,这个方案很合适。我们可以把@import放在顶层,然后用属性选择器控制字体样式的生效范围——因为浏览器只会下载实际被使用到的字体,所以未被应用的字体规则不会触发下载:
/* 顶层@import,符合CSS规范 */ @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100..900&display=swap'); /* 仅当html的lang为ja时,才给article应用日语字体 */ html[lang=ja] article { font-family: "Noto Sans JP", sans-serif; } /* 其他语言环境下用回退字体 */ html:not([lang=ja]) article { font-family: sans-serif; }
这里要注意:@import虽然是顶层的,但浏览器会判断字体是否被页面中的元素实际使用。如果当前页面lang不是ja,article用的是通用sans-serif,浏览器就不会下载Noto Sans JP字体,完美达到“避免无用下载”的目的。
方案三:用CSS条件导入(简洁但兼容性稍弱)
如果你的目标浏览器支持CSS Conditional Rules Level 4的特性,那这个方案最简洁——直接给@import加上条件判断,只有当条件满足时才执行导入:
/* 仅当html的lang属性为ja时,才导入字体样式 */ @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100..900&display=swap') when (document(html[lang=ja])); html[lang=ja] article { font-family: "Noto Sans JP", sans-serif; }
不过要注意,这个when条件的兼容性不如前两个方案,如果你需要兼容旧版浏览器,还是优先考虑前两个方案。
总的来说,这三个方案都不需要引入任何构建工具,完全用原生HTML/CSS就能实现,既能绕过@import不能嵌套的限制,又能精准控制字体的下载,避免浪费用户的带宽。
内容来源于stack exchange

