Hacker News 关注 CSS 类前缀选择器,但真正的考验尚未到来
Hacker News 关注到一项 CSS 提案:它用了两年多时间,从开发者的抱怨逐步发展为已获接受的标准方向。类前缀选择器将允许作者匹配共享某个前缀的独立类标记,潜在语法可简洁如 .icon-*。
这听起来只是一个小便利。更深层的争议在于,浏览器是否应理解工具框架、图标库和应用团队早已广泛使用的命名模式。
如今,作者必须枚举每一个相关类、添加一个共享基础类,或依赖脆弱的属性选择器变通方案。CSS 工作组已接受这一核心用例,但接受并不等于浏览器支持。在提案真正进入生产网站之前,测试、规范文本、实现工作和互操作性仍是必须跨越的关卡。
Hacker News 实际发现了 CSS 提案中的什么
新闻并不是浏览器突然发布了通配类选择器。真正有意义的变化,是 CSS 工作组接受了这个问题。
Lea Verou 于 2024 年 2 月 26 日提出了相关的 CSSWG 提案。她描述了一种反复出现的需求:匹配共享相同前缀的单独类名。
在参与者讨论用例、语法和更广泛的属性选择器问题期间,该议题一直保持开放。如今它已关闭,带有“Accepted by CSSWG Resolution”标签,并被分配至 Selectors Level 5。
这一状态很重要。它意味着工作组同意 CSS 应当解决该用例,但不意味着暂定的 .prefix-* 写法已经成为稳定的 Web 标准。
该议题还带有“Needs Testcase (WPT)”标签。WPT 指 Web Platform Tests,即浏览器用于验证互操作行为的共享测试套件。
开发部分没有列出关联的 pull request。公开的 Selectors Level 5 草案也尚未将这一特性表述为已完成、可部署的选择器。
这些细节界定了事件本身。一项长期提案跨过了重要的标准门槛,但其实现流程仍未完成。
该提案聚焦于类标记,而非完整 class 属性中的任意文本。这一区别既解释了它的实用性,也说明了现有变通方案为何不足。
请看下面的标记:
开发者可能想通过一条规则匹配每个以 icon- 开头的类标记。目标类族可能包括 icon-alert、icon-search,以及数百个其他图标。
提议中的类前缀选择器可直接表达这类集合:
该示例描述的是预期模型,而非可用于生产环境的语法。在规范、测试和浏览器就其行为达成一致前,作者不应部署它。
现有的属性选择器看起来极为相似:
但 ^= 检查的是完整属性值是否以给定文本开头。它不会独立检查每一个类标记。
该规则可匹配这个元素:
却会漏掉这个:
开发者通常会用两个选择器加以补偿:
第一个处理开头处的匹配标记,第二个则搜索空格后的匹配标记。
这一模式在常见 HTML 情形下有效,但它要求开发者针对序列化文本进行推理。类选择器本应针对类进行推理。
因此,该提案瞄准了文档模型与选择器语言之间真实存在的缺口。HTML 将 class 视为空格分隔的标记集合,而子字符串选择器处理的是序列化后的属性值。
在提供的快照中,这则 Hacker News 条目获得了 6 个积分和 1 条评论。讨论规模有限,因此不能据此证明开发者已形成广泛共识。
它的价值在于别处。这篇帖子将注意力引向了一项标准决定,否则它可能仍会淹没在一个持续多年的 GitHub 议题之中。
为什么工具框架和图标库感受到压力
该提案给当前为表达一个概念性类族而重复共享样式、或要求额外标记的库带来了压力。
工具框架会将属性与取值的关系编码在诸如 pt-6 或 space-y-4 的名称中。图标系统则使用 fa-* 和 bi-* 等类族。
这些命名系统形成两类样式。每个类都需要针对其值的声明,而完整的类族通常又共享基础声明。
例如,一个图标类族可能需要通用的显示、尺寸、对齐或渲染规则。具体图标类随后提供各自的字形或图像引用。
没有前缀匹配时,库作者有几种并不完美的选择:枚举每一个类、要求使用单独的基础类,或操作完整属性字符串。
枚举会生成这样的选择器:
构建工具可以生成这份列表。生成减少了手动输入,但不会消除生成出的字节,也不会消除作者必须维护的关系。
第二种方法将通用行为与具体取值分开:
这种设计明确,而且通常很合理。但它要求使用者为了一个可见组件记住两个类。
Bootstrap Icons 采用了这种通用模式:使用基础 bi 类和具体图标类。CSSWG 提案以此类系统为证据,说明缺失的选择器确实给作者带来了实际摩擦。
类前缀选择器可支持这样的标记:
类族选择器可提供共享行为,而 .icon-alert 则提供其独特声明。
这并不自动意味着单类标记更优。基础类可以传达意图、简化调试,并避免过于宽泛的类族规则。
该提案只是为作者提供了另一种表达方式。库可以决定,显式基础类还是由前缀推断出的类族更适合其契约。
工具优先 CSS 带来了类似压力。像 pt- 这样的前缀编码了属性类别,而后缀则标识具体取值。
框架可使用类族选择器建立共享自定义属性、包含规则或其他基础行为,具体类再提供各自的值。
即时节省看上去或许不大。结构性收益更重要,因为样式表能够表达已经嵌入类名中的同一分组关系。
这正是该提案并非仅是语法糖的原因。当语法让作者能够删除生成列表或冗余标记时,它就会带来架构层面的改变。
不过,这项特性不会取代 Tailwind、Bootstrap、Sass、PostCSS 或构建时提取。这些工具解决的问题远比匹配一个标记前缀更广泛。
例如,Tailwind 会根据配置的工具类和检测到的使用情况生成声明。原生选择器不会为每个工具类生成特定取值的声明。
浏览器可以匹配 .pt-*,但无法推断每个后缀的含义。样式表仍需要规则,将受支持的名称映射到有效的属性值。
因此,类前缀选择器解决的是分组问题,而不是任意工具类生成。声称它会消除 CSS 构建工具的说法夸大了其范围。
受影响的受众也不限于框架维护者。应用团队经常使用 status-*、theme-*、language-* 或 priority-* 等名称。
文档系统可能会在代码块上输出 language-javascript 和 language-python 类。HTML 规范本身也建议代码示例采用 language- 命名约定。
即使其他类出现在前面,语法高亮工具仍需识别语言标记。Verou 将此作为 Prism 的一个实际问题引用。
维护大型前端的团队应当关注这一点,因为约定会变成基础设施。一旦数千个模板依赖某种命名模式,每一种变通方案都会更难调整。
维护这些决策同样需要可靠的内部文档。一个可搜索的工程知识库可以将选择器约定与组件和迁移说明一并保存。
这项标准决定给框架和库维护者带来的是长期压力,而非立即的迁移压力。他们必须决定前缀关系是否构成有意义的公共契约。
该机制修复的是标记匹配,而非只是更短的语法
其核心机制是具备标记感知能力的前缀匹配,这与在 `class` 属性原始文本中搜索有着根本区别。
CSS 已包含多种属性选择器。选择器规范定义了用于精确值、空格分隔标记、前缀、后缀和子字符串的运算符。
每种运算符回答的问题不同。[class~="button"] 查找完整的 button 标记,而 [class^="button-"] 检查完整属性值的开头。
CSS 所缺少的是一种组合操作。作者需要从空格分隔的列表中选择一个标记,然后检验该标记是否以某个前缀开头。
原始议题考虑了两种路径。其一是扩展熟悉的类选择器,并引入通配符语法,例如 .foo-*。
另一种是增加一种属性运算符,组合 ~= 和 ^= 的行为。提议的形式包括 ~^=、^~= 和 ^~。
类符号更易阅读,因为它仍处于 CSS 现有的类选择器语汇之中。以点号开头的规则清楚表明其目标是类。
组合属性运算符则更通用。当 class 以外的属性包含空格分隔的值时,它同样可以适用。
通用性也会带来成本。新运算符必须符合 CSS 解析规则、保持易懂,并避免让已经在学习多种属性运算符的作者感到困惑。
通配类语法也会引出超越美学的问题。规范必须定义转义、匹配边界、大小写敏感性、无效输入和特异性。
特异性决定多个选择器匹配时哪个声明胜出。新的选择器必须能与普通类、属性、伪类和嵌套规则并存,并具有可预测的行为。
标准流程还必须决定该选择器在浏览器 API 中的行为。querySelector()、matches() 和样式表解析都会使用选择器语法。
无效选择器的行为很重要,因为不受支持的语法可能使一个选择器列表失效。作者需要一种可靠方式来使用该特性,而不会意外丢弃无关规则。
特性检测是另一个实际问题。CSS 支持通过 @supports selector(...) 检查浏览器是否识别某个选择器。
未来的渐进增强模式可能类似这样:
在最终语法发布前,这一示意仍属假设。它说明了在开发者能够编写安全回退方案前,解析细节为何至关重要。
性能问题值得谨慎对待,但不应沦为猜测。浏览器已经维护了经过优化的类和属性匹配机制。
具备标记感知能力的前缀操作并不必然缓慢。其成本取决于引擎索引策略、样式表模式和最终规范选择。
同样,这项特性也不会天生迫使浏览器在每次样式重新计算时,扫描每个元素上的每一个类。实现者可以开发索引和匹配捷径。
只有浏览器原型和 Web Platform Tests 能验证这些假设。标准获采纳提供的是方向,而非性能证据。
该提案最有力的论据是语义一致性。开发者会将 class="card icon-alert muted" 理解为三个 token,而不是一个包含空格的字符串。
普通的 .icon-alert 已经采用这种 token 模型。将其扩展到一个 class 家族,能够保持心智模型的一致。
这种语义契合也提升了可审查性。.icon-* 会立刻表明预期的命名空间或家族,而配对的属性变通方案则需要更仔细地检查。
不过,简洁的语法可能掩盖宽泛的匹配范围。一条家族规则可能影响应用中每个以短前缀开头的 class。
这不是解析器缺陷,而是样式表治理问题,类似于过于宽泛的类型选择器或命名松散的自定义属性。
这一机制为 CSS 提供了更简洁的原语。它并不能决定团队是否会谨慎地使用这一原语。
真正的风险是 CSS 泄漏,而非通配符字符
前缀选择器可以减少脆弱代码,却也更容易造成意外耦合,因此在采用后,命名规范会变得更加重要。
怀疑者的反应很直接。如果一个选择器匹配开放式的家族,未来的 class 可能会继承其作者从未预期的样式。
假设某个设计系统定义了这条规则:
数月后,另一个团队为分析或应用状态添加了 card-payment-error。尽管用途不同,这个 class 仍会加入该样式家族。
基础 class 可以避免这种歧义:
标记明确说明该元素是一个 card。具体的 class 则增加了独立的含义。
前缀匹配会从拼写中推断成员资格。它可以很简洁,但也会让命名约定变成可执行的关系。
这种区别类似于编程中的结构化类型。一个名称之所以符合条件,是因为它具有预期的形态,而非作者明确声明了其成员资格。
这在受控命名空间中可以很好地运作。当短前缀跨越产品、遗留模块、第三方 widget 或由不同团队独立管理的范围时,风险就会增加。
围绕这篇链接文章的早期公开反应中已经出现了这一担忧。一位 Reddit 评论者将这种担心概括为更多“leaky css”的机会。
这一反应并非反对标准的证据。它指出了规范无法替应用团队解决的权衡。
库需要将前缀家族记录为稳定的 API。一旦 .icon-* 具有共享行为,任何以 icon- 开头的新 class 都会进入这份契约。
重构也不再那么局部。重命名一个 class,可能同时改变其特定规则以及所有匹配它的通配符家族规则。
开发者工具需要清晰地呈现这些关系。检查器应显示 .icon-alert 匹配了一个家族选择器,而不仅是其精确选择器。
搜索工具、lint 工具和代码智能功能可能也需要类似更新。当一个选择器代表的是不断扩展的集合而非固定名称时,静态分析会变得更难。
该提案还可能鼓励作者在 class 名称中编码更多数据。这种模式已经很常见,但原生支持可能会增强其吸引力。
CSSWG 参与者质疑,一些键值关系是否应改用 data-* 属性。例如,data-pt="6" 会将属性和值在结构上分开。
这种表示更明确,但也更冗长。它可能无法与现有框架约定或基于 class 的工具集成。
没有任何一种模型在所有场景中都更胜一筹。class 仍适合用于分组和样式挂钩,而 data 属性可以表示状态或应用数据。
class 前缀选择器不应成为把每种状态都塞进压缩 class 名称的借口。原生匹配并不会消除语义设计上的选择。
过渡期间还存在兼容性风险。作者不能假定标准获采纳就意味着该语法已能在各浏览器中使用。
在没有回退方案的情况下使用未被识别的选择器,可能会悄然移除预期样式。生产环境的采用应等待有文档记录的支持与互操作性证据。
开发者也应避免在语法稳定之前照搬示例。该 issue 提出了 .foo-*,但工作组在编辑规范时可能会修订语法。
即使已有一个引擎实现该功能,团队仍应检查其他引擎是否以相同方式处理边界情况。CSS 的历史上,有些功能花了多年才达到可靠的互操作性。
Hacker News 的叙述方式可能会把这些阶段压缩成一个标题。“未来的 CSS”是恰当的,但“现在就能用的新 CSS”则会造成误导。
保守的应用团队应在这种结构传达重要含义时,继续使用显式基础 class。当 class 家族是有限的,生成选择器列表依然可行。
当前的属性变通方案在受控标记中仍可使用。作者必须记住,它依赖空白符和属性序列化,而非直接的 token 语义。
没有一条迁移规则适用于每个代码库。该功能改善了可用语言,但架构仍决定它是否能改善应用。
Class 前缀选择器发布前必须发生什么
三个信号将决定这个已获采纳的想法能否成为可靠的 CSS:规范文本、共享测试和可互操作的浏览器实现。
第一个信号是对 Selectors Level 5 的具体编辑。草案需要规范性的语法与匹配规则,而不只是一个链接到的 GitHub 决议。
规范性文本定义了合规实现必须执行的行为。它应明确选择器形式、token 边界、转义、特异性,以及在选择器 API 中的行为。
这一编辑将更有力地表明 .prefix-* 或后续语法正在走向实现。不同的语法则会削弱基于当前示例的假设。
第二个信号是 Web Platform Tests 的进展。该 issue 的测试标签表明,工作组期待可执行的覆盖。
测试应包括 class 位于属性中不同位置、多个匹配 token、转义字符、大小写行为和无效语法。
它们还应覆盖 JavaScript 选择器 API。如果样式表和 querySelector() 对同一语法存在分歧,那么一个 CSS 功能仍是不完整的。
广泛的测试套件将增强人们对浏览器团队共享同一解释的信心。缺失或反复变动的测试则意味着设计细节尚未解决。
第三个信号是跨浏览器引擎的实现。一个实验性构建可以证明可行性,但无法确立 Web 兼容性。
开发者应关注 Chromium、Gecko 和 WebKit 的 issue 跟踪器,了解实现工作。发布说明和兼容性数据将比社交关注度更重要。
跨引擎可用性将强化该提案的架构价值。长期仅有单一引擎支持,则会让它停留在渐进增强的领域。
框架实验提供了额外的采用线索,尽管它们应排在这三个技术信号之后。维护者可以测试家族选择器是否能减少输出或简化公开标记。
有用的衡量指标包括生成的选择器大小、构建复杂度、迁移成本和调试清晰度。这些结果比计算一个选择器中字符数量更重要。
框架采用并非该功能成功的必要条件。较小的设计系统、图标库和语法高亮器也能独立受益。
HTML 语言 class 示例可能尤其具有参考价值。它检验 token 感知匹配是否能改进一个超出 utility-first 样式范围的既有约定。
开发者不应期待该提案产生任意模式匹配。讨论涉及的是单个 class token 上的前缀,而不是 CSS 中的正则表达式。
他们也应避免假定后缀和子字符串通配符会同时到来。更广泛的通配符设计需要独立的论证与规范工作。
目前,生产代码应将该选择器视为一个正在开发、已获采纳的方向。团队可以在不发布未获支持语法的前提下评估命名约定。
这种准备仍可能很有用。审查前缀究竟代表有意设计的家族、偶然的相似性,还是两者兼而有之。
记录哪些前缀充当公开的样式契约。识别那些基础 class 传达的含义,否则推断会将其隐藏。
针对重新排序的 class 和意外空白符测试当前的属性变通方案。许多代码库会发现,所谓的前缀匹配实际上依赖 token 的位置。
原生支持到来后,应从边界清晰、所有权明确的命名空间开始迁移。图标家族和生成的语言标识符,比通用前缀有更明确的边界。
在支持仍不均衡时使用功能检测。保留回退方案,直到兼容性数据显示服务于你受众的浏览器行为一致。
当浏览器原型出现时,Hacker News 很可能会重新讨论这一选择器。那时的讨论应聚焦测试、行为和互操作性,而非仅仅是新奇性。
该提案的重要性来自现代 CSS 中反复出现的一种模式。浏览器正在吸收作者过去通过预处理器、生成代码或脆弱的选择器技巧近似实现的能力。
这项变更比嵌套、容器查询或 :has() 更为狭窄。其范围小反而可能是优势,因为问题和预期行为都异常具体。
剩余工作同样具体。编辑者必须写出规则,测试作者必须捕捉其边界情况,浏览器团队则必须实现同样的结果。
如果这些步骤达成一致,开发者将获得一种直接按前缀定位多个 CSS class 的方式。如果它们出现分歧,显式基础 class 仍是更安全的契约。
今天正确的行动是观察,而非立即替换。审查该提案,检查你的 class 命名空间,并识别 token 感知匹配在哪些地方能消除真实的维护成本。
然后按顺序关注这三个信号:规范性的规范文本、全面测试和多个浏览器实现。你自己代码库中的哪个前缀家族最能提供清晰的互操作性测试?



