当前内容所在位置(可进入专栏查看其他译好的章节内容)
- 【第三部分 现代 CSS 代码组织】 ✔️
- 【第八章 层叠图层及其嵌套】 ✔️
- 8.1 用 layer 图层来操控层叠规则(上篇)
- 8.1.1 图层的定义(上篇)
- 8.1.2 图层的顺序与优先级(下篇)
- 8.1.3 revert-layer 关键字(下篇)
- 8.2 层叠图层的推荐组织方案 ✔️
- 8.3 伪类 :is() 和 :where() 的用法(精译中 ⏳)
文章目录
- 8.2 层叠图层的推荐组织方案 A recommended organization for cascade layers
- 8.2.1 Reset 重置图层 Reset layer
- 8.2.2 Theme 主题图层 Theme layer
- 8.2.3 Global 全局图层 Global layer
- 8.2.4 Layout 布局图层 Layout layer
- 8.2.5 Modules 模块图层 Modules layer
- 8.2.6 Utilities 工具图层 Utilities layer
- 8.2.7 其余图层 Additional layers
《CSS in Depth》新版封面
译者按
了解了 CSS 层叠图层优先级的判定规则以及revert-layer
关键字的具体用法后,本篇再来看看作者推荐的一个图层组织方案。这些都是新版中才有的新知识,虽然介绍的进度比较慢,但我觉得在巩固基础的这条道路上,现在的慢就是将来的快。与其先囫囵吞枣学个大概后面再来回炉重造,不如一开始就吃透相关的核心知识点,然后再通过后续大量的项目实战来巩固所学。这可能就是李笑来所说的自学路上的“笨拙与耐心”的道理吧。一起学起来吧!
8.2 层叠图层的推荐组织方案 A recommended organization for cascade layers
层叠图层为 CSS 提供了极大的灵活性。所谓成也萧何败也萧何,这样的灵活性也可能让人很难做出抉择:究竟该怎样明确组织代码并分清各部分的先后主次呢?
层叠图层是一项新推出的功能特性,还有很多实验空间可供探索,但业内已经出现了一些通用的主题,比如下面这组图层列表:
@layer reset, theme, global, layout, modules, utilities;
其他开发者也推荐过非常类似的写法,上述代码则是根据前端工程师 Stephanie Eckles 推荐编制而成的。这些图层在页面上的堆叠情况如图 8.5 所示,位置靠后的图层的优先级高于靠前的图层:
【图 8.5 关于合理组织图层的一个实用模板示意图】
接下来将逐一考察各个图层,看看它们是如何帮助您更好地组织样式代码的。我们将从优先级最低的 reset
重置图层开始介绍。注意,并非每个项目都必须包含上述每个图层,可根据实际情况略作删减。
如果想跟着一起练练手,也可以创建一个新的样式表,并跟随本书的讲解同步添加样式。本章不会再手把手带您构建某个具体的页面,而是更注重代码本身的组织方式。建议将所有示例样式放在同一个地方,以便观察它们的组合方式,并在浏览器中验证实验效果。
8.2.1 Reset 重置图层 Reset layer
在 CSS 的早期阶段,不同的浏览器对应的某些用户代理样式差异很大。因此,通过页面样式重置来让链接、列表、标题等元素的行为可控就显得尤为重要了。目前线上可用的重置样式版本有好几个,其中最受欢迎的一个,叫做 normalize.css
。
尽管当前浏览器的趋同性还在进一步增强,不再需要这些重置样式来修复彼此间的不一致问题,但将某些属性重置为更为理想的默认值还是很有必要,包括边框盒模型的设置(详见第 3 章)、调整按钮及 input
文本框的默认字体、以及去掉 <body>
元素上默认的少量外边距等。
将代码清单 8.6 中的样式添加到本地示例样式表,为所有图层确立先后顺序,并设置一些常见的重置样式。
代码清单 8.6 reset 重置图层的样式代码示例
@layer reset, theme, base, layout, modules, utilities; /* 确立所有图层的先后顺序 */
@layer reset {
*,
*::before,
*::after {
box-sizing: border-box; /* 盒模型按边框盒计算尺寸 */
}
body {
margin: unset; /* 移除 body 的外边距 */
}
button,
input,
textarea,
select {
font: inherit; /* 修复表单元素的字体行为 */
}
img,
picture,
svg,
canvas { /* 提升图片及类似元素尺寸的可预见性 */
display: block;
max-inline-size: 100%;
height: auto;
}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
}
以上是我推荐的样式代码,之前的章节已经涵盖了大部分内容。这里只是将我的意见汇集起来,提供一个实用参考。您可以根据需要适当修改。
reset
重置图层通常不需要太多样式,其主要作用是将用户代理样式 “修复(fix)” 成您喜欢的默认样式。所有基于该页面的样式设计都将在后续图层予以体现。使用时可将该层样式完整复制到各个项目中,视具体情况略作调整即可。
8.2.2 Theme 主题图层 Theme layer
接下来需要定义的是自定义属性,尤其是页面将会用到的各种颜色。从概念上讲,提前考虑这些自定义属性是有意义的,以便被后续样式引用;指定较低的优先级也是合理的,这样一来就能在某些位置轻松覆盖掉它们。
除了自定义属性外,还有两个属性也应该在这一层处理。第一个是 accent-color
,它用于自定义某些元素的强调色,例如选中的复选框及单选按钮、范围输入组件(<input type="range">
)和进度条(<progress>
)元素。将其设置为与页面其他颜色相匹配的颜色,能为您的网站增色不少。
第二个属性是 color-scheme
,可指定为 light
或 dark
,让页面在浅色模式与深色模式间切换。浏览器会读取该设置来确定表单输入框和滚动条的合理的默认颜色(具体效果视浏览器的不同而各异)。将代码清单 8.7 中的样式添加到本地样式表,为页面设置主题层样式。
代码清单 8.7 theme 主题图层样式代码示例
@layer theme {
:root {
--brand-color: #0063cc;
--background-color-1: #edf3fa;
--background-color-2: #c6cdd5;
--foreground-color-1: #39434d;
--foreground-color-2: #5a636d;
--font-main: "Helvetica Neue", "Nimbus Sans", Arial, sans-serif;
--font-heading: Georgia, sans-serif;
accent-color: var(--brand-color);
color-scheme: light;
}
}
以上代码只是演示主题图层的用法;若是在大多数现实世界的网站中,则需要设置更多的颜色。比如我的个人博客中的样式表就定义了超过 50 各自定义属性;而我参与开发的应用包含的则多达数百个。我将在后续章节介绍一些命名和颜色管理的实用建议,以便在样式表中进行相关操作。
注意:并非所有自定义属性都要在这一层定义。theme
主题图层可视为自定义属性的大本营,但页面某些地方可能需要一些无需全局生效的自定义属性。这种情况下,将这些自定义属性和用到它们的代码放在一起通常更为合理。例如,如果一个侧边栏会用到一个专属的 --image-radius
属性,那么就可以考虑将其与侧边栏的样式放到一块儿。这些样式可能位于优先级更高的图层,例如 layout
布局图层或者 modules
模块图层。
8.2.3 Global 全局图层 Global layer
层叠图层的第三层为 global
全局图层(也称 base layer,即 基础图层)。该层用于设置对整个网站生效的所有默认样式,包括默认字体样式、背景色与字体颜色、标题与链接样式等。
这一图层的大多数选择器都是标签选择器(tag selectors),因为它们是在各种 HTML 元素上生效的全局默认样式。代码清单 8.8 给出了全局样式的一个示例,将它们添加到本地样式表:
代码清单 8.8 global 全局图层样式代码示例
@layer global {
:root {
font-size: clamp(1rem, 0.4rem + 0.8svw, 1.2rem);
}
body {
font-family: var(--font-main);
background-color: var(--background-color-1);
color: var(--foreground-color-2);
}
a:any-link {
color: var(--brand-color);
}
h1 {
font-family: var(--font-heading);
font-size: 2.2rem;
}
h2 {
font-size: 1.125rem;
}
@media (min-width: 768px) {
h1 {
font-size: 3rem;
}
h2 {
font-size: 2rem;
}
}
}
上述代码使用了定义在 theme
主题图层上的自定义属性,同时还设置了一些字号以及一些响应式行为,以便在更宽的视口上增大字号。其他还可以在 global
全局图层上定义的样式包括:表单 input
文本输入框、label
标签、代码块(code blocks)、大段引用(blockquotes)、以及像 :hover
、:visited
这样的链接状态的进一步处理。
8.2.4 Layout 布局图层 Layout layer
由外向内地设计页面样式往往是最容易实现的。在专注于内部元素的微调之前,先大致确定页面的主要部分——这便是 layout
布局图层的主要目的。
layout
布局图层专注于更高层面的页面布局,包括页眉页脚样式、侧边栏样式布局等等。如果需要在大型网格中放置一系列元素项或者定义列的样式,也可以将它们放在这一层。
很多网站会提供好几种不同的页面布局。例如,主页的布局可能与文章正文布局不同;而文章正文布局又与搜索结果页面布局不同。您可以在 layout
布局图层定义每个页面的总体结构。
代码清单 8.9 给出了部分该图层样式的简要示例。将这些样式添加到您本地的样式表中并查看它们的上下文,即主页布局和文章页布局的一些特定样式。
代码清单 8.9 layout 布局图层的样式代码示例
@layer layout {
#homepage {
display: grid;
grid-template-areas:
"header header"
"main sidebar"
"footer footer";
grid-template-columns: 1fr 300px;
gap: 1rem;
}
#homepage > header,
#homepage > footer {
grid-column: span 2;
}
#article > main {
max-inline-size: 1000px;
margin-inline: auto;
}
}
您可以将 ID 值 homepage
或 article
添加到页面的 <body>
元素或者更上层的 <div>
元素来切换页面生效的布局。这样,同一份样式表就能在多个页面间重用。
过去,人们通常对选用 ID 选择器非常谨慎,因为它的优先级太高;随着层叠图层的出现,这类问题将迎刃而解。如有必要,添加到后续图层中的任意样式都能根据图层的优先级原理轻松覆盖当前图层内的样式规则。如果还是用不惯 ID 而选用样式类,推荐一个常见的样式类写法:使用 l-
前缀(L 即 layout,表示布局的意思)。例如,上述样式代码中的 ID 选择器可以分别替换为 .l-homepage
和 .l-article
。使用 l-
前缀可以迅速区分出普通样式类与层叠图层中的样式类。
还有一点特别重要:根据 HTML 的规则,页面上的 ID 必须是唯一的。因此,如果页面上存在重复使用的布局样式,应该首选样式类来完成相关样式的设置。
8.2.5 Modules 模块图层 Modules layer
接下来的这个层叠图层专注于页面的可重用单元,称为 modules
模块图层。这些模块通常也被称为组件(components)、区块(blocks)或对象(objects)。它们通常包括下拉菜单(dropdown menus)、模态框(modals)、横幅图片(banner images)、导航栏(navigation bars)以及信息卡片(information cards)等。模块图层中的样式主要为页面各部分提供大部分颜色、间距、排版规则等。绝大多数样式都位于这一层。
作为通用规则,各模块应该有一个唯一的名称,并且名称应该相对简短,以便在页面任意位置进行添加。代码清单 8.10 给出了 nav-menu
模块与 card
模块的一组示例样式。将它们添加到您本地的样式表中:
代码清单 8.10 modules 模块图层的示例样式代码
@layer modules {
.nav-menu { /* 导航菜单模块 */
margin-block: unset;
padding-inline: unset;
border: 1px solid #ccc;
list-style: none;
}
.nav-menu > li + li {
border-top: 1px solid #ccc;
}
.nav-menu > li > a {
display: block;
padding: 0.8em 1em;
color: inherit;
font-weight: normal;
}
.nav-menu > li > a:hover {
color: var(--brand-color);
background-color: white;
}
.card { /* 卡片模块 */
padding: 1rem;
border-radius: 0.5rem;
background-color: #fff;
}
.card > h3 {
align-self: end;
margin-block: 0;
padding-block-end: 0.5rem;
border-block-end: 1px solid #eee;
}
}
构建一个由可重用模块组成的网站是一个独立的大主题。我们将在下一章进行更深入的探讨。
鉴于 modules
模块图层是包含样式代码最多的图层,将其进一步细分为各个嵌套图层可能更为实用。但层叠图层目前仍然是一个相对较新的功能,因此暂时还没有任何具体的常用策略。
8.2.6 Utilities 工具图层 Utilities layer
偶尔可能也需要通过一个样式类来实现一个既简单而特别具体的效果,比如设置文本居中或隐藏某个元素等。这些样式类也被称之为 工具类(utilities classes)。
工具类有点类似小型的模块,然而其实现的效果应该非常聚焦。工具类上的样式声明通常不会超过一个。样式清单 8.11 给出了定义在 utilities
工具图层上的部分工具类样式。每个工具类都将执行某个特定的操作:文本居中、元素隐藏、设置圆角半径等等。将这些示例代码添加到您的样式表中:
代码清单 8.11 utilities 工具图层的示例样式代码
@layer utilities {
.text-center {
/* 令文本在容器内居中对齐 */
text-align: center;
}
.hidden {
/* 隐藏页面上的某个元素 */
display: none;
}
.border-radius {
/* 为某元素设置圆角半径 */
border-radius: 1rem;
}
}
过去我通常会在大部分工具类上添加 !important
标记;现在有了层叠图层,只需将它们放到优先级更高的图层上就能达到同样的效果。无论在哪里应用该工具类,它都会生效。当您想在某个元素上设置文本居中效果、却又不希望它被其他样式覆盖时,我向您保证,只要给该元素添加一个 text-center
的样式类就行了。
工具类旨在成为您的得力助手,让您无需引入一个完整的模块就能轻松实现页面上的一个简单效果。工具类虽好,但也不要过于依赖它们。在大多数网站开发中,您可能会要用到的工具类通常也就十来个。
8.2.7 其余图层 Additional layers
一些开发者倾向于再加一个第七层,并称之为 states
状态图层,旨在根据各种模块的状态(state)或扮演的角色(status)动态地添加或删除页面上的某些样式。这些样式可以是页面加载状态、下拉菜单的打开或关闭状态等。
我个人倾向于将它们和 modules
模块图层放到一起,或者和它的嵌入图层放到一起。具体情况将在下一章进行重点考察。
最后再次强调,以上介绍的特定图层组织结构仅仅只是一种推荐方案,并非硬性要求。在开发您自己的图层应用模式时,完全可以根据具体需求随意调整;您也有可能设计出更对您口味的组织方案,或者让某些项目完全受益于另一套方法论。
关于《CSS in Depth》(中译本书名《深入解析 CSS》)
第 1 版 | 第 2 版 | |
---|---|---|
读者评分 | 原版:4.7(亚马逊);中文版:9.3(豆瓣) | 原版:5.0(亚马逊);中文版:暂无,待出版 |
出版时间 | 原版:2018 年 3 月;中文版:2020 年 4 月 | 原版:2024 年 7 月;中文版:暂无,待出版 |
原价 | 原版:$44.99;中文版:¥139.00 | 原版:$59.99;中文版:暂无,待出版 |
现价 | 原版:$36.49;中文版:¥52.54 起步 | 原版:$52.09;中文版:暂无,待出版 |
原版国内预订 | 起步价 ¥461.00 | 起步价 ¥750.00 |
本专栏为该书第 2 版高分译文专栏,全网首发,精译精校,持续更新,计划今年内完成全书翻译,敬请期待!!!
目前已完结的章节(可进入本专栏查看详情,连载期间完全免费):
- 第一章 层叠、优先级与继承(已完结)
- 1.1 层叠
- 1.2 继承
- 1.3 特殊值
- 1.4 简写属性
- 1.5 CSS 渐进式增强技术
- 1.6 本章小结
- 第二章 相对单位(已完结)
- 2.1 相对单位的威力
- 2.2 em 与 rem
- 2.3 告别像素思维
- 2.4 视口的相对单位
- 2.5 无单位的数值与行高
- 2.6 自定义属性
- 2.7 本章小结
- 第三章 文档流与盒模型(已完结)
- 3.1 常规文档流
- 3.2 盒模型
- 3.3 元素的高度
- 3.4 负的外边距
- 3.5 外边距折叠
- 3.6 容器内的元素间距问题
- 3.7 本章小结
- 第四章 Flexbox 布局(已完结)
- 4.1 Flexbox 布局原理
- 4.2 弹性子元素的大小
- 4.3 弹性布局的方向
- 4.4 对齐、间距等细节处
- 4.5 本章小结
- 第五章 网格布局(已完结)
- 5.1 构建基础网格
- 5.2 网格结构剖析 (上)
- 5.2.1 网格线的编号(下)
- 5.2.2 网格与 Flexbox 配合(下)
- 5.3 两种替代语法
- 5.3.1 命名网格线
- 5.3.2 命名网格区域
- 5.4 显式网格与隐式网格(上)
- 5.4.1 添加变化 (中)
- 5.4.2 让网格元素填满网格轨道(下)
- 5.5 子网格(全新增补内容)
- 5.6 对齐相关的属性
- 5.7 本章小结
- 第六章 定位与堆叠上下文(已完结)
- 6.1 固定定位
- 6.1.1 创建一个固定定位的模态对话框
- 6.1.2 在模态对话框打开时防止屏幕滚动
- 6.1.3 控制定位元素的大小
- 6.2 绝对定位
- 6.2.1 关闭按钮的绝对定位
- 6.2.2 伪元素的定位问题
- 6.3 相对定位
- 6.3.1 创建下拉菜单(上)
- 6.3.2 创建 CSS 三角形(下)
- 6.4 堆叠上下文与 z-index
- 6.4.1 理解渲染过程与堆叠顺序(上)
- 6.4.2 用 z-index 控制堆叠顺序(上)
- 6.4.3 深入理解堆叠上下文(下)
- 6.5 粘性定位
- 6.6 本章小结
- 第七章 响应式设计(已完结)
- 7.1 移动端优先设计原则(上篇)
- 7.1.1 创建移动端菜单(下篇)
- 7.1.2 给视口添加 meta 标签(下篇)
- 7.2 媒体查询(上篇)
- 7.2.1 深入理解媒体查询的类型(上篇)
- 7.2.2 页面断点的添加(中篇)
- 7.2.3 响应式列的添加(下篇)
- 7.3 流式布局
- 7.4 响应式图片
- 7.5 本章小结