资讯专栏INFORMATION COLUMN

CSS Modules

wangdai / 2515人阅读

摘要:为什么引入全局样式冲突进行打包时,将所有文件导入到入口文件中,样式也会统一加载到入口中,根据的规则,后面的样式会覆盖掉前面的样式声明,造成全局样式的覆盖问题。

CSS Modules 为什么引入CSS Modules

(1)全局样式冲突
webpack进行打包时,将所有js文件导入到入口App.js文件中,样式也会统一加载到入口中,根据css的layout规则,后面的样式会覆盖掉前面的样式声明,造成全局样式的覆盖问题。
(2)嵌套层次过深的选择器
为了解决全局样式的冲突问题,不得不引入一些特地命名namespace来区分,但是往往有些namespace命名得不够清晰,就会造成要想下一个样式不会覆盖,就要再加一个新的命名空间来进行区分,最终可能一个元素的显示样式嵌套特别深。

嵌套特别深会造成的问题:
- 根据CSS选择器的解析规则可以知道,层级越深,比较的次数也就越多,影响整个页面的渲染
- 增加了不必要的字节开销
- 语义混乱 可扩展性不好,约束越多,扩展性越差

(3)无法共享变量
复杂组件要使用 JS 和 CSS 来共同处理样式

一些解决方案

(1)css预处理器(less/sass) 支持模块引入

存在问题:不能解决全局样式冲突问题

(2)BEM(Block Element Modifier)解决命名冲突以及更好的语义化

Block:逻辑和页面功能都独立的页面组件,是一个可复用单元,特点如下:

可以随意嵌套组合

可以放在任意页面的任何位置,不影响功能和外观

可复用,界面可以有任意多个相同Block的实例

Element:Block的组成部分,依赖Block存在(出了Block就不能用)

[可选]定义Block和Element的外观及行为,就像HTML属性一样,能让同一种Block看起来不一样

存在问题:对于嵌套过深的层次在命名上会给需要语义化体现的元素造成很大的困难 对于多人协作上,需要统一命名规范,这同样也会造成额外的effort

CSS Modules

(1)什么是css modules

通过构建工具来使指定class达到scope的过程

(2)css modules优势

解决全局命名冲突问题 css modules只关心组件本身 命名唯一

模块化 可以使用composes来引入自身模块中的样式以及另一个模块的样式

解决嵌套层次过深的问题 使用扁平化的类名

(3)css modules的用法

开启css modules功能
由于css modules对样式的处理逻辑是放在loader中,所以在css-loader中开启css-loader

{
    test: /.css$/,
    use: [
      {
        loader: MiniCssExtractPlugin.loader,
        options: {
          publicPath: "./build/styles"
        }
      },
      { 
        loader: "css-loader",
        options: {
            importLoaders: 1,
            modules: true,
            localIdentName: "[name]__[local]___[hash:base64:5]"  // 为了生成类名不是纯随机
        }
      }
    ]
}        

修改index.js文件中对样式的引入方式

import styles from "./index.css"; // 导出对象的格式是键值对 

编译之后的类使用

//index.css
.color{
  color:blue;
}

// index.js
import styles from "./index.css"; // 导出对象的格式是键值对 

// jsx
使用转化后的类名
// 如果以下划线给类命名使用styles["color-style"]

(4)其他用法

局部变量和全局变量

:local 做localIdentName规则处理(类名进行编译 默认可以不写)

:global 样式编译后不变

/*下面两种进行编译*/
.normal {
 color: green;
 }
:local(.normal) {
  color: green; 
}

/*下面两种不会进行编译*/
// 多个类不编译
:global {
  .link {
    color: green;
  }
  .box {
    color: yellow;
  }
}
// 单个类不编译
:global(.box){
  color:blue;
}

compose组合class(需要样式复用,在 CSS Modules 中,一个选择器可以继承另一个选择器的规则) 自身引入的声明的优先级会比较高

    /* 同一个css文件中复用类*/
    .bg {
        background-color:blue;
        }
    
    .title {
        composes:bg;
        color:white;
        }
    
   // js中使用
    import styles from "./test.css";
    
css modules
// 生成的HTML
css modules
   /* 不同css文件中复用类*/ 
    /* color.css */
     .red {
       color: red;
      }

    .blue {
      color: blue;
    }

    /* index.css */
    .red {
        color: red;
    }

    .header {
        font-size: 32px;
    }

    .title {
        color: green;
        composes: blue from "./color.css";
        border-bottom: 1px solid #ccc;
        padding-bottom: 20px;
    }    

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);

备注

项目中如果使用antd 需要将antd样式不进行编译
使用exclude排除exclude中指定目录的资源。在node-modules中关闭css-module,在我们自己写的src下的css开启css-module

  {
    test: /.css$/,
    exclude: /node_modules|antd.css/,
    use: [
      {
        loader: MiniCssExtractPlugin.loader,
        options: {
          publicPath: "./build/styles"
        }
      },
      { 
        loader: "css-loader",
        options: {
            importLoaders: 1,
            modules: true,
            localIdentName: "[name]__[local]___[hash:base64:5]"  // 为了生成类名不是纯随机
        }
      }
    ]
}        

项目中使用stylelint进行css检查 需要在stylelint配置忽略css-modules的关键字

 module.exports = {
  rules: {
    "selector-pseudo-class-no-unknown": [
      true,
      {
        ignorePseudoClasses: [
          "export",
          "import",
          "global",
          "local",
          "external",
        ],
      },
    ],
    "selector-type-no-unknown": [
      true,
      {
        ignoreTypes: ["from"],
      },
    ],
    "property-no-unknown": [
      true,
      {
        ignoreProperties: ["composes", "compose-with"],
      },
    ],
    "at-rule-no-unknown": [
      true,
      {
        ignoreAtRules: ["value"],
      },
    ],
  },
};

推荐css解决方案文章:
React拾遗:从10种现在流行的 CSS 解决方案谈谈我的最爱 (上)
CSS Modules入门及React中实践

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

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

相关文章

  • 简单易懂的CSS Modules

    摘要:结果是选手获胜,名为的元素,最终的值为。而合理的命名约定,的确是组织代码的有效策略。它们会再由转换为适当的组合。虽然本文为了严谨,结果写了相当长的篇幅,但希望你读过之后,还能觉得是简单易懂的。 不要误会,CSS Modules可不是在说css模块化这个好像在某些地方见过的词,它其实是特指一种近期才出现的技术手段。 什么技术手段呢?请待后文说明。 层叠样式表 我们知道,css的全名叫做层...

    chunquedong 评论0 收藏0
  • CSS Modules实践

    摘要:能最大化地结合现有生态预处理器后处理器等和模块化能力,几乎零学习成本。编码相关的所有样式上例中打印的结果是注意到是按照自动生成的名。实践手动引用渲染结果使用可以实现使用属性自动加载模块。 文章同步于Github Pines-Cheng/blog 随着前端这几年的风生水起,CSS作为前端的三剑客之一,各种技术方案也是层出不穷。从CSS prepocessor(SASS、LESS、Styl...

    hankkin 评论0 收藏0
  • CSS Modules详解及React中实践

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

    wemall 评论0 收藏0
  • CSS Modules

    摘要:为什么引入全局样式冲突进行打包时,将所有文件导入到入口文件中,样式也会统一加载到入口中,根据的规则,后面的样式会覆盖掉前面的样式声明,造成全局样式的覆盖问题。 CSS Modules 为什么引入CSS Modules (1)全局样式冲突 webpack进行打包时,将所有js文件导入到入口App.js文件中,样式也会统一加载到入口中,根据css的layout规则,后面的样式会覆盖掉前...

    gecko23 评论0 收藏0
  • CSS module 入门

    摘要:示例库通过记录来查看定制类名默认的哈希算法是,从前面我们可以发现被编译成了这样的字符串。与上面不加等价显式的局部作用域语法通过示例库的记录来查看下的样式复用对于样式复用,提供了组合的方式来处理。 showImg(https://segmentfault.com/img/bV9WfX?w=800&h=274);前端发展越来越快,这应该是每个前端开发者的切身感受,但是CSS 是前端领域中进...

    warnerwu 评论0 收藏0

发表评论

0条评论

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