原文地址:https://css-tricks.com/css-mo...
最近我對CSS Modules比較好奇。若是你曾經據說過他們,那麼這篇博客正適合你。咱們將去探索它的目的和主旨。若是你一樣很好奇,敬請關注,在下一篇博文中咱們將介紹如何使用CSS Modules。若是你想親自嘗試而且掌握如何使用,第三部分將會很適合你,這一部分剖析瞭如何在React環境中使用。css
根據官方的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; }
class屬性和.title選擇器已經徹底不見了,取而代之的是這個全新的字符串;咱們的源CSS文件也沒有爲瀏覽器提供服務。
就像Hugo Griaudel在他的這一模塊的教程中所說:設計
[the classes]是動態生成的,惟一的,並且和當前的樣式有映射關係的。
這就是樣式也有做用域的緣由。它們的做用域是特定的模板。若是咱們有一個buttons.css文件咱們將在buttons.js模板中導入它,而且在css文件內的.btn class相對於其餘模板(例如forms.js)也是不可用的,除非咱們在這個文件中一樣導入了進來。
爲何咱們想要把CSS和HTML搞成這樣?咱們這樣作的真真正正的緣由是什麼?
有了CSS Modules,就能夠確保全部的樣式可以服務於單個組件:
除此以外,任何組件都能擁有真正的依賴,就像下面這樣:
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.
咱們如今擁有一個叫作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; }
在構建CSS module的過程當中,不須要BEM。有2個緣由:
很酷,難道不是嗎?
這些僅僅是CSS Modules的部分優勢。
若是你想學習更多,Glen Madden寫了更多的這樣作的好處。
這個系列的下一篇文章將會去探索如何在項目中使用Webpack和CSS Modules。咱們將使用最新的ES2015的特性去實現,也會給出一些代碼例子去引導你們去理解。