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

CSS Modules 学习

作者头像
李振
发布2021-11-26 13:52:32
4580
发布2021-11-26 13:52:32
举报
文章被收录于专栏:乱码李乱码李

CSS Modules 的用法很简单,不过现阶段还需要 webpack 的支持。CSS Modules 的功能非常少,它一共就干了两件事:局部作用域和模块依赖。

CSS Modules 示例

代码地址

项目路径

代码语言:javascript
复制
├── README.md
├── index.html
├── node_modules
│?? └── ...
├── package.json
├── src
│?? ├── animation.css
│?? ├── colors.css
│?? ├── index.js
│?? └── style.css
└── webpack.config.js

把文件 clone 下来后,安装依赖,然后就可以运行了

代码语言:javascript
复制
$ git clone https://github.com/Leo555/css_modules_study.git
$ cd css_modules_study
$ npm install
$ npm run start

浏览器会自动打开静态文件,方便查看效果。

CSS Modules 用法

webpack

首先配置 webpack 环境(本文使用webpack2),给 css-loader 增加一个 modules 查询参数,表示打开 CSS Modules 功能。

简单的示例如下:

代码语言:javascript
复制
module: {
  rules: [{
    test: /\.css$/,
    loader: "style-loader!css-loader?modules"
  }]
},

如果需要给 CSS Modules 传递一些参数,可以用对象的方式:

代码语言:javascript
复制
module: {
  rules: [{
    test: /\.css$/,
    use: ["style-loader", 
    {
      loader: "css-loader",
      options: {
        modules: true,
        localIdentName: '[path][name]__[local]--[hash:base64:5]',
        importLoaders: 1,
        camelCase: true
      }
    }]
  }]
}

作用域

开启 CSS Modules 后,所有的 CSS 选择器都是局部作用域,除非声明它为全局的。

代码语言:javascript
复制
/*Scoped Selectors*/
.className {
  color: green;
  margin: 10px 0;
}

/*Global Selectors*/
:global(.text) {
  font-size: 22px;
}

以上两个 CSS class 通过如下方法被 JS 引用

代码语言:javascript
复制
import styles from "./style.css";
// import { className } from "./style.css";

let app = document.getElementById('app')
app.innerHTML = 
`
<div class="${styles.className}">Hello CSS Modules</div>
<div class="text">Global Selectors</div>
`

后面的引用方式都相同,因此略去,具体可查看 index.js

查看构建后的 CSS,发现局部变量的名字被编译成 hash (localIdentName: '[path][name]__[local]--[hash:base64:5]'),而全局变量的名字不变。

css-modules
css-modules

原来 CSS Modules 就做了这么一点微小的工作。

class 继承和重写

CSS Modules 通过组合的方式进行集成,以达成代码复用的效果。

代码语言:javascript
复制
/*Class Composes*/
.otherClassName {
  composes: className;
  width: 220px;
  height: 60px;
  line-height: 60px;
  border-width: 2px;
  border-style: solid;
}

/*Composes Overrides*/
.background {
  border-radius: 20px;
  background: #efefef;
  composes: otherClassName;
  border-style: dotted;
}

otherClassName 继承 className,因为拥有了 color 和 margin 属性,而 background 继承 otherClassName,却重写了 border-style。

局部动画

在 animation.css 中,定义了动画 tada:

代码语言:javascript
复制
@keyframes tada {
  from {
    transform: scale3d(1, 1, 1);
  }
  10%, 20% {
    transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg);
  }
  30%, 50%, 70%, 90% {
    transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
  }
  40%, 60%, 80% {
    transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
  }
  to {
    transform: scale3d(1, 1, 1);
  }
}

.tada {
  animation: tada 2s infinite;
}

在 style 中的引用方式如下:

代码语言:javascript
复制
/*Scoped Animations*/
.backgroundAnimation {
  composes: background;
  composes: tada from './animation.css';
}

上面第二个 composes 也展示了如何从其它 CSS 模块中引用选择器。

定义变量

通过 @value 定义变量和引用变量

colors.css

代码语言:javascript
复制
@value color: black;
@value fontSize: 22px;

引用方式

代码语言:javascript
复制
/*Define variables*/
@value colors: "./colors.css";
@value color, fontSize from colors;

.color {
  composes: otherClassName;
  color: color;
  font-size: fontSize;
}

Vue 结合 CSS Modules

vue-loader 中集成了 CSS Modules,可以作为模拟 CSS 作用域的替代方案。

使用

<style> 上添加 module 属性即可开启 CSS Modules 模式:

代码语言:javascript
复制
<style module>
.red {
  color: red;
}
.bold {
  font-weight: bold;
}
</style>

css-loader 会自动将生成的 CSS 对象注入到 $style 中,只需要在 <template> 中使用动态 class 绑定:

代码语言:javascript
复制
<template>
  <p :class="$style.red">
    This should be red
  </p>
</template>

由于它是一个计算属性,它也适用于 :class 的 object/array 语法:

代码语言:javascript
复制
<template>
  <div>
    <p :class="{ [$style.red]: isRed }">
      Am I red?
    </p>
    <p :class="[$style.red, $style.bold]">
      Red and bold
    </p>
  </div>
</template>

在 JavaScript 访问它:

代码语言:javascript
复制
<script>
export default {
  created () {
    console.log(this.$style.red)
  }
}
</script>

自定义注入名称

在 .vue 中可以定义不止一个 <style>,为了避免被覆盖,你可以通过设置 module 属性来为它们定义注入后计算属性的名称。

代码语言:javascript
复制
<style module="a">
  /* identifiers injected as a */
</style>

总结

在前端模块化的道路上,CSS 显然落后 JS 非常多。ES2015/ES2016 的快速普及和 Babel/webpack 等工具的发展,让 JS 在大型项目工程化中越发强大,最终成为一流语言

CSS Modules 解决了哪些问题呢?

  1. 消除了全局命名的问题,再也不用担心不同文件之间的命名冲突了,也不用写一层又一层的选择器了。
  2. 通过 JS 去管理 CSS 之间的依赖,在引入组件的时候,可以只引入次组件需要的 CSS,组件更加独立。
  3. CSS 变量 可以在 CSS 和 JS 中共享,对于复杂组件的使用会有奇效。
  4. 对代码压缩也有一定帮助。

CSS 模块化的解决方案有很多,但主要有两类。一类是彻底抛弃 CSS,使用 JS 或 JSON 来写样式。Radium,jsxstyle,react-style 属于这一类。优点是能给 CSS 提供 JS 同样强大的模块化能力;缺点是不能利用成熟的 CSS 预处理器(或后处理器) Sass/Less/PostCSS,:hover 和 :active 伪类处理起来复杂。另一类是依旧使用 CSS,但使用 JS 来管理样式依赖,代表是 CSS Modules。CSS Modules 能最大化地结合现有 CSS 生态和 JS 模块化能力,API 简洁到几乎零学习成本。发布时依旧编译出单独的 JS 和 CSS。它并不依赖于 React,只要你使用 Webpack,可以在 Vue/Angular/jQuery 中使用。是我认为目前最好的 CSS 模块化解决方案。

引自 CSS Modules 详解及 React 中实践

参考资料

本文参与?腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-06-21,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • CSS Modules 示例
  • CSS Modules 用法
    • webpack
      • 作用域
        • class 继承和重写
          • 局部动画
            • 定义变量
            • Vue 结合 CSS Modules
              • 使用
                • 自定义注入名称
                • 总结
                • 参考资料
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
                http://www.vxiaotou.com