什么是CSS Modules ?咱们为何须要他们

原文地址:https://css-tricks.com/css-mo...
最近我对CSS Modules比较好奇。若是你曾经据说过他们,那么这篇博客正适合你。咱们将去探索它的目的和主旨。若是你一样很好奇,敬请关注,在下一篇博文中咱们将介绍如何使用CSS Modules。若是你想亲自尝试而且掌握如何使用,第三部分将会很适合你,这一部分剖析了如何在React环境中使用。css

什么是CSS Modules?

根据官方的repository介绍,CSS Modules是:webpack

全部的class的名称和动画的名称默认属于本地做用域的CSS文件。
因此CSS Modules不是一个官方的规范,也不是浏览器的一种机制,它是一种构建步骤中的一个进程。(构建一般须要webpack或者browserify的帮助)。经过构建工具的帮助,能够将class的名字或者选择器的名字做用域化。(相似命名空间化。)

这究竟是什么呢?咱们为何要这么作呢?咱们很快就进行介绍。首先,不要忘记HTML和CSS的工做原理。在HTML中一个类添加:web

<h1 class="title">An example heading</h1>

在CSS中这个class的定义以下:浏览器

.title {
    background-color: red;
}

只要CSS被添加到HTML文档上,那个<h1>的背景色就是红色。咱们不须要人为处理CSS和HTML文件。浏览器自己本身就理解这些文件的格式。dom

CSS Modules 和上面的方法不同。咱们不写纯HTML,咱们须要在一个相似index.js这样的Javascript 文件中取写咱们全部的标签。这里有一个例子来讲明这是怎么回事(咱们以后将会去看更多真实的实例):工具

import styles from "./styles.css";

element.innerHTML = 
    `<h1 class="${styles.title}">
        An example heading
      </h1>`;

在咱们构建的步骤中,编译器将会搜索咱们导入的styles.css文件,而后到咱们刚刚写的js文件中,经过styles.title使得.title class可用。咱们的构建步骤将会同时处理这些东西成为新的,分离的HTML和CSS文件,而且用一个新的字符串去替换HTML和CSS选择器的class。学习

经过构建工具生成的HTML也许像下面这样:动画

<h1 class="_styles__title_309571057">
    An example heading
</h1>

经过构建工具生成的CSS也许像下面这样:spa

._styles__title_309571057{
    background-color: red;
}

image
class属性和.title选择器已经彻底不见了,取而代之的是这个全新的字符串;咱们的源CSS文件也没有为浏览器提供服务。
就像Hugo Griaudel在他的这一模块的教程中所说:设计

[the classes]是动态生成的,惟一的,并且和当前的样式有映射关系的。

这就是样式也有做用域的缘由。它们的做用域是特定的模板。若是咱们有一个buttons.css文件咱们将在buttons.js模板中导入它,而且在css文件内的.btn class相对于其余模板(例如forms.js)也是不可用的,除非咱们在这个文件中一样导入了进来。

为何咱们想要把CSS和HTML搞成这样?咱们这样作的真真正正的缘由是什么?

为何咱们要用CSS Modules?

有了CSS Modules,就能够确保全部的样式可以服务于单个组件:

  1. 集中在一个地方
  2. 只应用于那个组件,其余组件不适用

除此以外,任何组件都能拥有真正的依赖,就像下面这样:

import buttons from "./buttons.css";
import padding from "./padding.css";

element.innerHTML = `<div class="${buttons.red}${padding.large}">`;

这样设计的目的在于解决CSS中的全局做用域问题。

你曾有过为了提高效率,节省时间去简略的写css吗?并且是在彻底不考虑你会不会影响其余代码的状况下?

你曾有过在样式表的底部随机打了一些的比特和垃圾,而后尝试回过头来从新去组织可是历来没这么作吗?

你曾有过看到样式却不彻底知道它的意义的时候吗?即便它们被用在了当前的标签上?

你曾有过思考如何去不破坏任何东西的状况下,去弃用一些现有的样式吗?考虑过这些样式是仅仅做用于本身仍是依赖其它样式呢?或者是在哪里从新覆盖了样式了?

这些问题会让人很头痛,项目时间紧张,而你的心思又在窗外的花花世界。

可是当你有了CSS Modules以后,关键是这种默认本地做用域的概念,这个问题将会被避免。你必须去思考写样式的方便性。

例如,若是你在不该用CSS module-style class去作转换的状况下,在HTML中使用random-gross-class,这个样式将不会被应用,由于这个选择器将会被转换为._style_random-gross-class_0038089.

composes 关键词

咱们如今拥有一个叫作type.css的模块去渲染text样式。在那个文件中,咱们也许会有以下代码:

.serif-font {
    font-family: Georgia,serif;
}
.display {
   composes: serif-font;
    font-size: 30px;
    line-height: 35px;
}

咱们将在咱们的模板中声明class:

import type from "./type.css";
element.innerHTML = 
`
    <h1 class="${type.display}">
        This is a heading
    </h1>;
`

编译后的模板上的标签会是下面这样:

<h1 class="_type__display_0980340 _type_serif_404840">
    Heading title
</h1>

使用composes关键词汇将2个class都绑定到元素上,从而避免了相似解决方案的一些问题,相似Sass中的@extend。

咱们甚至能够在一个分离的CSS文件中去compose。

.element{
    compose: dark-red from "./colors.css";
    font-size: 30px;
    line-height: 1.2;
}

不须要BEM

在构建CSS module的过程当中,不须要BEM。有2个缘由:

  1. 易解析- 相似type.display这样的代码,对于开发者来讲就像BEM-y的.font-size__serif--large。当BEM选择器变长时,可能更容易被理解。
  2. 本地做用域- 好比咱们在模块中有一个相似.big去修改font-size属性的class。一样咱们可能还会用.big去同时增大padding和font-size。这不要紧!他们不会冲突,由于做用域中的样式是有各自意义的。甚至一个module引入2个样式表,而后它有一般的名字咱们的构建工具会为那个class加上前缀做区分。换句话说:CSS modules消除了特殊性问题。

很酷,难道不是吗?

这些仅仅是CSS Modules的部分优势。

若是你想学习更多,Glen Madden写了更多的这样作的好处。

这个系列的下一篇文章将会去探索如何在项目中使用Webpack和CSS Modules。咱们将使用最新的ES2015的特性去实现,也会给出一些代码例子去引导你们去理解。

相关文章
相关标签/搜索