我最近对 CSS Modules 感兴趣。 如果你还没有听说过它们,这篇文章就是为你准备的。 我们将研究这个项目及其目标和目的。 如果你感兴趣,请继续关注,因为下一篇文章将介绍如何开始使用这个理念。 如果你想实现或提升你的使用水平,第 3 部分将介绍如何在 React 环境中使用它们。
文章系列
什么是 CSS Modules 以及我们为什么需要它们? (您当前所在位置!)
CSS Modules 入门
React + CSS Modules = 😍
什么是 CSS Modules?
根据 仓库,CSS Modules 是
默认情况下所有类名和动画名称都在本地限定范围的 CSS 文件。
因此,CSS Modules 不是一个官方规范或浏览器中的实现,而是在构建步骤中(借助 Webpack 或 Browserify)更改类名和选择器以限定范围(即有点像命名空间)的过程。
这看起来像什么,为什么要这样做? 我们稍后会详细介绍。 首先,请记住 HTML 和 CSS 通常是如何工作的。 类在 HTML 中应用
An example heading
并在 CSS 中设置该类的样式
.title {
background-color: red;
}
只要该 CSS 应用于 HTML 文档,则该
的背景将为红色。 我们不需要处理 CSS 或 HTML。 浏览器理解这两种文件格式。
CSS Modules 采用了不同的方法。 我们需要在 JavaScript 文件(如index.js)中编写所有标记,而不是编写纯 HTML。 以下是如何工作的示例(我们稍后将查看更真实的示例)
import styles from "./styles.css";
element.innerHTML =
`
An example heading
`;
在我们的构建步骤中,编译器将搜索我们导入的styles.css文件,然后查看我们编写的 JavaScript 并通过styles.title使.title类可访问。 然后,我们的构建步骤将这两者处理成新的、单独的 HTML 和 CSS 文件,并使用新的字符字符串替换 HTML 类和 CSS 选择器类。
我们生成的 HTML 可能如下所示
An example heading
我们生成的 CSS 可能如下所示
._styles__title_309571057 {
background-color: red;
}
类属性和选择器.title完全消失了,被这个全新的字符串替换了;我们的原始 CSS 根本没有提供给浏览器。
正如 Kitty Giraudel 在他的教程中所说
【类】是动态生成的、唯一的,并映射到正确的样式。
这就是样式限定范围的含义。 它们限定在特定的模板中。 如果我们有一个buttons.css文件,我们只会将其导入到buttons.js模板中,并且其中的.btn类将无法访问其他模板(例如forms.js),除非我们也在那里专门导入它。
为什么我们要修改 CSS 和 HTML 来做到这一点? 我们为什么要以这种方式工作?
我们为什么要使用 CSS Modules?
使用 CSS Modules,可以保证单个组件的所有样式
位于一个地方仅应用于该组件,而不是其他任何组件
此外,任何组件都可以拥有真正的依赖项,例如
import buttons from "./buttons.css";
import padding from "./padding.css";
element.innerHTML = `
`;
这种方法旨在解决 CSS 中的全局作用域问题。
您是否曾因为时间或资源不足而只想尽快编写 CSS,而不考虑可能影响的其他内容?
您是否曾经在样式表的底部粘贴一些随机的片段和垃圾,打算以后整理,但从未整理?
您是否曾经遇到过不确定其作用或是否正在使用的样式?
您是否曾经想过是否可以在不破坏任何内容的情况下删除某些样式?想知道样式是否独立存在或依赖于其他内容?或者覆盖了其他地方的样式?
这些问题会导致严重的麻烦、项目截止日期延长以及悲伤、渴望地望着窗外。
使用 CSS Modules 和默认本地作用域的概念,可以避免此问题。 您在编写样式时始终被迫考虑后果。
例如,如果您在 HTML 中使用random-gross-class而不将其应用为 CSS modules 样式类,则样式将不会应用,因为 CSS 选择器将转换为._style_random-gross-class_0038089。
composes 关键字
假设我们有一个名为type.css的模块用于我们的文本样式。 在该文件中,我们可能拥有以下内容
.serif-font {
font-family: Georgia, serif;
}
.display {
composes: serif-font;
font-size: 30px;
line-height: 35px;
}
我们将如下所示在我们的模板中声明其中一个类
import type from "./type.css";
element.innerHTML =
`
This is a heading
`;
这将生成如下标记
Heading title
通过使用composes关键字,这两个类都已绑定到元素,从而避免了类似解决方案(如 Sass 的@extend)的一些问题。
我们甚至可以从单独的 CSS 文件中的特定类进行组合
.element {
composes: dark-red from "./colors.css";
font-size: 30px;
line-height: 1.2;
}
无需 BEM
在创建 CSS 模块时,我们不需要使用 BEM。 这是因为两个原因
易于解析 – 像type.display这样的代码对于开发人员来说与 BEM 风格的.font-size__serif--large一样易读。 当 BEM 选择器变长时,可能更容易在心理上进行解析。本地作用域 – 假设我们在一个模块中有一个像.big这样的类,它更改了font-size。 在另一个模块中,我们使用完全相同的类.big,它以不同的数量增加padding和font-size。 这根本没关系! 它们不会发生冲突,因为样式非常谨慎地限定了范围。 即使一个模块导入两个样式表,它也有一个自定义名称,我们的构建过程专门为此类创建该名称。 换句话说,CSS Modules 消除了特异性问题。
很酷,对吧?
这些只是编写 CSS Modules 的一些好处。
如果您有兴趣了解更多信息,Glen Madden 已经广泛地撰写了关于这种方法的其他一些好处。
本系列的下一篇文章将介绍如何使用 Webpack 和 CSS Modules 启动项目。 我们将使用最新的 ES2015 功能来执行此操作,并查看一些示例代码以指导我们完成整个过程。
进一步阅读
CSS Modules:欢迎来到未来Kitty Giraudel 的 Sitepoint 上的 CSS Modules 教程理解 ES6 模块学习 ES2015ES6 模块语法概述
文章系列
什么是 CSS Modules 以及我们为什么需要它们? (您当前所在位置!)
CSS Modules 入门
React + CSS Modules = 😍