CSS Modules使用詳解

gzsinx 7年前發布 | 9K 次閱讀 CSS 前端技術

CSS Modules

CSS 模塊化

不管是用jquery還是react開發,都會遇到的一系列 CSS 的問題:

  1. 全局污染
  2. 命名混亂
  3. 依賴引入復雜
  4. 無法共享變量
  5. 代碼冗余

通過 JS 來管理 CSS 就很好解決上述列舉的問題。CSS 模塊化的解決方案有很多,但主要有兩類。

一類是徹底拋棄 CSS,使用 JS 或 JSON 來寫樣式。Radium, jsxstyle ,react-style 屬于這一類。優點是能給 CSS 提供 JS 同樣強大的模塊化能力;缺點是不能利用成熟的 CSS 預處理器(或后處理器) Sass/Less/PostCSS, :hover 和 :active 偽類處理起來復雜。

另一類是依舊使用 CSS,但使用 JS 來管理樣式依賴,代表是CSS Modules。CSS Modules 能最大化地結合現有 CSS 生態和 JS 模塊化能力。發布時依舊編譯出單獨的 JS 和 CSS。它并不依賴于 React,只要你使用 Webpack,可以在 Vue/Angular/jQuery 中使用。

啟用 CSS Modules

// webpack.config.js
css?modules&localIdentName=[name]__[local]-[hash:base64:5]

加上 modules 即為啟用, localIdentName 是設置生成樣式的命名規則,[name]表示標簽名,[local]表示類名,[hash:base64:5]是按照給定算法生成的序列碼。

/ components/test.css /
.active { 
    color: red;
}
.disabled {
    color: gray;
}

/ components/test.js / import styles from './test.css';

console.log(styles);

elem.outerHTML = &lt;h1 class=${styles.active}&gt;CSS Modules&lt;/h1&gt;</code></pre>

生成的 HTML 是

<h1 class="h1--active-abc53"> Processing... </h1>

它將根據 styleName 的值在關聯的 style 對象中查找對應的 CSS Modules,并為 ReactElement className 屬性值添加相匹配的獨一無二的 CSS 類名。

上例中 styles的consolelog 打印的結果是:

Object {
  active: 'h1--active-abc53',
  disabled: 'h1--disabled-def84',
}

CSS Modules 對 CSS 中的 class 名都做了處理,使用對象來保存原 class 和定制處理后的 class 的對應關系。經過這樣類名定制處理后,class 名基本就是唯一的,大大降低了項目中樣式覆蓋的幾率。同時可以生成更短的 class 名,減少代碼量。

CSS Modules 使用

局部變量和全局變量

  • :local : 做 localIdentName 規則處理
  • :global : 樣式編譯后不變

如果書寫時不加,默認處理為 :local 。

.normal {
  color: green;
}

:local(.normal) { color: green; }

/ 上面兩個等價,默認給每個 class 名外加加了一個 :local /

/ 全局樣式 / :global { .link { color: green; } .box { color: yellow; } }</code></pre>

唯一哈希類名

開啟CSS Modules時定義的規則 localIdentName=[name]__[local]-[hash:base64:5] 會控制對class名的處理, [hash:base64:5]定義的hash計算能保證類名的唯一性。

Compose 組合Class

很多時候我們都需要樣式復用,在 CSS Modules 中,一個選擇器可以繼承另一個選擇器的規則,這稱為 composes 組合。

/ components/test.css /
.bg {
  background-color: blue;
}

.title { composes: bg; color: white; }

/ components/test.js / import styles from './test.css';

elem.outerHTML = &lt;h1 class=${styles.title}&gt;CSS Modules&lt;/h1&gt;</code></pre>

生成的 HTML 為

<h1 class="h1--bg-fec53 h1--title-Ijf8"> Processing... </h1>

CSS和JS變量共享

:export 關鍵字可以把 CSS 中的 變量輸出到 JS 中:

/ index.scss /
$primary-color: #f40;

:export { primaryColor: $primary-color; }

/ app.js / import style from 'index.scss';

// 會輸出 #F40 console.log(style.primaryColor);</code></pre>

CSS Modules使用特點

  1. 不使用選擇器,只使用 class 名來定義樣式
  2. 不層疊多個 class,只使用一個 class 把所有樣式定義好
  3. 不嵌套class
  4. 所有樣式通過 composes 組合來實現復用

舊項目的兼容

  1. 如果對一個元素使用多個 class,樣式照樣生效。
  2. 如何在一個 style 文件中使用同名 class ,編譯后仍是同名的。
  3. 如果在 style 文件中使用了 id 選擇器,偽類,標簽選擇器,所有這些選擇器將不被轉換,原封不動的出現在編譯后的 css 中。即 CSS Modules 只會轉換 class 名相關樣式。
  4. 當類名經過編譯生成新的隨機類名后,可以解決命名沖突,但因為無法預知最終 class 名,不能通過一般選擇器覆蓋。現在一般給出的項目中的實踐是可以給組件關鍵節點加上 data-role 屬性,然后通過屬性選擇器來覆蓋樣式。
  5. 前端項目不可避免會引入 normalize.css 或其它一類全局 css 文件。使用 Webpack 可以讓全局樣式和 CSS Modules 的局部樣式和諧共存。
module: {
  loaders: [{
    test: /\.jsx?$/,
    loader: 'babel'
  }, {
    test: /\.scss$/,
    exclude: path.resolve(__dirname, 'src/styles'),
    loader: 'style!css?modules&localIdentName=[name]__[local]!sass?sourceMap=true'
  }, {
    test: /\.scss$/,
    include: path.resolve(__dirname, 'src/styles'),
    loader: 'style!css!sass?sourceMap=true'
  }]
}

 

來自:http://imweb.io/topic/586519b1b3ce6d8e3f9f99aa

 

 本文由用戶 gzsinx 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!