资讯专栏INFORMATION COLUMN

CSS Modules实践

hankkin / 549人阅读

摘要:能最大化地结合现有生态预处理器后处理器等和模块化能力,几乎零学习成本。编码相关的所有样式上例中打印的结果是注意到是按照自动生成的名。实践手动引用渲染结果使用可以实现使用属性自动加载模块。

文章同步于Github Pines-Cheng/blog

随着前端这几年的风生水起,CSS作为前端的三剑客之一,各种技术方案也是层出不穷。从CSS prepocessor(SASS、LESS、Stylus)到后来的后起之秀 PostCSS,再到 CSS ModulesStyled-Component 等。有人维护了一份完整的 CSS in JS 技术方案的对比,里面已经有将近50种技术方案。CSS Modules就是其中一种。

CSS Modules 介绍

要弄懂CSS Modules是什么,可以先看官方介绍:GitHub – css-modules/css-modules: Documentation about css-modules。

通过上面介绍可以看出,CSS Modules既不是官方标准,也不是浏览器的特性,而是在构建步骤(例如使用Webpack或Browserify)中对CSS类名选择器限定作用域的一种方式(通过hash实现类似于命名空间的方法)。例如我们在buttons.js里引入buttons.css文件,并使用.btn的样式,在其他组件里是不会被.btn影响的,除非它也引入了buttons.css.

CSS模块化

JS已经全面实现了模块化,但是css还处于探索阶段。为什么我们需要css模块化?主要由一下几个原因。

CSS全局作用域问题

CSS的规则都是全局的,任何一个组件的样式规则,都对整个页面有效。现在的前端工程大多是基于组件开发,随着工程的页面数量好复杂度的提升,相信写css的人都会遇到样式冲突(污染)的问题。一般我们会采用一下几种方法:

class命名写长一点吧,降低冲突的几率

加个父元素的选择器,限制范围

重新命名个class吧,比较保险

可是以上方案只是降低了全局冲突的概率,并不能彻底解决全局冲突的问题。并且,实现方式也不够优雅,还增加了代码的复杂和冗余。

我们的追求

面向组件开发 : 处理 UI 复杂性的最佳实践就是将 UI 分割成一个个的小组件,React 就鼓励高度组件化和分割。我们希望有一个 CSS 架构去匹配。

沙箱化(Sandboxed) : 如果一个组件的样式会对其他组件产生不必要以及意想不到的影响,那么将 UI 分割成组件并没有什么用。就这方面而言,CSS的全局作用域会给你造成负担。

方便 :不会增加开发的负担和代码的冗余。

方案

CSS 模块化的解决方案有很多,但主要有三类。

CSS 命名约定

规范化CSS的模块化解决方案(比如BEM BEM — Block Element Modifier ,OOCSS,AMCSS,SMACSS,SUITCSS)
但存在以下问题:

JS CSS之间依然没有打通变量和选择器等

复杂的命名

CSS in JS

彻底抛弃 CSS,用 JavaScript 写 CSS 规则,并内联样式。styled-components 就是其中代表。styled-components可以让CSS真正意义地写到JS里面,同时让标签更具有语意化,这跟HTML5新标签思想相同;该框架让样式也具备组件化思想,让前端完全面向组件化编程,就像java的包装类型。
但存在以下问题:

样式代码也会出现大量重复。

不能利用成熟的 CSS 预处理器(或后处理器)

使用 JS 来管理样式模块

使用JS编译原生的CSS文件,使其具备模块化的能力,代表是 CSS Modules。

CSS Module还是JS和CSS分离的写法,不会改变大家的书写习惯,CSS Module只需修改构建代码和使用模块依赖引入className的方式即可使用,且支持less和sass的语法,

使用CSS Modules可以让组件className控制权转交给JS,我们不会去关心命名冲突污染等问题,同时可以灵活控制生成的命名,样式代码不用修改即可让使用CSS语法的旧项目零成本接入。

CSS Modules 能最大化地结合现有 CSS 生态(预处理器/后处理器等)和 JS 模块化能力,几乎零学习成本。只要你使用 Webpack,可以在任何项目中使用。是目前最好的 CSS 模块化解决方案。

使用 配置

CSS Modules配置非常简单,如果你使用webpack,只需要在配置文件中改动一行即可。

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

加上 modules 即为启用,localIdentName 是设置生成样式的命名规则。

编码

css

/* components/Button.css */
.normal { /* normal 相关的所有样式 */ }
 

js

// components/Button.js
import styles from "./Button.css";
console.log(styles);
buttonElem.outerHTML = ``

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

Object {
  normal: "button--normal-abc53",
  disabled: "button--disabled-def886",
}
 

注意到 button--normal-abc53 是 CSS Modules 按照 localIdentName 自动生成的 class 名。其中的 abc53 是按照给定算法生成的序列码。经过这样混淆处理后,class 名基本就是唯一的,大大降低了项目中样式覆盖的几率。同时在生产环境下修改规则,生成更短的 class 名,可以提高 CSS 的压缩率。

CSS Modules 对 CSS 中的 class 名都做了处理,使用对象来保存原 class 和混淆后 class 的对应关系。

React实践 手动引用
import React from "react";
import styles from "./table.css";
 
export default class Table extends React.Component {
    render () {
        return 
; } }

渲染结果:

使用babel-plugin-react-css-modules

babel-plugin-react-css-modules 可以实现使用styleName属性自动加载CSS模块。只需要把className换成styleName即可获得CSS局部作用域的能力,babel插件来自动进行语法树解析并最终生成className。改动成本极小,不会增加JSX的复杂度,也不会给项目带来额外的负担。

import React from "react";
import styles from "./table.css";
 
class Table extends React.Component {
    render () {
        return 
; } } export default Table;

CSS Modules 很好的解决了 CSS 目前面临的模块化难题。支持与 CSS处理器搭配使用,能充分利用现有技术积累。如果你的产品中正好遇到类似问题,非常值得一试。

参考

CSS Modules 入门及 React 中实践

CSS Modules 用法教程

Styled Components:让样式也成为组件

精读《请停止 css-in-js 的行为》

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/112299.html

相关文章

  • CSS Modules详解及React中实践

    摘要:上例中打印的结果是对中的名都做了处理,使用对象来保存原和混淆后的对应关系。结合实践在处直接使用中名即可。如因为只会转变类选择器,所以这里的属性选择器不需要添加。 showImg(http://gtms01.alicdn.com/tps/i1/TB15w0HLpXXXXbdaXXXjhvsIVXX-600-364.png); CSS 是前端领域中进化最慢的一块。由于 ES2015/201...

    wemall 评论0 收藏0
  • React项目 - 几种CSS实践

    摘要:一切样式都是全局,产生的各种命名的痛苦,等命名规则能解决一部分问题,但当你使用三方插件时却无法避免命名冲突。这一解决法的优雅在于,全局的可以正常使用,只有带后缀的才会被化使用的模板字符串,在文件里写纯粹的。 前言团队在使用react时,不断探索,使用了很多不同的css实现方式,此篇blog总结了,react项目中常见的几种css解决方案:inline-style/radium/styl...

    princekin 评论0 收藏0
  • React实践(一)——webpack4搭建开发环境

    摘要:按需引入在入口文件中引入全局的如果仅仅是这样的话,我们加载组件是全部加载的,这时候我们要在的中配置这样之后就可以按照的官网来使用里的组件了。啦,这样一个简单的开发环境就搭建好了。 github 1、创建基本目录结构 npm init 创建src文件夹,再其中新建index.html 安装webpack依赖:npm install webpack webpack-cli webpack...

    Simon 评论0 收藏0
  • Webpack 最佳实践总结(三)

    摘要:这里要介绍的是工作流中的一种很普遍的代码加工流程正常的业务逻辑开发流程需要经过预处理器如或,然后再经过后处理器如进行深加工。 还未看的,可以点击查看上两篇文章哟:Webpack 最佳实践总结(一)、Webpack 最佳实践总结(二) 好了,这篇是第三篇,也是完结篇,我感觉这一篇是最乱的一篇,凑合着看吧,不会让你失望的 整合 CSS 加工流 有时候,前端项目中除了 JavaScript ...

    pkhope 评论0 收藏0
  • Webpack 最佳实践总结(三)

    摘要:这里要介绍的是工作流中的一种很普遍的代码加工流程正常的业务逻辑开发流程需要经过预处理器如或,然后再经过后处理器如进行深加工。 还未看的,可以点击查看上两篇文章哟:Webpack 最佳实践总结(一)、Webpack 最佳实践总结(二) 好了,这篇是第三篇,也是完结篇,我感觉这一篇是最乱的一篇,凑合着看吧,不会让你失望的 整合 CSS 加工流 有时候,前端项目中除了 JavaScript ...

    jerryloveemily 评论0 收藏0

发表评论

0条评论

hankkin

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<