CSS Modules使用详解

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 = `<h1 class=${styles.active}>CSS Modules</h1>`

生成的 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;
  }
}

唯一哈希类名

开启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 = `<h1 class=${styles.title}>CSS Modules</h1>`

生成的 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);

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'
  }]
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏.Net移动开发

.Net语言 APP开发平台——Smobiler学习日志:Poplist控件的正确打开方式以及如何快速实现

PopList控件显示包括两种模式:展开模式和筛选分类模式;两种模式只能选其中一种

862
来自专栏mukekeheart的iOS之旅

Mac和Xcode常用的快捷键

Mac电脑一般都不怎么用鼠标,因此除了触摸屏的各种双指、三指甚至四指的操作之外,快捷键的使用可以带来非常大的便利,本文则主要收集整理了自己在Mac常规和Xcod...

42113
来自专栏前端新视界

Angular CLI 升级 6.0 之后遇到的问题

1962
来自专栏个人随笔

Java Eclipse和MyEclipse快捷键

 首先: 常用快捷键 alt+/ - - 万能快捷键 Ctrl+1 - - 快速修复 Eclipse和MyEclipse快捷键 (1)Ctrl+M --切换窗口...

3529
来自专栏林德熙的博客

WPF 如何画出1像素的线

如何有人告诉你,请你画出1像素的线,是不是觉得很简单,实际上在 WPF 上还是比较难的。 本文告诉大家,如何让画出的线不模糊

1291
来自专栏用户2442861的专栏

Qt 常用类 (9)—— QWidget

http://blog.csdn.net/hmsiwtv/article/details/7562015

1111
来自专栏Flutter入门

Flutter开发实战分析-animation_demo解析导读

以下代码基本参考于 flutter_gallery中的animation_demo示例。(可以结合本文看源码) 整体动画效果预览

5083
来自专栏偏前端工程师的驿站

HTML语义化:HTML5的新标签及IE5.5~9的部分兼容方案

一、前言                               本文将介绍HTML5中新增的语义化标签,及在IE5.5~9(IE9已经开始支持部分HTML...

19610
来自专栏葡萄城控件技术团队

Spread for Windows Forms快速入门(3)---行列操作

开发人员可以定义用户与行和列的交互,如是否可以更改行或列的大小、是否可以移动行或列、冻结指定的行或列、在行或列中查找数据等。 更改行或列的大小 你可以允许用户重...

2626
来自专栏游戏杂谈

EditPlus中有用的快捷键

点击到该标记(全选或光标落在里面即可)按下ctrl+[就可以找到匹配的标签了。权支持HTML标签的匹配。

872

扫码关注云+社区