【CSS in Depth2精译】1.1 层叠

CSS 本质上就是声明规则,并让这些特定的规则在各种情况下生效。一个类添加到某个元素上,则应用这个类包含的这一些样式;元素 X 是元素 Y 的一个子节点,则应用另一些样式。浏览器于是根据这些规则,判定所有样式生效的具体位置,再将它们渲染到页面上。

如果看的都是些简单的示例,这个过程通常都很直观。但随着样式表的不断扩充,或者关联样式的页面一增多,CSS 代码很快就会以惊人的速度变得越来越复杂。在 CSS 里实现一个效果通常有若干种方法。当页面 HTML 结构变更、或者同一份样式被应用到不同的页面时,不同的实现方法会导致截然不同的最终结果。CSS 开发很关键的一点就是确保书写的样式是可预测的。

要做到这一点,首要任务就是理解浏览器究竟是如何解析您书写的样式的。每条规则单拎出来可能简单明了,但要是两条样式有冲突的规则放一起怎么办?某条规则可能因为与另一条规则相冲突而失效。要想预判这些样式规则的最终走向,就必须深入理解 CSS 里的层叠的概念。

为此,您需要构建一个简易的页面标题栏,就像您在某网页顶部看到的那样(如图 1.1 所示)。网站标题位于一组茶色导航链接的上方。最后一个导航链接为橙色,用来代表一个特色链接。

给纸质书读者的提示

本书中的许多图片应该查看彩色版本。我已尽力确保这些图片在黑白印刷时能看明白,但您可能碰巧觉得参考本书电子版里的彩图会很有帮助。获取 PDF、ePub 和 Kindle 格式的免费电子书,请访问 https://www.manning.com/books/css-in-depth 注册纸质书。

在构建这个网页头部时,您可能已经熟悉了大部分涉及的 CSS 样式。这样一来,就可以重点关注那些一知半解的部分了。


图 1.1 本章要实现的页面标题和导航链接效果

首先,创建一个 HTML 文档和一个名为 styles.css 样式表。将代码清单 1.1 中的内容添加到 HTML 里。

注意

本书的所有代码都可以访问代码库 https://github.com/CSSInDepth/css-in-depth-2 进行下载。该代码库已将所有 CSS 示例样式嵌入对应的若干 HTML 文档内(译注:以 style 标签形式给出,与书中代码略有不同)。

代码清单 1.1 网页头部的 HTML 标记

html 复制代码
<!doctype html>
<html lang="en-US">
<head>
  <meta charset="utf-8" />
  <link href="styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
  <header class="page-header">
    <h1 id="page-title" class="title">Wombat Coffee Roasters</h1> <!-- 网页标题 -->
    <nav>
      <ul id="main-nav" class="nav"> <!-- 导航链接列表 -->
        <li><a href="/">Home</a></li>
        <li><a href="/coffees">Coffees</a></li>
        <li><a href="/brewers">Brewers</a></li>
        <li><a href="/specials" class="featured">Specials</a></li> <!-- 特色链接 -->
      </ul>
    </nav>
  </header>
</body>
</html>

当两个或更多规则指向页面上同一元素时,规则间可能包含相互冲突的声明,正如下面的代码所示。三个规则集,每一个都对页面标题指定了不同的字体系列(font family)。该标题不可能同时显示三种字体。哪一个会生效呢?将这些样式代码加到您的 CSS 文件内一探究竟。

代码清单 1.2 相互冲突的样式声明

css 复制代码
h1 { /* 标签(或类型)选择器 */
  font-family: serif;
}
#page-title { /* ID 选择器 */
  font-family: sans-serif;
}
.title { /* 类选择器 */
  font-family: monospace;
}

声明冲突的规则集可能会连续出现,也可能分散在样式表的不同位置。无论哪种情况,这些规则集都指向了 HTML 中的同一个元素。

当三个规则集都去设置标题的字体系列,最终生效的是哪一个呢?要回答这个问题,浏览器就必须遵循一系列规则,来确保最终样式是可预测的。本例中,这些判定规则让第二个声明胜出,理由是其选择器中有 id;因此标题最终采用的是无衬线(sans-serif)字体(如图 1.2 所示)。


图 1.2 ID 选择器胜出,标题最终显示为 sans-serif 无衬线字体

层叠 指的就是这一系列判定规则。它决定了解决冲突的方式,是 CSS 语言的核心基础。尽管大多数有经验的开发者对层叠的概念大致了解,但其中的部分规则有时还是会引发误解。

让我们来深入剖析层叠规则。当声明发生冲突时,层叠将按照以下顺序、先后通过六个判定标准来消除差异。后续将深入探究每一个判定标准,它们分别是:

  1. 样式表来源(Stylesheet origin:样式是从哪里来的,包括您编写的样式和浏览器的默认样式。
  2. 内联样式(Inline styles :无论是通过 HTML 的 style 属性(attribute),还是通过 CSS 选择器应用到某元素的样式,都在此列。
  3. 图层(Layer:样式可以在具有不同优先级的每个图层中定义。
  4. 选择器优先级(Selector specificity:哪些选择器优先于哪些。
  5. 作用域就近原则(Scope proximity:样式是否只作用于 DOM 的某一部分。
  6. 源码顺序(Source order:样式在样式表里的声明顺序。

其中一些判定标准受 !important 标注的影响,后续章节会重点讨论。图 1.3 概括地展示了这些规则的用法。


图 1.3 层叠的高级流程图,展示了冲突声明间的先后顺序

有了这些规则,浏览器才能在解决 CSS 冲突时表现出可预测性。在之前的例子中, #page-title 选择器就是基于这些规则而优于其他选择器并最终生效,尤其是选择器优先级的判定标准,很快我将详细阐释。

图层(Layers作用域(scope 是 CSS 的新增内容,可以更明确地控制层叠。后续第 8 章、第 9 章将深入考察这部分知识。

首先需要强调的是,倘若样式表中没有任何图层,或者任何带作用域的样式,层叠的其余四个判定节点将按此前的惯例继续执行。让我们逐一分析剩下的这些规则:样式表来源、内联样式、选择器优先级和源码顺序。

相关推荐
y先森3 小时前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy3 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189113 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿4 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡5 小时前
commitlint校验git提交信息
前端
虾球xz6 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇6 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒6 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员6 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐6 小时前
前端图像处理(一)
前端