【CSS in Depth 2 精译_057】第九章 CSS 的模块化与作用域 + 9.1 CSS 模块的定义(上)
当前内容所在位置(可进入专栏查看其他译好的章节内容)
- 【第三部分 现代 CSS 代码组织】 ✔️
- 【第九章 CSS 的模块化与作用域】 ✔️
- 9.1 模块的定义 ✔️
- 9.1.1 模块和全局样式 ✔️
- 9.1.2 一个简单的 CSS 模块 ✔️
- 9.1.3 模块的变体
- 9.1.4 多元素模块
文章目录
《CSS in Depth》新版封面
译者按
因为照顾生病住院的父亲,专栏的更新不得不中断了一周多。好在手术非常成功,术后也恢复得很好,这才重新回归。让大家等了这么多天,先说声抱歉。上一篇我们结束了全新章节层叠图层的学习,这一篇则开始学习模块化 CSS 的相关内容。由于引入了图层的全新概念,本章内容在第一版的基础上也作了相应调整,同时还新增了最新的@scope
语法,非常值得期待!
第九章 模块化 CSS 和范围 Modular CSS and scope
本章概要
- 将 CSS 整理成可复用的模块
- 防止选择器优先级不断攀升
- 组织 CSS 代码的通用命名规则
- 用
@scope
更好地控制层叠规则- 使用模式库编写模块文档
在修改现有样式表时,这些样式变更可能会影响到整个网站中任意多个页面及其页面元素。有个老笑话是这么说的:两个 CSS 属性走进了一间酒吧,结果另一间酒吧的高脚凳却摔倒了(two CSS properties walk into a bar; a barstool in a different bar falls over.)。那么问题来了:怎样确保这些样式修改仅对希望变更的位置生效、而不影响到其他无关的元素样式呢?
上一章介绍的 CSS 层叠图层是控制页面样式优先级的第一步;当时我还给出了页面图层的推荐组织方案。其中最大的图层,即模块图层(modules layer),也是大多数页面样式所在的图层。本章将围绕该层展开讨论,并将其组织为易于管理的模块化代码。
9.1 模块的定义 Defining modules
模块化 CSS(Modular CSS) 是指将页面分割成不同的组成部分,并让它们在多种上下文语境中重复使用,但相互之间并不存在依赖关系。其最终目的是,当我们修改其中一部分 CSS 样式时,不会对其他部分产生意料之外的影响。
这个概念类似于宜家厨房(IKEA kitchen)采用的模块化家具设计:顾客可以随意选择风格一致、组合起来毫无违和感的多个独立小件;而不是购置一个大型的橱柜单元。此外还可以将这些小件随意摆放到自己喜欢的位置,从而形成完整的布局;模块化 CSS 也是如此,不必再构建一个大型网页,而是独立构建页面的各个部分,然后按照既定设计将它们组合到一起。
在计算机科学中,编写模块化代码并不是什么新潮的做法,但许多开发人员并没有意识到可以将其应用于 CSS 领域。随着现代网站和 Web 应用的体量日渐庞大且复杂,人们不得不另寻出路来管理日益庞大且繁杂的样式表。模块化 CSS 便是一种行之有效的解决方案。
之前的样式表可以使用选择器在页面上随意修改样式;而模块化的样式则可以让开发人员添加一些限制条件。我们把样式表的每个组成部分称为 模块(module),每个模块独立负责自己的样式,并且不会影响其他模块内的样式。由此在 CSS 中引入了软件封装的原则。
封装的定义
封装(Encapsulation) 是将相关功能和数据组合在一起,构成一个对象。通常用来隐藏结构化对象内部的状态或值,从而无法从外部操作对象内部。
CSS 没有数据和传统函数的概念,但是有选择器及其选中的页面元素;为了达到封装的目的,它们会成为模块的组成部分,并且每个模块都只负责少量的 DOM 元素样式。此外,CSS 全新推出的 @scope
功能也为样式封装和模块化设计的落地提供了极大的便利。
牢固树立封装的思想后,就可以为页面上相互独立的组件定义模块了,如导航菜单、对话框、进度条、缩略图(thumbnail images)等。每个模块都可以通过作用于 DOM 元素的唯一类名来进行标识。同时,每个模块又包含各自的子元素来构成页面上的组件。模块内部还可以嵌套其他模块,最终构成一个完整的页面。
注意
如果用的是
React
、Vue
或SolidJS
这样的JavaScript
框架,那么您就不会对模块这个概念感到陌生,因为其中的JavaScript
也是以类似的方式组织成组件(component)的。在按模块组织 CSS 时,所构建的 CSS 模块很可能与JavaScript
组件一一对应,只是这样的关联并非强制要求。
9.1.1 模块和全局样式 Modules and global styles
在开始编程模块化样式前,需要提前备好一些基础样式(basic styles),包括常用的重置样式(resets)和全局样式(如字体)。鉴于这些样式会影响到页面上的所有内容,在构建任何特定模块之前,都需要提前设置这些样式。
新建一个页面并关联一个样式表,然后将代码清单 9.1 中的基础样式和全局样式添加到 CSS 中。reset
重置图层的样式取自上一章代码清单 8.5。
代码清单 9.1 添加重置样式与全局样式代码
@layer reset, global, modules;
@layer reset {
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
margin: unset;
}
button,
input,
textarea,
select {
font: inherit;
}
img,
picture,
svg,
canvas {
display: block;
max-width: 100%;
height: auto;
}
}
@layer global {
body {
font-family: Helvetica, Arial, sans-serif;
}
}
根据第 8 章的介绍,我们知道一个完整的网站可能会用到更多的图层;但上述代码已经足以让我们对模块进行更深入的了解。
层叠图层并非编写模块化 CSS 的先决条件(prerequisite)。如果因为浏览器不支持 CSS 图层功能而无法正常使用,您仍然可以遵循这些模块构建原则。
9.1.2 一个简单的模块 A simple module
下面来创建一个用于发送简短通知信息的简单模块。每个模块都需要一个唯一的名称,不妨将该模块命名为 message
(即“消息”模块)。为了吸引用户注意,可以加上一些颜色和边框效果,如图 9.1 所示:
【图 9.1 message 消息模块样式示意图】
该模块的 HTML 标记是一个带 message
样式类的 div
元素。将其添加到您的页面。
代码清单 9.2 message 消息模块的 HTML 标记
<div class="message">
Save successful
</div>
模块的 CSS 是一个规则集,可通过类名选中该模块。CSS 中设置了内边距、边框、圆角半径以及字体颜色等样式。只要将代码清单 9.3 添加到基础样式后,就可以令这些样式应用到消息模块了。
代码清单 9.3 message 消息模块的样式实现
@layer modules {
.message { /* 通过类名选中 message 消息模块 */
padding: 0.8em 1.2em;
border-radius: 0.2em;
border: 1px solid #265559;
color: #265559;
background-color: #e0f0f2;
}
}
这些属性应该非常熟悉了,至少现在看上去跟您在本书见到的其他 CSS 代码类似,并没有什么特别之处。事实上,我们写过的 CSS 代码有很多是符合模块化 CSS 的原则的,只是之前并没有专门提及罢了。下面来重点分析一下这些 CSS 是如何模块化的。
有一点非常重要:该模块的选择器只包含一个类名。该选择器中并没有其他规则来限制这些样式只对页面某个位置生效。例如使用像 #sidebar .message
这样的选择器,则表示该模块只能在 #sidebar
元素内使用;一旦取消这一限制条件,该模块即可在任何上下文中重复使用。
通过给元素添加类名,就可以把这些样式复用到很多场景,比如根据表单输入提供用户反馈信息、提供醒目的帮助文字,抑或是提醒用户注意某个系统通知等等。通过复用同一个模块,就能在任意位置实现一致的用户界面,不必担心某些地方的蓝绿色有色差,或者某些地方的内边距偏大等问题。
我曾经在没有模块化 CSS 的项目里工作过,其中一个项目出现过好几个类似的按钮:.save-form button
、.login-form button
以及 .toolbar .options button
。同样的代码在样式表中重复出现了多次,尽管并不是完全的复制。这么做旨在获得一致的用户体验,本无可厚非;但随着时间的推移,不同的按钮间还是出现了一些不一样的样式调整,导致有的按钮内边距略有不同,而有的按钮又红得更鲜艳。
这个问题的解决办法,就是把按钮样式重构成一个可复用的模块,不受页面位置的限制。创建 CSS 模块不仅可以精简代码(减少冗余),还可以保证视觉上的一致性。这样处理后看上去也更专业,不会给人仓促堆砌的感觉。用户在潜意识里也会更容易信赖我们的应用程序。
篇幅原因,9.1 节的后面两小节内容放到下篇介绍,敬请关注!
关于《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 本章小结
- 第八章 层叠图层及其嵌套
- 8.1 用 layer 图层来操控层叠规则(上篇)
- 8.1.1 图层的定义(上篇)
- 8.1.2 图层的顺序与优先级(下篇)
- 8.1.3 revert-layer 关键字(下篇)
- 8.2 层叠图层的推荐组织方案
- 8.3 伪类 :is() 和 :where() 的用法
- 8.4 CSS 嵌套的使用
- 8.4.1 嵌套选择器的使用
- 8.4.2 深入理解嵌套选择器
- 8.4.3 媒体查询及其他 @规则 的嵌套
- 8.5 本章小结
原文地址:https://blog.csdn.net/frgod/article/details/143824455
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!