前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CSS Modules使用详解

CSS Modules使用详解

作者头像
IMWeb前端团队
发布2019-12-04 22:49:29
1.8K0
发布2019-12-04 22:49:29
举报
文章被收录于专栏:IMWeb前端团队IMWeb前端团队

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

代码语言:javascript
复制
// webpack.config.js
css?modules&localIdentName=[name]__[local]-[hash:base64:5]

加上 modules 即为启用, localIdentName 是设置生成样式的命名规则,[name]表示标签名,[local]表示类名,[hash:base64:5]是按照给定算法生成的序列码。

代码语言:javascript
复制
/* 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 是

代码语言:javascript
复制
<h1 class="h1--active-abc53"> Processing... </h1>

它将根据 styleName 的值在关联的 style 对象中查找对应的 CSS Modules,并为 ReactElement className 属性值添加相匹配的独一无二的 CSS 类名。

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

代码语言:javascript
复制
Object {
  active: 'h1--active-abc53',
  disabled: 'h1--disabled-def84',
}

CSS Modules 对 CSS 中的 class 名都做了处理,使用对象来保存原 class 和定制处理后的 class 的对应关系。经过这样类名定制处理后,class 名基本就是唯一的,大大降低了项目中样式覆盖的几率。同时可以生成更短的 class 名,减少代码量。

CSS Modules 使用

局部变量和全局变量
  • :local: 做 localIdentName 规则处理
  • :global: 样式编译后不变

如果书写时不加,默认处理为:local

代码语言:javascript
复制
.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 组合。

代码语言:javascript
复制
/* 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 为

代码语言:javascript
复制
<h1 class="h1--bg-fec53 h1--title-Ijf8"> Processing... </h1>
CSS和JS变量共享

:export 关键字可以把 CSS 中的 变量输出到 JS 中:

代码语言:javascript
复制
/* 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 的局部样式和谐共存。
代码语言:javascript
复制
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'
  }]
}
本文参与?腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016-12-29 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客?前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • CSS Modules
    • CSS 模块化
      • 启用 CSS Modules
        • CSS Modules 使用
          • 局部变量和全局变量
          • 唯一哈希类名
          • Compose 组合Class
          • CSS和JS变量共享
        • CSS Modules使用特点
          • 旧项目的兼容
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
          http://www.vxiaotou.com