自学内容网 自学内容网

【CSS in Depth 2 精译】2.6 CSS 自定义属性(即 CSS 变量)+ 2.7 本章小结

当前内容所在位置

  • 第一章 层叠、优先级与继承
  • 第二章 相对单位
    • 2.1 相对单位的威力
    • 2.2 em 与 rem
    • 2.3 告别像素思维
    • 2.4 视口的相对单位
    • 2.5 无单位的数值与行高
    • 2.6 自定义属性 ✔️
    • 2.7 本章小结 ✔️
  • 第三章 文档流与盒模型

2.6 自定义属性(即 CSS 变量)

自定义属性(Custom properties 可以实现更高水准的基于上下文的动态样式设计。自定义属性的功能在很多方面都与变量(variables)相似;CSS 可以声明一个变量并赋值,然后在整个样式表中引用该值。这样不仅能减少样式表中的重复,而且还有其他好处,稍后会举例说明。

注意

如果用了 CSS 预处理器(如 Sass 或 Less)自带的变量,那么您可能会忽略 CSS 变量。千万别这么干。由于 CSS 变量有着本质上的区别,它比任何一款预处理器具备的变量功能都要强大得多。因此我更倾向于称其为“自定义属性”,而不是变量,以强调它们和预处理器变量的不同。

定义一个自定义属性,需要像其它 CSS 属性一样进行声明,如下方代码所示。新建一个示例页和样式表,并添加如下 CSS:

:root {
  --main-font: Helvetica, Arial, sans-serif;
}

该代码定义了一个名为 --main-font 的变量,并将变量的值设为一组常见的无衬线字体(sans-serif)。变量名须以两个连字符(--)开头,以便与其他 CSS 属性作区分;然后再加上要声明的任何合法名称。

CSS 变量必须在声明块中声明。这里用到了 :root 选择器,表示为整个页面设置了该变量,原因稍后解释。

该变量声明只有在被调用时才会在页面看到效果。将它应用到某个段落,则效果如图 2.14 所示:

图 2.14 使用变量设置无衬线字体的普通段落图 2.14 使用变量设置无衬线字体的普通段落

调用函数 var() 就能使用该变量。使用该函数引用刚才定义的 --main-font 变量。按如下代码更新样式,将变量用起来:

代码清单 2.18 使用自定义属性

:root {
  --main-font: Helvetica, Arial, sans-serif;
}
p { /* 将段落字体设置为 Helvetica, Arial, sans-serif */
  font-family: var(--main-font); 
}

自定义属性可以将值定义到某处作为“单一数据源”,然后在整个样式表中复用该值。这种方式特别适合反复出现在页面上的值,比如颜色值。代码清单 2.19 添加了一个名为 brand-color 的自定义属性,之后整个样式表都能多次调用该变量;后续即便要改,也只需改动这一个地方即可。

代码清单 2.19 使用自定义颜色属性

:root {
  --main-font: Helvetica, Arial, sans-serif;
  --brand-color: #369; /* 定义一个蓝色的 brand-color 变量 */
}
p {
  font-family: var(--main-font);
  color: var(--brand-color);
}

var() 函数还能接受一个非必填的第二参数作备用值。如果第一参数设置的变量未定义,则启用第二个备用值。

代码清单 2.20 提供备用值

:root {
  --main-font: Helvetica, Arial, sans-serif;
  --brand-color: #369;
}
p {
  /* 指定备用值为 sans-serif */
  font-family: var(--main-font, sans-serif);
  /* 变量 secondary-color 未定义,因此启用备用值 blue */
  color: var(--secondary-color, blue);    
}

上述样式代码在两个不同的声明中指定了备用值。在第一个声明中,--main-font 被定义为 Helvetica, Arial, sans-serif,因此使用该值;而第二个声明中,变量 --secondary-color 未定义,因此启用备用值 blue

注意

如果 var() 函数算出的结果为无效值(invalid value),该属性将被设置为初始值(initial value)。例如,如果 padding: var(--brand-color) 中的变量值为一个颜色值,对于内边距 padding 而言就是一个无效值。此时 padding 的值将被设置为 0

2.6.1 动态变更自定义属性

在前面的示例中,自定义属性仅仅是为减少大量冗余代码提供了一种便捷方式;而它真正的意义在于,自定义属性的声明也适用 CSS 层叠与继承规则:只要在多个选择器中定义相同的变量,就能让该变量在页面不同位置拥有不同的取值。

例如,将一个变量定义为黑色,然后在特定容器内将其重新定义为白色。这样依赖,任何基于该变量的样式在容器外都将被动态解析为黑色,而容器内则为白色,如图 2.15 所示。

图 2.15 自定义属性会根据本地变量值生成不同颜色的面板图 2.15 自定义属性会根据本地变量值生成不同颜色的面板

该示例与之前创建的面板效果类似,只是多了一个深色版本。其 HTML 结构如代码清单 2.21 所示。它有两个面板实例:一个在 body 元素内,另一个在深色的 section 元素内。按如下代码更新示例页。

代码清单 2.21 同一页面不同环境下的两个面板

<body>
  <div class="panel"> <!-- 网页中的一个普通面板 -->
    <h2>Single-origin</h2>
    <div class="body">
      We have built partnerships with small farms
      around the world to hand-select beans at the
      peak of season. We then careful roast in
      small batches to maximize their potential.
    </div>
  </div>
 
  <aside class="dark">
    <div class="panel"> <!-- 深色容器内的另一个面板 -->
      <h2>Single-origin</h2>
      <div class="body">
        We have built partnerships with small farms
        around the world to hand-select beans at the
        peak of season. We then careful roast in
        small batches to maximize their potential.
      </div>
    </div>
  </aside>
</body>

接下来,通过变量来设置文字颜色与背景色,从而重新定义面板样式。在样式表中添加如下代码,将背景色设置为白色,文字设置为黑色。具体工作原理待面板变为深色版本后再作解释。

代码清单 2.22 使用变量定义面板颜色

:root { /* 分别将背景色和文字颜色变量定义为白色和黑色 */
  --main-bg: #fff;
  --main-color: #000;
}
.panel {
  font-size: 1rem;
  padding: 1em;
  border: 1px solid #999;
  border-radius: 0.5em;
  /* 在面板样式中使用变量 */
  background-color: var(--main-bg);
  color: var(--main-color);
}
.panel > h2 {
  margin-top: 0;
  font-size: 0.8em;
  font-weight: bold;
  text-transform: uppercase;
}

这一次同样使用 :root 选择器定义变量——这一点很重要——它意味着这些变量值是为根元素(即整个页面)中的所有内容设置的。当根元素的后代元素调用它们时,浏览器也会解析到这些值。

两个面板准备就绪,尽管看上去效果是一样的。接下来再次定义变量,但选择器和刚才不一样了。以下代码为深色容器设置了深灰色背景,以及少量的内外边距(paddingmargin)。此外还重新定义了两个变量。将这些代码更新到样式表中:

代码清单 2.23 深色容器的样式

.dark {
  margin-top: 2em; /* 给深色容器与前面的面板之间加上外边距 */
  padding: 1em;
  background-color: #999; /* 给深色容器加上深灰色背景 */
  /* 在容器内重新定义变量的取值: */
  --main-bg: #333;
  --main-color: #fff;
}

重新加载页面后,第二个面板变为深色背景、白色文字。这是因为当面板使用这些自定义属性时,浏览器会解析在深色容器上定义的变量值,而非根元素上的值。注意,这里无需重新设计面板样式,也不用借助任何其他的样式类。

本例定义了两次自定义属性:先是根元素(此时 --main-color 为黑色),然后是深色容器(此时 --main-color 为白色)。自定义属性是一种带作用域的变量,其值会被后代元素继承。在深色容器中,--main-color 解析为白色;而在页面其他位置,则解析为黑色。

自定义属性是一种用途极为广泛的工具,其用途不胜枚举。本书后续章节还将继续介绍自定义属性的各种应用。

(第一版中曾介绍的第二小节内容:使用 JavaScript 改变自定义属性,在新版中被舍弃了)

2.7 本章小结

  • 相对单位可用于指定与字号或视口大小相适应的尺寸。
  • em 单位制基于该元素字号来定义长度;若用于指定字号本身,则基于该元素继承的字号来定义长度。
  • rem 单位制基于 <html> 根元素上设置的字号来定义长度。
  • 在响应式设计中缩放根元素字号,则页面上用 emrem 定义的元素也会同步缩放。
  • 视口相对单位基于视口的宽度或高度来定义长度。
  • 用无单位数值定义的行高,在继承到子元素时其可预测性更强。
  • 自定义属性的工作原理虽然与变量类似,但可以通过层叠和继承规则实现动态调整。

(本章完)


原文地址:https://blog.csdn.net/frgod/article/details/140291725

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!