• CSS模块化解决命名冲突---css module


    css模块化解决冲突

    CSS作用域是全局的,项目越来越大,人越来越多,命名慢慢成为了问题,难免会出现命名重复的问题,于是也诞生了相应的模块化解决方案。
    目前有这几类:

    • 1.CSS 命名方法论:通过人工的方式来约定命名规则。
    • 2.CSS Modules:一个 CSS 文件就是一个独立的模块。
    • 3.CSS-in-JS:在 JS 中写 CSS。
    • 4.HTML5的style scoped

    CSS 命名方法论

    BEM

    BEM即为块级元素修饰字符(Block Element Modifier),以 .block__element–modifier 形式命名,即 .模块名__元素名修饰符名 三个部分,用双下划线 __ 来明确区分模块名和元素名,用双横线 – 来明确区分元素名和修饰符名。

    .box__menu-item--active {}
    
    • 1

    这种命名主要还是人为去遵守命名约束

    Atomic CSS

    Atomic CSS是原子化的CSS,就是将单一的属性封装一个Class,保证没有重复的样式,这样便于属性的复用,同时也会导致样式复杂的元素Class非常臃肿。

    <div class="mt-10 w-100 h-15"></div> 
    
    • 1

    CSS Modules

    css module 遵循以下思路解决类名冲突问题:

    • css的类名冲突往往发生在大型项目中
    • 大型项目往往会使用构建工具(webpack等)搭建工程
    • 构建工具允许将css样式切分为更加精细的模块
    • 同JS的变量一样,每个css模块文件中难以出现冲突的类名,冲突的类名往- - 往发生在不同的css模块文件中
    • 只需要保证构建工具在合并样式代码后不会出现类名冲突即可

    CSS Modules既不是官方标准,也不是浏览器的特性,而是在构建步骤(例如使用 Webpack 或 Browserify)中对 CSS 类名选择器限定作用域的一种方式(通过 hash 实现类似于命名空间的方法)。

    webpack自带的css-loader 组件,自带了 CSS Modules,通过简单的配置即可使用。

    module.exports = {
      module: {
        rules: [
          {
            test: /\.css$/,
            use: [
              'style-loader',
              {
                loader: 'css-loader',
                options: {
                  modules: true,
                }
              }
            ],
          },
        ]
      }
    };
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    自定义生成的类名
    css-loader默认的哈希算法是[hash:base64],但是我们可能有需求去自定义想要的类名格式,css-loader为我们提供了localIdentName参数指定生成的名字格式。

    module.exports = {
      module: {
        rules: [
          {
            test: /\.css$/,
            use: [
              'style-loader',
              {
                loader: 'css-loader',
                options: {
                  modules: true,
                  localIdentName: '[name]__[local]-[hash:base64:5]',
                }
              }
            ],
          },
        ]
      }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    Vue使用module

    <template>
     <p :class="$style.gray">
     Im gray
     </p>
    </template>
    <style module>
    .gray {
     color: gray;
    }
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    编译后结果:

    <p class="gray_3FI3s6uz">Im gray</p>
    .gray_3FI3s6uz {
     color: gray;
    }
    
    • 1
    • 2
    • 3
    • 4

    作用域

    CSS Modules 通过默认的局部作用域 :local来实现样式的局部化,使用全局作用域 :global 来实现样式的全局化,同时全局的类名打包不会被编译成哈希字符串。

    // 局部样式(可以省略:local)
    .normal {
      color: green;
    }
    
    :local(.normal) {
      color: green; 
    }
    
    
    // 全局样式
    :global(.btn) {
      color: red;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    全局类名

    某些类名是全局的、静态的,不需要进行转换,仅需要在类名位置使用一个特殊的语法即可:

    :global(.main){
        ...
    }
    
    • 1
    • 2
    • 3

    使用了global的类名不会进行转换,相反的,没有使用global的类名,表示默认使用了local

    :local(.main){
        ...
    }
    
    • 1
    • 2
    • 3

    使用了local的类名表示局部类名,是可能会造成冲突的类名,会被css module进行转换

    注意点

    在处理动画animation的关键帧keyframes,动画名称必须先写。比如,animation: deni .5s,能正常编译; animation: .5s deni, 则编译异常
    记得配置css-loader,否则不会生效。
    若使用的是style-loader,则需配置更换为vue-style-loader才可生效。
    css modules如何解决权重问题?

    优点:允许通过重命名或命名空间来封装样式规则,减少对选择器的约束,从而达到不需要特定方法就可舒服的使用类名。当样式规则耦合到每个组件时,当不再使用组件时,样式也会被移除。

    CSS in JS

    彻底抛弃 CSS,用 JavaScriptCSS 规则,并内联样式。 React: CSS in JS // Speaker Deck。Radium,react-style 属于这一类。但存在以下问题:

    • 无法使用伪类,媒体查询等
    • 样式代码也会出现大量重复。
    • 不能利用成熟的 CSS 预处理器(或后处理器)

    使用 JS 来管理样式模块
    使用 JS 编译原生的 CSS 文件,使其具备模块化的能力

    css scoped

    vue通过在DOM结构以及css样式上加唯一不重复的标记,以保证唯一,达到样式私有化模块化的目的。无法完全避开css权重和类名重复的问题。

    <style scoped>
    .example {
      color: red;
    }
    </style>
    
    <template>
      <div class="example">hi</div>
    </template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    转化

    <style>
    .example[data-v-f3f3eg9] {
      color: red;
    }
    </style>
    
    <template>
      <div class="example" data-v-f3f3eg9>hi</div>
    </template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    注意:

    1. scoped在DOM中添加了一个唯一的属性data-v-f3f3eg9,在css中也添加了一个属性.example[data-v-f3f3eg9]
    来保证唯一性,这样如果外部使用了同名的class,依然有可能影响组件的样式
    2. scoped使用了属性选择器,会使得选择的效率降低
    3. scoped在html和css中都添加了哈希值,会使得两者的提交都变大,降低加载速度,影响渲染效率
    4. scoped修改子组件的样式,必须使用深度选择器
    
    • 1
    • 2
    • 3
    • 4
    • 5

    缺点:

    如果用户在别处定义了相同的类名,也许还是会影响到组件的样式。
    根据css样式优先级的特性,scoped这种处理会造成每个样式的权重加重,引用 使用了scoped的组件
    作为子组件,修改子组件的样式变得很难,可能迫不得已只能用!important
    scoped会使 标签选择器 渲染变慢很多倍,用标签选择器时scoped会严重降低性能,而使用class或id则不会

    总体而言,CSS Modules优于scoped,提倡使用CSS Modules。
    参考文章:https://juejin.cn/post/6994046975851102239

  • 相关阅读:
    和iPhone14一样高的像素?全网首测OAK-1-MAX人工智能相机
    Java 生成随机码工具类 线程安全 两种方式
    4-3:点赞功能
    三十、java版 SpringCloud分布式微服务云架构之Java 集合框架
    记一次线上故障--HashMap在多线程条件下运行造成CPU 100%
    Spring Boot 常用注解汇总
    Xline 源码解读(三) —— CURP Server 的实现
    Redis分布式锁
    【路径规划】基于VFH算法实现机器人路径规划附matlab代码
    Go 使用 RabbitMQ---------------之一
  • 原文地址:https://blog.csdn.net/nihaio25/article/details/125540575