1. 引言
1.1. 背景
本节为非规范性内容。
[CSS21] 定义了一种条件分组规则,即 @media
规则,并且只允许在其内部使用样式规则(不允许其他 @-规则)。@media
规则提供了媒体专用样式表的能力,这也可以通过 @import
和 link
等样式表链接特性实现。
对 @media 规则内容的限制降低了其实用性;这迫使在媒体专用样式表中使用含有 @-规则等 CSS
特性的作者不得不为每种媒体分别使用独立的样式表。
本规范扩展了条件分组规则内容的规则,允许包含其他 @-规则,使作者能够在同一份样式表中,将含有 @-规则的 CSS 特性与媒体专用样式表结合使用。
本规范还定义了另一种条件分组规则 @supports,以满足作者和用户的需求。
@supports 规则允许 CSS 根据对 CSS 属性和值的实现支持情况进行条件处理。该规则使作者更容易使用新的 CSS 特性,并为不支持这些特性的实现提供良好的回退。这对于提供新布局机制的 CSS 特性,以及需要依据属性支持情况进行条件样式设置的其他场景尤为重要。
1.2. 模块交互
本模块替换并扩展了 @media 规则(见 [CSS21] 第7.2.1节),并纳入了 [MEDIAQUERIES-4] 第1节此前非规范性做出的修改。
2. 条件分组规则的处理
本规范定义了一些 CSS at-规则, 称为 条件分组规则, 它们将一个条件与一组其他 CSS 规则关联起来。这些不同的规则能够测试不同类型的条件,但在条件为真和条件为假时,它们内容的使用方式有共同点。
@media print{ /* hide navigation controls when printing */ #navigation{ display : none} }
会使某条 CSS 规则(让 ID 为“navigation”的元素 display:none)只在样式表用于打印介质时生效。
每个条件分组规则都有一个条件,该条件在任意时刻都可以计算为 true 或 false。当条件为 true 时,CSS 处理器必须像在分组规则位置直接声明一样应用分组规则内的所有规则;当条件为 false 时,CSS 处理器不得应用分组规则内的任何规则。条件的当前状态不会影响 CSS 对象模型,在对象模型中,分组规则的内容始终保留在分组规则内部。
测试
条件为真时,规则在原地应用。
条件为假时,规则不会被应用。
无论条件如何,CSSOM 始终包含规则。
这意味着当多个条件分组规则嵌套时,只有所有分组规则的条件都为真,内部的规则才会被应用。
测试
嵌套规则仅在所有条件为真时应用。
- at-supports-002.html (在线测试) (源码)
- at-supports-003.html (在线测试) (源码)
- at-supports-004.html (在线测试) (源码)
- at-supports-005.html (在线测试) (源码)
- at-supports-048.html (在线测试) (源码)
- css-supports-025.xht (在线测试) (源码)
- css-supports-026.xht (在线测试) (源码)
- css-supports-046.xht (在线测试) (源码)
@media print{ /* rule (1) */ /* hide navigation controls when printing */ #navigation{ display : none} @media ( max-width:12 cm ) { /* rule (2) */ /* keep notes in flow when printing to narrow pages */ .note{ float : none} } }
标记为(1)的规则的条件在打印媒体下为真,标记为(2)的规则的条件在显示区域(对于打印媒体而言是页面盒)宽度小于等于 12cm 时为真。因此,#navigation { display: none } 这条规则在应用于打印媒体时总是生效,而 .note { float: none } 这条规则只在既为打印媒体且页面盒宽度小于等于 12 厘米时生效。
当条件分组规则的条件发生变化时,CSS 处理器必须反映出规则现在是否适用,除了那些其定义规定计算值效果在该值生命周期之外还会持续生效的属性(如 [CSS3-TRANSITIONS] 和 [CSS3-ANIMATIONS] 中的某些属性)。
3. 条件分组规则的内容
所有条件分组规则都定义为其块内接受一个<rule-list>,允许包含样式表顶层通常允许的任意规则,除非有其他限制。 (例如,@import 规则必须出现在样式表实际开头,因此在其他规则内部无效。)
测试
所有无限制的顶层规则都允许嵌套。
- at-supports-content-002.html (在线测试) (源码)
- at-supports-content-003.html (在线测试) (源码)
- at-supports-content-004.html (在线测试) (源码)
- at-media-content-002.html (在线测试) (源码)
- at-media-content-003.html (在线测试) (源码)
- at-media-content-004.html (在线测试) (源码)
无效或未知规则在<rule-list> 内时应被视为无效并忽略,但不会导致条件分组规则整体无效。
测试
无效规则不会使条件分组规则整体无效。
在条件分组规则中使用的任何命名空间前缀都必须已被声明,否则即为无效。
@namespace xurl ( http://www.w3.org/1999/xlink ); @supports ( content:attr ( x|href)) { // do something}
@supports ( content:attr ( n|tooltip)) { // do something}
用户代理会查找命名空间映射表,确定是否存在与 "n" 前缀对应的命名空间 url。
测试
命名空间前缀的有效性取决于命名空间映射。
4. 条件分组规则的位置
条件分组规则可以出现在允许样式规则出现的任何位置 (既可以在样式表的顶层,也可以嵌套在其他条件分组规则内)。 CSS 处理器必须按照上述描述处理这些规则。
测试
条件分组规则可以出现在允许样式规则出现的任何位置。
- at-media-001.html (在线测试) (源码)
- at-supports-001.html (在线测试) (源码)
- at-supports-002.html (在线测试) (源码)
- at-supports-003.html (在线测试) (源码)
- at-supports-004.html (在线测试) (源码)
- at-supports-005.html (在线测试) (源码)
- css-supports-025.xht (在线测试) (源码)
- css-supports-026.xht (在线测试) (源码)
- css-supports-046.xht (在线测试) (源码)
任何不允许在样式规则后出现的at-规则 (如 @charset、@import 或 @namespace 规则) 也同样不允许出现在条件分组规则之后, 因此如果这样放置则无效。
5. 媒体专用样式表:@media 规则
@media 规则是一种条件分组规则,其条件是媒体查询。 其语法如下:
@media <media-query-list> { <rule-list> }
它由 at-关键字 @media 后跟一个(可能为空的)媒体查询列表 (定义见 [MEDIAQUERIES-4]), 再跟一个包含任意规则的块组成。 该规则的条件即媒体查询的结果。
@media screen and( min-width:35 em ), print and( min-width:40 em ) { #section_navigation{ float : left; width : 10 em ; } }
其条件为 screen and (min-width: 35em), print and (min-width: 40em), 对于视口至少为初始字体大小 35 倍的屏幕显示器和视口至少为初始字体大小 40 倍的打印显示器来说,该条件为真。 当上述条件之一为真时, 规则的条件为真, 并应用 #section_navigation { float: left; width: 10em; } 这条规则。
测试
媒体规则条件可以为空
媒体规则条件为媒体查询
只要不是出于分词需要,空白是可选的。
- at-media-whitespace-optional-001.html (在线测试) (源码)
- at-media-whitespace-optional-002.html (在线测试) (源码)
- at-supports-whitespace.html (在线测试) (源码)
6. 特性查询:@supports 规则
@supports 规则是一种条件分组规则,其条件用于测试用户代理是否支持 CSS property:value 对。作者可以使用它来编写样式表,在新特性可用时使用新特性,在不支持时优雅降级。 这些查询称为 CSS 特性查询,或(口语中)supports 查询。
注意:CSS 已有优雅降级机制,如忽略不支持的属性或值,但当大量样式需与某些特性的支持绑定时(例如使用新布局系统功能),这些机制并不总是足够。
@supports 规则中条件的语法与 <media-condition> 在 [MEDIAQUERIES-4] 中定义的语法类似, 但没有“unknown”值逻辑:
-
需要否定(not),以便新特性样式和回退样式能分开编写(在前向兼容语法规则下),无需互相覆盖。
-
需要合取(and),以便可同时测试多个要求的特性。
-
需要析取(or),当一组样式有多个可选特性时尤为重要,特别是当这些备选项中有供应商前缀属性或值时。
因此,@supports 规则的语法允许对属性:值对进行检测,并对它们进行任意合取(and)、析取(or)和否定(not)组合。
@supports 规则的语法如下:
@supports <supports-condition> { <rule-list> }
<supports-condition> 的定义如下:
<supports-condition> = not <supports-in-parens> | <supports-in-parens> [ and <supports-in-parens> ]* | <supports-in-parens> [ or <supports-in-parens> ]* <supports-in-parens> = ( <supports-condition> ) | <supports-feature> | <general-enclosed> <supports-feature> = <supports-decl> <supports-decl> = ( <declaration> )
上述语法特意宽松,以实现前向兼容, 因为 <general-enclosed> 产生式 允许未来进行大量扩展。 任何不符合上述语法的 @supports 规则 (即,不符合包含 <general-enclosed> 产生式的宽松语法的规则) 都是无效的。 样式表不得使用此类规则,处理器必须忽略此类规则(包括其中全部内容)。
测试
只要不是出于分词需要,空白是可选的。
语法无效的 @supports 规则会被忽略。
- at-supports-019.html (在线测试) (源码)
- at-supports-020.html (在线测试) (源码)
- at-supports-021.html (在线测试) (源码)
- at-supports-022.html (在线测试) (源码)
- at-supports-023.html (在线测试) (源码)
- at-supports-024.html (在线测试) (源码)
- at-supports-025.html (在线测试) (源码)
- at-supports-026.html (在线测试) (源码)
- at-supports-027.html (在线测试) (源码)
- at-supports-028.html (在线测试) (源码)
- at-supports-029.html (在线测试) (源码)
- at-supports-030.html (在线测试) (源码)
- at-supports-031.html (在线测试) (源码)
- at-supports-032.html (在线测试) (源码)
- at-supports-033.html (在线测试) (源码)
- css-supports-034.xht (在线测试) (源码)
- css-supports-037.xht (在线测试) (源码)
每个语法术语都与一个布尔结果相关联,如下所示:
- <supports-condition>
- <supports-in-parens>
-
结果等于子表达式的结果。
- not <supports-in-parens>
-
结果为 <supports-in-parens> 项的取反。
测试
Not 用于取反 supports 条件。
Not 后必须有空格。
Not 必须有括号。
- <supports-in-parens> [ and <supports-in-parens> ]*
-
如果所有 <supports-in-parens> 子项都为 true,则结果为 true,否则为 false。
- <supports-in-parens> [ or <supports-in-parens> ]*
-
如果所有 <supports-in-parens> 子项都为 false,则结果为 false,否则为 true。
测试
Or 条件只要有一个为真就为真。
- at-supports-008.html (在线测试) (源码)
- at-supports-010.html (在线测试) (源码)
- at-supports-013.html (在线测试) (源码)
- css-supports-006.xht (在线测试) (源码)
- css-supports-007.xht (在线测试) (源码)
- css-supports-011.xht (在线测试) (源码)
- css-supports-021.xht (在线测试) (源码)
Or 后必须有空格。
Or 需要括号。
- <supports-decl>
-
如果 UA 支持括号内的声明,则结果为 true。
测试
只有声明被支持时 supports 条件才为真。
- at-supports-001.html (在线测试) (源码)
- at-supports-017.html (在线测试) (源码)
- at-supports-018.html (在线测试) (源码)
- css-supports-001.xht (在线测试) (源码)
声明不能包含分号。
声明值可以为空。
声明不能包含无效的 !token。
括号必须成对出现
- <general-enclosed>
-
结果为 false。
作者不得在样式表中使用 <general-enclosed>。它仅为未来兼容性而存在, 这样新语法的增加不会导致老版用户代理中 <supports-condition> 过多无效。
测试
无法识别但语法上有效的条件为 false,不是无效。
- at-supports-015.html (在线测试) (源码)
- at-supports-046.html (在线测试) (源码)
- css-supports-023.xht (在线测试) (源码)
- css-supports-031.xht (在线测试) (源码)
- css-supports-032.xht (在线测试) (源码)
- css-supports-033.xht (在线测试) (源码)
- css-supports-034.xht (在线测试) (源码)
- css-supports-036.xht (在线测试) (源码)
- css-supports-040.xht (在线测试) (源码)
- css-supports-041.xht (在线测试) (源码)
- css-supports-042.xht (在线测试) (源码)
- css-supports-046.xht (在线测试) (源码)
@supports 规则的条件 是其前导中的 <supports-condition> 的结果。
@supports ( display: flex) { body, #navigation, #content{ display : flex; } #navigation{ background : blue; color : white; } #article{ background : white; color : black; } }
只有在支持 display: flex 时,才会应用 @supports 规则内部的规则。
@supports not( display: flex) { body{ width : 100 % ; height : 100 % ; background : white; color : black; } #navigation{ width : 25 % ; } #article{ width : 75 % ; } }
请注意,width 声明可能会对基于 flex 的布局产生不良影响,因此这些声明应仅在非 flex 样式中出现。
.noticebox{ border : 1 px solid black; padding : 1 px ; } @supports ( box-shadow:0 0 2 px black inset) or( -moz-box-shadow:0 0 2 px black inset) or( -webkit-box-shadow:0 0 2 px black inset) or( -o-box-shadow:0 0 2 px black inset) { .noticebox{ -moz-box-shadow : 0 0 2 px black inset; -webkit-box-shadow : 0 0 2 px black inset; -o-box-shadow : 0 0 2 px black inset; box-shadow : 0 0 2 px black inset; /* 非前缀的放最后 */ /* 用 @supports 覆盖上面规则 */ border: none; padding : 2 px ; } }
为避免 and 和 or 混淆,语法要求 and 和 or 都必须显式指定(例如,不能用逗号或空格)。同样,为避免优先级规则混淆,语法不允许 and、or、not 运算符混用时没有括号层级。
@supports ( transition-property: color) or( animation-name: foo) and( transform:rotate ( 10 deg )) { /* ... */ }
作者应写成如下之一:
@supports (( transition-property: color) or( animation-name: foo)) and( transform:rotate ( 10 deg )) { /* ... */ }
@supports ( transition-property: color) or(( animation-name: foo) and( transform:rotate ( 10 deg ))) { /* ... */ }
测试
混合运算符时必须加括号。
被检测的声明在表达式中单独出现时,必须放在括号内。
测试
声明测试必须加括号。
- at-supports-011.html (在线测试) (源码)
- at-supports-034.html (在线测试) (源码)
- at-supports-035.html (在线测试) (源码)
- at-supports-036.html (在线测试) (源码)
- at-supports-037.html (在线测试) (源码)
- css-supports-002.xht (在线测试) (源码)
语法允许在不需要时添加额外的括号。这种灵活性有时对作者有用(例如注释掉部分表达式时),对编辑工具也有帮助。
被检测声明结尾加 !important 是允许的,尽管这不会影响声明的有效性。
6.1. 支持的定义
为了前向兼容,《CSS21》第4.1.8节(声明和属性)定义了处理无效属性和值的规则。 未实现或部分实现某规范的 CSS 处理器,必须将其未实现或不具备可用支持级别的值部分,按照该无效属性和值处理规则,视为无效,并因此必须将该声明作为解析错误丢弃。
如果 CSS 处理器在样式规则内接受该声明(即不将其作为解析错误丢弃),则认为该处理器支持该声明(包括属性和值)。 如果处理器未以可用支持级别实现所给属性和值,则不得接受该声明或声称支持它。
注意: 由用户偏好实际上禁用支持的属性或值,仍然视为被本定义支持。 例如,如果用户启用了高对比度模式导致颜色被覆盖,CSS 处理器依然视为支持 color 属性,尽管 color 属性的声明可能没有效果。 另一方面,面向开发者的用于启用或禁用实验性 CSS 特性的偏好设置,会影响本定义下的“支持”。
这些规则(以及它们之间的等价性)允许作者使用回退(无论是 [CSS1] 中通过后续声明覆盖的回退,还是本规范中 @supports 规则提供的新能力),从而针对已实现的特性正常工作。对于复合值尤其适用;实现必须实现值的所有部分,才能认为声明被支持,无论是在样式规则内还是 @supports 规则的声明条件中。
测试
仅当属性声明(包括所有值)被解析/支持时 supports 查询为真。
- css-supports-005.xht (在线测试) (源码)
- css-supports-020.xht (在线测试) (源码)
- css-supports-024.xht (在线测试) (源码)
- CSS-supports-CSSStyleDeclaration.html (在线测试) (源码)
- at-supports-044.html (在线测试) (源码)
7. API
7.1.
CSSRule
接口的扩展
CSSRule
接口扩展如下:
partial interface CSSRule {const unsigned short = 12; };
SUPPORTS_RULE
7.2.
CSSConditionRule
接口
CSSConditionRule
接口表示所有“条件” at-规则,由一个条件和一个语句块组成。
[Exposed =Window ]interface :
CSSConditionRule CSSGroupingRule {readonly attribute CSSOMString ; };
conditionText
测试
CSSConditionRule 继承自 CSSGroupingRule。
CSSConditionRule 有 .conditionText 属性。
conditionText
类型为CSSOMString
-
conditionText
属性表示规则的条件。 由于该条件的实际作用因CSSConditionRule
的派生接口而异, 这些派生接口可指定该属性的不同行为(例如见下方CSSMediaRule
)。 若无此类特定规则,按如下规则处理:获取
conditionText
属性时,必须返回关联条件的序列化结果。测试
.conditionText 返回条件的序列化字符串。
7.3.
CSSMediaRule
接口
CSSMediaRule
接口表示一个 @media at-规则:
[Exposed =Window ]interface :
CSSMediaRule CSSConditionRule { [SameObject ,PutForwards =mediaText ]readonly attribute MediaList ;
media readonly attribute boolean ; };
matches
media
类型为MediaList
,只读-
media
属性必须返回 @media at-规则中指定的媒体查询列表的MediaList
对象。测试
.media 返回与 @media 条件匹配的 MediaList。
matches
类型为boolean
,只读-
matches
属性在规则处于附加到文档的样式表中,并且其Window
匹配该规则的media
媒体查询时返回 true,否则返回 false。测试
.matches 匹配媒体查询,返回布尔值。
conditionText
类型为CSSOMString
(CSSMediaRule 对 CSSConditionRule 属性的专有定义)-
conditionText
属性(定义在CSSConditionRule
父规则上),获取时,必须返回规则上media.mediaText
的值。测试
CSSMediaRule.conditionText 的值与 media.mediaText 的值相同。
7.4.
CSSSupportsRule
接口
CSSSupportsRule
接口表示一个 @supports 规则。
[Exposed =Window ]interface :
CSSSupportsRule CSSConditionRule {readonly attribute boolean ; };
matches
matches
类型为boolean
,只读-
matches
属性返回conditionText
中表示的 CSS 特性查询 的求值结果。测试
CSSSupportsRule.matches 若匹配特性查询则返回 true
conditionText
类型为CSSOMString
(CSSSupportsRule 对 CSSConditionRule 属性的专有定义)-
conditionText
属性(定义在CSSConditionRule
父规则上),获取时,必须返回指定的条件,不进行任何逻辑简化,确保返回条件在本规范的任何一致性实现中(包括实现本规范所允许的未来扩展的实现)都能与指定条件得到相同的结果。 换句话说,允许对 token 流进行简化(例如将多个空白合并为一个空格,或在已知可选时省略空白),但不允许逻辑简化(如去除多余括号或基于求值结果的简化)。测试
CSSSupportsRule.conditionText 可进行分词简化。
CSSSupportsRule.conditionText 不得有其他简化。
7.5. CSS
命名空间及 supports ()
函数
CSS
命名空间包含一些实用的 CSS 相关函数,这些函数不属于其他地方。
partial namespace CSS {boolean (
supports CSSOMString ,
property CSSOMString );
value boolean (
supports CSSOMString ); };
conditionText
,返回supports ( CSSOMString property, CSSOMString value) boolean
-
当以两个参数 property 和 value 调用
supports(property, value)
方法时:-
如果 property 是 UA 支持的任何已定义 CSS 属性的ASCII 不区分大小写匹配,或是自定义属性名字符串,并且 value 能根据该属性的语法成功解析,则返回
true
。 -
否则,返回
false
。
注意: 属性名不会进行 CSS 转义或空白处理,例如
CSS.
会返回supports ( " width" , "5px" ) false
,因为 " width"(前导空格)不是任何属性的名称。注意: !important 标志不是属性语法的一部分,会导致 value 解析为无效,这与 element.style.setProperty() 的 value 参数一致。
测试
CSS.supports(arg1, arg2) 检查属性 arg1 配合值 arg2 的支持情况。
-
,返回supports ( CSSOMString conditionText) boolean
-
当以单个 conditionText 参数调用
supports(conditionText)
方法时:-
如果 conditionText 被解析并作为 <supports-condition> 求值结果为 true,则返回
true
。 -
否则,如果 conditionText 外包一层括号后解析并作为 <supports-condition> 求值为 true,则返回
true
。 -
否则,返回
false
。
参数 conditionText 中的所有命名空间都视为无效,与
document.
一致。querySelector ( "a|b" ) 测试
CSS.supports(arg1) 检查 supports 条件 arg1。
CSS.supports(arg1) 隐含括号。
-
安全性注意事项
本规范未引入任何新的安全性注意事项。
隐私性注意事项
本规范中的各种特性,主要与@media规则相关,但在一定程度上也与@supports规则相关,会向 Web 内容提供有关用户硬件、软件及其配置和状态的信息。 大多数信息是通过[MEDIAQUERIES-4]中的特性提供的,而不是通过本规范的特性提供的。 不过,@supports规则可能会提供关于用户软件以及是否启用或禁用某些功能的非默认设置的更多细节。
大多数这些信息也可以通过其他 API 获得。然而,本规范中的特性是这些信息在 Web 上暴露的方式之一。
这些信息还可以被汇总用于提高对用户的指纹识别的准确性。
8. 变更记录
自2022年1月13日候选推荐快照以来,对本规范做出了以下(非编辑性)更改:
- 明确规定 supports() 对于无效自定义属性值必须返回 false
- 修正 Web IDL,“bool”应为“boolean”
- 明确处理器必须同时支持属性和值(Issue 8795)
- 为 @media 和 @supports 添加 .matches(Issue 4240)
- 更新为新的解析算法名称及块产生式名称。
- 移除设置只读 CSSMediaRule.conditionText 的过程(PR 8796)
- 将 conditionText 设为只读属性。
自2020年12月8日候选推荐快照以来,对本规范做出了以下(非编辑性)更改:
- 明确废弃属性声明仅适用于样式规则,不适用于 at-规则
- 明确 !important 不属于属性语法
- 将安全和隐私拆分为独立章节
- 定义了术语 CSS 特性查询 和 supports 查询,用于指代@supports规则的条件语法,便于交叉引用。
- 移除了“unknown”值在CSS 特性查询布尔逻辑中的用法,未识别的语法定义为“false”。(Issue 6175)
-
明确了条件分组规则的放置位置。(Issue 5697)
条件分组规则允许 出现在允许样式规则出现的任何位置( 样式表的顶层,
以及内部以及嵌套在 其他条件分组规则内部 ) 。 CSS 处理器必须如上所述处理这些规则。任何 at- 规则不允许出现在样式规则后 (例如 @charset、@import 或 @namespace 规则) 也同样不允许出现在条件分组规则后
。 因此,样式表不得在条件分组规则后放置这些规则, CSS 处理器须忽略这些规则。,因此这样放置时无效。
自2013年4月4日候选推荐以来,对本规范做出了以下(非编辑性)更改:
- 明确 conditionText 中的命名空间为无效
- 新增编辑者
- 将对parse的显式调用替代“匹配语法”
- 移除重复的 CSSGroupingRule,CSSOM 已有定义
- 将 supports() 文本改写为算法形式,更易表达 supports(prop, val) 需考虑已注册自定义属性语法
- 将 @supports selector 定义移至 css-conditional-4
- @supports 已不再是 at risk 特性
- 改为使用 CSS 语法语法,而非 CSS 2.1 语法
- 从 CSS Interface 改为 WebIDL 兼容的 CSS 命名空间
- 去除了 and、or 及not 关键字周围必须有空格的要求,保持与 媒体查询 一致(后者受部分 CSS 压缩器分词兼容性约束)。 注意这些关键字后仍需有空格或注释,否则会被分词为函数。
- 允许
方法对简单声明隐含括号,与 @import 规则的 supports() 函数保持一致。supports () - 修复 IDL 代码中缺失分号
- 根据其它模块变动,更新链接、术语和示例代码
- 拼写和语法修正
- 新增隐私与安全性注意事项章节
致谢
感谢 Tab Atkins、 Arthur Barstow、 Ben Callahan、Tantek Çelik、 Alex Danilo、 Elika Etemad、 Pascal Germroth、Björn Höhrmann、 Paul Irish、 Brad Kemper、Anne van Kesteren、 Vitor Menezes、 Alex Mogilevsky、 Chris Moschini、 James Nurthen、 Simon Pieters、Florian Rivoal、Simon Sapin、 Nicholas Shanks、 Ben Ward、 Zack Weinberg、 Estelle Weyl、 Boris Zbarsky, 以及所有 www-style 社区成员提出的想法和反馈。