css命名冲突怎么办?原理是啥?

本文探讨了CSS命名冲突的问题及其解决办法,包括人为约定、CSS in JS、使用CSS Modules和HTML5的style scoped。推荐使用CSS Modules,因为它能有效避免类名冲突,且提供了良好的模块化管理。

CSS命名冲突

通常我们在项目开发中每个人负责不同的模块,对于样式设置的时候可能设置了同样的类选择器的类名,这个时候就会出现命名冲突,那怎么解决呢?

方法一:人为约定

比如说在开发之前就人为的制定一下命名规则以避免冲突,例如前缀,嵌套等。

方法二:CSS in JS

CSS in JS是将应用的CSS样式写在JavaScript文件里面 ,而不是独立为一些 css、scss 或者 less 之类的文件,这样你就可以在CSS中使用一些属于JS的诸如模块声明,变量定义,函数调用和条件判断等语言特性来提供灵活的可扩展的样式定义的这样一种技术,最常见的是styled-components

核心思想:用一个JS对象来描述样式,而不是css样式表。

const styles = {
    backgroundColor: "#f40",
    color: "#fff",
    width: "400px",
    height: "500px",
    margin: "0 auto"
}

这种描述样式的方式根本就不存在类名,自然不会有类名冲突

缺点

  • 书写不是很方便,特别是公共样式的时候,处理起来不是很方便。
  • 在页面中处理css in js时,往往是将样式加入到元素的style属性中,会大量增加元素的内联样式,并且可能会有大量重复,不易阅读最终的页面代码。
方法三:使用编译工具改变css类名:比如 css Modules

解决思路

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

原理

  • 在webpack中,处理css的是css-loader,启用css module,需要将css-loader的配置modules设置为true,启用后,css-loader会将样式中的类名进行转换,转换为一个唯一的hash值
    • 由于hash值是根据模块路径和类名生成的,不同的模块即使类名一样hash值也不一样

样式怎么使用呢?

  • 源代码的类名最终生成的类名不一样的,开发者也不知道这个hash值,怎么应用类名到元素上呢?
    • 通过一个对象描述原类名最终类名的对应关系,css-loader会导出他们的对应关系,可以在js代码中获取到css模块导出的结果(即描述的对象),从而应用类名
    • style-loader为了我们更加方便的应用类名,会去除掉其他信息,仅暴露对应关系

注意

  • 全局类名是不需要担心会出现冲突的问题,所以不需要css-loader进行转换,仅需要在类名位置使用一个特殊的语法即可,也就是使用global的类名,其他的默认为local,而local是可能出现命名冲突的,所以需要进行处理。
    :global(.main){
        ...
    }
    
  • 绝大部分情况下,我们都不需要控制最终的类名,如果一定要控制最终的类名,需要配置css-loader的localIdentName
  • 其他注意事项
    • css module往往配合构建工具(比如webpack)使用。
    • css module仅处理顶级类名,尽量不要书写嵌套的类名。
    • css module仅处理类名,不处理其他选择器。
    • css module还会处理id选择器
    • 使用了css module后,只要能做到让类名望文知意即可不需要遵守其他任何的命名规范
方法四:HTML5的style scoped

可以部分解决css重名问题,但缺陷很多!!!

原代码

<style scoped>
.example {
  color: red;
}
</style>

<template>
  <div class="example">hi</div>
</template>

转换后代码

<style>
.example[data-v-f3f3eg9] {
  color: red;
}
</style>

<template>
  <div class="example" data-v-f3f3eg9>hi</div>
</template>

原理分析

  • scoped在DOM中添加了一个唯一的属性data-v-f3f3eg9,在css中也添加了一个属性.example[data-v-f3f3eg9]来保证唯一性,这样如果外部使用了同名的class,依然有可能影响组件的样式。

缺点

  • scoped使用了属性选择器,会使得选择的效率降低。
  • scoped在html和css中都添加了哈希值,会使得两者的提交都变大,降低加载速度,影响渲染效率。
  • scoped修改子组件的样式,必须使用深度选择器,形式如下所示:(可以使用 /deep/ 或者 >>>
<template>
  <div id="app">
    <gHeader></gHeader>
  </div>
</template>

<style lang="css" scoped>
  .gHeader /deep/ .name{ //第一种写法
      color:red;
  }
  .gHeader {
      /deep/ .name{
        color:red;
      }
  }
  .gHeader >>> .name{   //第二种写法
     color:red;
  }
</style>

<div class="gHeader">
  <div class="name"></div>
</div>
总结:CSS Modules优于scoped,提倡使用CSS Modules!!!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力不熬夜的小喵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值