1. 介绍
[css-variables-1] 规范定义了“级联变量”的概念, 即由自定义属性的值创建的作者自定义变量, 能够通过 var() 函数被替换到任意其他属性中。
本规范定义了一个相关但更简单的环境变量概念。 与“级联变量”不同, 级联变量会随着其对应自定义属性的不同取值在页面中变化, 而环境变量在特定文档中是“全局”的——其值在任何地方都相同。 env() 函数可以用于将该值替换到任意位置, 类似于 var() 函数。
这些“全局”变量相较于级联变量有优点也有缺点:
-
许多变量并不需要在页面中发生变化; 它们用于设置主题, 或作为特定数值的辅助变量。 使用环境变量而不是自定义属性来定义这些内容, 能更好地传达设计意图, 这不仅有利于文档作者 (尤其当多人协作同一文档时), 也有利于用户代理, 因为它可以用更优化的方式存储这些变量。
-
由于环境变量不依赖于任何特定元素的值, 它们可以用于没有明确元素来源的场景, 比如 @media 规则中, 而 var() 函数在此处无效。
-
来自用户代理本身的信息, 例如视口的边距(比如为避免内容覆盖屏幕“刘海”或缺口), 可以通过 env() 获取, 而 var() 的元素特性使其不适合传递此类信息。
大多数环境变量在同一时间只会有一个值。
但也有一些是“索引型”的,即同时表示多个值,
例如 viewport-segment-* 变量中表示多个独立内容面板的尺寸和位置。
要引用这些索引型变量,需在变量名后提供一个或多个整数,
如 viewport-segment-width 1 0,
用于从可能的值列表或网格中选取单个值,
类似于传统编程语言中用 values[0]
语法从列表中选取元素。
2. 环境变量
一个 CSS 环境变量 是与 <declaration-value>(一段零个或多个 CSS 记号的序列,对包含的记号几乎无限制)关联的名字, 类似于自定义属性。环境变量可以由用户代理定义, 也可以由用户定义。 (后者情况下,名字为<custom-property-name>, 并按自定义标识符规则以 `--` 开头。)
用户代理定义的
环境变量
是否对脚本可见?
如果是,需在 Document
上定义一个 API 以暴露它们。
定义作者如何添加 环境变量, 尽量同时支持 JS 和 CSS。 注意,混用 CSS 规则和 JS 定义的内容容易导致混乱, 类似 CSSFontFaceRule 与 FontFace 的情况……
以下用户代理定义的环境变量为官方定义,必须支持。 其他用户代理定义的 环境变量不得被支持, 除非/直到它们被加入此列表。
2.1. 安全区域内边距变量
名称 | 值 | 维度数 |
---|---|---|
safe-area-inset-top | <length> | 0(标量) |
safe-area-inset-right | <length> | 0(标量) |
safe-area-inset-bottom | <length> | 0(标量) |
safe-area-inset-left | <length> | 0(标量) |
安全区域内边距是四个环境变量,用于通过其距视口边缘的上、右、下、左内边距描述一个矩形。对于矩形显示,这些值都必须为零;但对于非矩形显示,它们必须组成一个由用户代理选择的矩形,保证该矩形内所有内容可见,并且减少任一内边距都会导致矩形内部分内容因显示器形状而不可见。这样作者可以将重要内容的布局限定在安全区域矩形内。
2.2. 安全区域最大内边距变量
名称 | 值 | 维度数 |
---|---|---|
safe-area-max-inset-top | <length> | 0(标量) |
safe-area-max-inset-right | <length> | 0(标量) |
safe-area-max-inset-bottom | <length> | 0(标量) |
safe-area-max-inset-left | <length> | 0(标量) |
安全区域最大内边距是四个环境变量,与安全区域内边距变量相关联。 不同于动态变化的安全区域内边距变量, 安全区域最大内边距是静态值, 表示当动态用户代理界面收起时,其动态对应用的最大值, 使布局视口尺寸达到最大视口尺寸。
2.3. 视口分段变量
名称 | 值 | 维度数 |
---|---|---|
viewport-segment-width | <length> | 2 |
viewport-segment-height | <length> | 2 |
viewport-segment-top | <length> | 2 |
viewport-segment-left | <length> | 2 |
viewport-segment-bottom | <length> | 2 |
viewport-segment-right | <length> | 2 |
视口分段是环境变量,用于定义视口逻辑上独立区域的位置和尺寸。当视口被一个或多个硬件特性(如折叠或多屏之间的铰链)分割时,会创建视口分段;这些分段是作者可视为逻辑独立区域的视口部分。
视口分段环境变量有两个维度,分别代表被硬件特性分割后二维网格中的 x 和 y 位置。 位于左侧边缘的分段 x 位置为 0,右侧下一个分段 x 位置为 1,以此类推。 同样,顶部边缘的分段 y 位置为 0,依次递增。
注意: 在某些硬件配置中,分隔物本身可能会占据视口的逻辑空间。可以通过计算视口分段的位置之间的区域来得到分隔物的尺寸。
这些变量仅在存在至少两个此类分段时才定义。 如果没有硬件特性分割视口,则应使用视口单位,否则在多分段设备上内容可能无法按预期显示。
2.4. 首选文本缩放
名称 | 值 | 维度数 |
---|---|---|
preferred-text-scale | <number> | 0(标量) |
preferred-text-scale 环境变量 表示用户的首选文本缩放因子, 即他们对操作系统和/或用户代理“默认”字体大小的调整。 (在 text-size-adjust 有效的设备上, 这是 text-size-adjust: auto 应用的缩放因子。)
例如,如果 text-size-adjust:auto 会使文本尺寸变为原来的两倍, 那么 env(preferred-text-scale) 的值就是 2。
注意: pem 单位代表了相同的信息;1em 完全等价于 calc(1em * env(preferred-text-scale))。 直接定义尺寸时,bsem 只是一个更方便的长度单位。
通常,作者应:
-
设置 text-size-adjust: calc(100% * env(preferred-text-scale));, 以确保页面所有文本自动适应用户偏好, 并在需要时按缩放因子缩放非文本尺寸。
-
或者设置 text-size-adjust:none, 然后始终使用此环境变量和/或pem单位来缩放相关文本和界面元素。
3. 使用环境变量:env() 语法
要在 CSS 环境中替换环境变量的值, 使用 env() 函数:
env() = env( <custom-ident> <integer [0,∞]>*, <declaration-value>? )
env() 函数可以用在任何元素的任何属性值的任意部分, 或用在任何 at-rule 的描述符值的任意部分, 以及其它允许 CSS 值出现的地方。
env() 的第一个参数用于提供要替换的环境变量名称。 后续的整数参数(如果有)表示该变量的维度索引,如果提供的名称对应一个类似数组的环境变量。 逗号后的参数(如果有)为回退值, 当引用的 环境变量 不存在时,回退值将被用于替换。
注意: 回退值的语法(与自定义属性类似)允许包含逗号。 例如,env(foo, red, blue) 的回退值为 red, blue; 也就是说,第一个逗号之后到函数结尾的内容都视为回退值。
如果一个属性包含一个或多个 env() 函数,并且这些函数语法有效, 那么整个属性的语法必须在解析时假定为有效。 只有在计算值阶段 env() 被替换后,才进行语法检查。
如果一个描述符包含一个或多个 env() 函数,并且这些函数语法有效, 那么整个声明在解析时也必须假定为有效。 只有在 env() 被替换后才进行语法检查。
需要定义替换发生的时机。 它必须发生在 var() 替换之前。 或者,是否应让 env() 在解析时替换, 这样未知变量名会导致语法检查失败? 并没有充分理由让它像 var() 那样在计算值时替换——那样做主要是为了让自定义属性可以先继承值, 然后再被 var() 取用。
等确定 env() 还能用于哪些地方,再定义其替换时机和方式。
3.1. 环境变量在简写属性中的用法
如果 env() 替换发生在解析阶段, 那么这一节就不需要了。
env() 函数与 简写属性配合时会遇到与 var() 函数相同的问题。 当在 env() 用于 简写属性时, 其行为与 CSS Variables 1 § 3.2 简写属性中的变量一致。
4. 隐私注意事项
本规范定义的 环境变量 可能涉及隐私, 因为它们可能代表页面本无法获得的额外信息。 特别是,暴露这些变量可能成为指纹识别途径, 因为它们泄露了用户使用的设备的更多信息。
目前为止,本规范定义的 环境变量 已经过 CSSWG 审查,认为可公开暴露。
5. 安全注意事项
本规范为设备的一些新类型信息提供只读访问。
本规范定义的 环境变量 不会暴露任何安全敏感信息。