什麼是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的特性去實現,也會給出一些代碼例子去引導你們去理解。

相關文章
相關標籤/搜索