stylelint property-no-unknown 规则完全指南:拦截未知 CSS 属性并自定义白名单
2026/9/24 14:57:43 网站建设 项目流程

stylelint property-no-unknown 规则完全指南:拦截未知 CSS 属性并自定义白名单

【免费下载链接】stylelintA mighty CSS linter that helps you avoid errors and enforce conventions.项目地址: https://gitcode.com/gh_mirrors/st/stylelint

property-no-unknown 是 stylelint 中用于禁止未知(拼写错误或不存在的)CSS 属性的核心规则。本文将以 lib/rules/property-no-unknown/README.md 为骨架,结合 规则实现源码、测试用例 与底层 属性参考数据,深入讲解该规则的所有配置项、判定原理、忽略机制与扩展方式,帮助你将其正确接入项目并处理 SCSS/LESS、SVG、CSS-in-JS 等各类场景。

规则简介与定位

property-no-unknown 用于禁止未知属性,例如把color误拼成colr、手写一个尚未定义的属性名,都能被该规则捕获:

a { height: 100%; } /** ↑ * This property */

这里的height是已知属性,不会触发告警;但colrmy-property这类属性就会报错。该规则面向的是"属性名"本身是否合法,而不是属性值——值合法性的校验由declaration-property-value-no-unknown等其他规则负责。

规则定义在 lib/rules/property-no-unknown/index.mjs,其 ruleName 为property-no-unknown,默认消息为Unknown property "${property}"(见 index.mjs 第 20-22 行),并且支持 1 个 message 参数:未知属性的名字,可用于自定义告警文案。

判定原理:CSSTree Lexer 与已知属性集合

规则的"已知属性"判定并非简单查一个字符串表,而是两级机制(见 index.mjs 第 105-109 行):

  1. CSSTree Lexer 查询:通过lexer.getProperty(prop)判断该属性是否存在于 CSSTree 语法词典中。这个 lexer 由 lib/utils/getLexer.mjs 提供——它基于 css-tree 的fork机制构建,会合并@csstools/css-syntax-patches-for-csstree补丁与配置中的languageOptions.syntax扩展,并按语法定义做缓存。
  2. 历史已知属性回退previouslyKnownProperties(以及开启前缀检查时的previouslyKnownPrefixedProperties)记录了从 stylelint 迁移到 CSSTree 之前就被认定为已知的属性集合(约 130 余项),见 lib/reference/properties.mjs 第 813-954 行 与 第 956-1000 行,其中注释注明这些数据源于 stylelint issue #9065 的历史行为。当 CSSTree 词典尚未收录某些浏览器私有或提案阶段属性时,这一集合能避免误报。

由于判定依赖 CSSTree 语法参考(覆盖 CSS 规范直至 Editor's Draft 编辑草案),你可以通过过滤 CSSTree Syntax Reference 来查询哪些属性被认为是已知的,再用languageOptions配置扩展它(详见下文)。

默认忽略项:变量、前缀与描述符

规则在checkStatement中对每个声明做层层过滤(index.mjs 第 60-103 行),默认情况下以下内容不会告警:

各类变量

  • CSS 自定义属性:--custom-property(通过isCustomProperty判断);
  • SCSS 变量:$sass
  • LESS 变量:@less
  • SCSS 命名空间变量:namespace.$bgColor
  • SCSS/LESS 属性插值:#{$prop}@{prop}
  • LESS 嵌套属性(如border: { style: solid; })、LESS 的+/+_追加语法(如transform+: rotate(15deg))。

这些识别逻辑集中在 lib/utils/isStandardSyntaxProperty.mjs:它以@开头、以++_结尾、含插值、或为 SCSS 变量时均视为非标准属性而跳过。

厂商前缀属性

默认情况下-moz-*-webkit-*-khtml-*等带前缀的属性一律忽略(无论是否真的存在),因为前缀属性大量存在于旧代码中且风格多样。前缀提取由 lib/utils/vendor.mjs 的prefix()完成:匹配^-(-\w+-),命中即返回前缀字符串。将checkPrefixed设为true可关闭这一默认豁免。

CSS hacks 与描述符

  • 兼容 IE 的*property写法(如*width: 100px)会被跳过;
  • @font-face@position-try等 at-rule 内部的描述符(descriptor)声明会被isDescriptorDeclaration识别并跳过;
  • 自定义 at-rule 内的声明整体跳过(可能是描述符,测试用例中的@foo { bar: 0; }即为此意);
  • CSS-in-JS(经 customSyntax 解析)与模板字符串中的插值属性同样不会误报,测试见tests/index.mjs 第 319-362 行。

主选项:true

启用规则只需:

{ "property-no-unknown": true }

以下模式会被视为问题:

a { colr: blue; }
a { my-property: 1; }

以下模式不会被视为问题:

a { color: green; }
a { fill: black; }
a { -moz-align-self: center; }
a { -webkit-align-self: center; }
a { align-self: center; }

注意fill等 SVG 属性默认即被接受;colorCOLoR均被接受(属性名不区分大小写),而COLR会被拒绝——测试用例证实了属性判定的大小写处理行为(tests/index.mjs 第 12-17 行与第 69-75 行)。

可选次级选项详解

规则的选项校验在 index.mjs 第 31-45 行,通过validateOptions约束:ignorePropertiesignoreSelectorsignoreAtRules接受字符串或正则(isString | isRegExp),checkPrefixed接受布尔值。下面逐一说明。

ignoreProperties:按属性名放行

{ "ignoreProperties": ["array", "of", "properties", "/regex/"] }

字符串按字面量精确匹配,/regex/形式则按正则匹配。例如:

{ "property-no-unknown": [true, { "ignoreProperties": ["/^my-/", "custom"] }] }

以下模式都不会被视为问题:

a { my-property: 10px; }
a { my-other-property: 10px; }
a { custom: 10px; }

not-my-property: 1仍会报错(测试见tests/index.mjs 第 165-230 行)。该选项匹配由 lib/utils/optionsMatches.mjs 调用matchesStringOrRegExp完成,支持字符串与正则混合数组。常用于放行自定义属性前缀(如--之外的框架属性)、IE hack 或业务约定的私有属性。

ignoreSelectors:按选择器放行

{ "ignoreSelectors": ["array", "of", "selectors", "/regex/"] }

跳过对指定选择器下属性的检查。例如:

{ "property-no-unknown": [true, { "ignoreSelectors": [":root"] }] }

以下模式不会被视为问题:

:root { my-property: blue; }

注意:字符串必须与父选择器精确匹配。测试用例明确指出:import("path/to/file.css")这类带参数的选择器不会被字符串:import命中,必须改用正则/^:import/才能匹配(tests/index.mjs 第 264-312 行)。实际实现中,匹配的是decl.parent.selector(即直接父规则的选择器文本,见 index.mjs 第 87-95 行)。该选项对 CSS Modules 的:export:import块特别实用。

ignoreAtRules:按 at-rule 放行

{ "ignoreAtRules": ["array", "of", "at-rules", "/regex/"] }

忽略嵌套在指定 at-rule 内的属性。例如:

{ "property-no-unknown": [true, { "ignoreAtRules": ["supports"] }] }

以下模式不会被视为问题:

@supports (display: grid) { a { my-property: 1; } }

该选项通过findNodeUpToRoot从声明节点向上遍历祖先 at-rule 判断(index.mjs 第 97-103 行),因此深层嵌套也生效——测试用例验证了@supports内再套@media、以及@supports内嵌规则均被放行,而@media screen内的foo: 1仍会报错(tests/index.mjs 第 364-400 行)。正则写法[/^lay/]可匹配@layer。该选项常用于兼容条件特性检测块中的占位属性或非标准属性。

checkPrefixed:检查厂商前缀属性

默认false。设为true后,规则会像对待普通属性一样检查带前缀的属性——但注意,历史上真实存在过且被浏览器采用过的前缀属性不会报错,因为它们记录在previouslyKnownPrefixedProperties中。

{ "property-no-unknown": [true, { "checkPrefixed": true }] }

以下模式不会被视为问题(前缀属性被历史集合认定为已知):

a { -webkit-overflow-scrolling: auto; }

以下模式被视为问题(-moz-overflow-scrolling不属于任何浏览器实现过的前缀属性):

a { -moz-overflow-scrolling: center; }

测试用例进一步证实(tests/index.mjs 第 232-262 行):-webkit-overflow-scrolling-moz-box-flex-khtml-opacity-moz-align-self均被接受,而-moz-overflow-scrolling被拒绝——这正是previouslyKnownPrefixedProperties(约 200 项)在起作用。开启后如需继续放行某些前缀,可与ignoreProperties组合,例如:

{ "property-no-unknown": [true, { "ignoreProperties": ["-moz-overflow-scrolling"], "checkPrefixed": true }] }

自定义告警消息

该规则支持 1 个消息参数(未知属性名),可在配置中通过message覆盖默认文案:

{ "rules": { "property-no-unknown": [ true, { "message": "未知属性 \"{{property}}\"({{variable}})" } ] } }

具体写法请参考 docs/user-guide/configure.md 中message一节(其中说明了{{variable}}等占位符的转义规则)。消息中的{{property}}会被替换为实际的未知属性名。

扩展已知属性:languageOptions

当项目使用规范尚未收录或自定义的属性时,与其写一长串ignoreProperties,更推荐通过languageOptions.syntax.properties直接扩展 CSSTree 语法词典,让规则"认识"这些属性:

{ "languageOptions": { "syntax": { "properties": { "foo": "<color>" } } } }

自定义属性值语法与types组合使用还能定义更复杂的类型(参见 docs/user-guide/configure.md 中languageOptions一节):

{ "languageOptions": { "syntax": { "types": { "--foo()": "--foo( <length-percentage> )" }, "properties": { "top": "| <--foo()>" } } } }

从实现看(lib/utils/getLexer.mjs 第 22-53 行),languageOptions.syntax最终会与@csstools/css-syntax-patches-for-csstree补丁通过mergeSyntaxDefinitions合并,并fork出新的 CSSTree lexer;合并结果以 JSON 序列化为缓存键,同配置多次 lint 会复用缓存 lexer。这解释了两点:其一,扩展的属性能立即被 property-no-unknown 认可;其二,syntax.atRules别名会归一化为atrulessyntax.units会与内建单位合并,保证扩展语法与原生语法共存。

与其他规则协同与实战建议

  • 拼写检查property-no-unknowndeclaration-property-value-no-unknown(校验属性值)、property-no-vendor-prefix(强制移除前缀)、property-allowed-list/property-disallowed-list(属性白/黑名单)互为补充。前者管"属性存不存在",后者管"属性允不允许用"。
  • 按项目分层配置:基础配置中property-no-unknown: true保持默认严格;若项目确实存在my-*私有属性,优先用languageOptions声明其语法而非逐一 ignore;仅对临时性兼容代码使用ignoreSelectors/ignoreAtRules收窄范围。
  • 多语法场景:该规则对 SCSS/LESS 变量、插值、嵌套属性天然免疫(测试见tests/index.mjs 第 111-163 行),但前提是配置了对应的customSyntax(如postcss-scsspostcss-less),否则这些语法无法被正确解析。
  • CSS-in-JS 与 HTML:搭配postcss-html可检查<style>内联样式,style属性中的模板插值({{unknown}})会被跳过,而字面量未知属性会报错(tests/index.mjs 第 337-362 行)。

小结

property-no-unknown 的完整行为可用一张判定流水线概括:非标准语法属性 → 自定义属性 → 前缀属性(默认跳过)→ ignoreProperties → ignoreSelectors → ignoreAtRules → CSSTree lexer 已知属性 → previouslyKnownProperties 历史回退 → 报错(见 index.mjs 第 60-118 行)。掌握这条流水线,你就能精准预测任何一条声明是否会触发告警,并在ignorePropertiesignoreSelectorsignoreAtRulescheckPrefixedlanguageOptions.syntax.properties之间选出最合适的放行或扩展方案。

【免费下载链接】stylelintA mighty CSS linter that helps you avoid errors and enforce conventions.项目地址: https://gitcode.com/gh_mirrors/st/stylelint

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询