样式冲突让人头疼?CSS Module 来拯救你

59 阅读3分钟

今天我们来聊一个在实际开发中经常遇到的问题——样式冲突。你有没有遇到过这种情况:改了一个页面的样式,结果另一个页面的样式也跟着乱了?别担心,CSS Module 就是来解决这个问题的!

开发过程中,我们遇到样式冲突如何解决?

先来说说我们平时是怎么遇到样式冲突的。比如你在写一个按钮组件:

/* button.css */
.button {
  background: blue;
  color: white;
}

然后在另一个地方也写了一个按钮:

/* submit.css */
.button {
  background: red;
  padding: 10px;
}

结果两个按钮样式互相影响,蓝色的按钮突然有了10px的内边距,红色的按钮文字变成了白色... 这就是典型的样式冲突!

传统的解决方案有:

  • 使用 BEM 命名规范(比如 .btn--primary__text
  • 增加额外的包裹层(比如 .page-1 .button
  • 使用 !important(千万别!)

但这些方法要么太麻烦,要么会带来新问题。这时候,CSS Module 闪亮登场!

什么是CSS Module?

简单来说,CSS Module 就是一个让你写的 CSS 只作用于当前组件的技术。它会在编译阶段自动给类名加上一串随机哈希值,这样就绝对不会和其他组件的类名冲突了。

比如你写的 .button,编译后会变成 .button_1a2b3c_xyz 这样的形式。

CSS Module 的背景

为什么会有 CSS Module 呢?因为前端项目越来越复杂,组件越来越多,传统的全局 CSS 已经撑不住了。想想一个大型项目有几百个组件,每个组件都有 .container.title.button,这不冲突才怪呢!

CSS Module 的出现就是为了让 CSS 也拥有"模块化"的能力,就像 JavaScript 的模块一样,每个组件的样式都是独立的作用域。

CSS Module 解决了哪些问题?

1. 彻底解决样式冲突

这是最核心的!每个组件的类名都是唯一的,再也不用担心重名问题了。

2. 嵌套层次过深的选择器

以前我们经常写出这样的 CSS:

.header .nav .list .item .link .icon {
  color: red;
}

有了 CSS Module,你只需要写:

.icon {
  color: red;
}

因为类名已经是唯一的了,不需要用长长的选择器来保证特异性。

3. 更好的维护性

组件和它的样式紧密关联,删除组件时也不用担心会影响到其他地方的样式。

CSS Module 如何使用?

说了这么多,怎么用呢?超级简单!

在 React 中使用

首先,你的 CSS 文件要命名为 [name].module.css

/* Button.module.css */
.primary {
  background: blue;
  color: white;
}

.secondary {
  background: gray;
  color: black;
}

然后在组件中这样使用:

import React from 'react';
import styles from './Button.module.css';

const Button = ({ type }) => {
  return (
    <button className={styles[type]}>
      点击我
    </button>
  );
};

export default Button;

// 使用方式:<Button type="primary" />

编译后的 HTML 会变成:

<button class="primary_1a2b3c_xyz">点击我</button>

在 Vue 中使用

Vue 单文件组件天然支持 CSS Module:

<template>
  <button :class="$style.button">点击我</button>
</template>

<style module>
.button {
  background: blue;
  color: white;
}
</style>

高级用法:组合样式

CSS Module 还支持样式组合:

/* base.module.css */
.base {
  padding: 10px;
  border-radius: 4px;
}

/* button.module.css */
.button {
  composes: base from './base.module.css';
  background: blue;
  color: white;
}

这样 .button 类就会同时拥有 base 和 button 的样式。

实际项目中的小技巧

1. 多个类名怎么处理?

// 使用模板字符串
<div className={`${styles.title} ${styles.highlighted}`}></div>

// 或者使用 classnames 库
import cn from 'classnames';
<div className={cn(styles.title, styles.highlighted)}></div>

2. 全局样式怎么办?

有时候确实需要全局样式,可以用 :global

:global(.global-style) {
  /* 这个样式不会被处理,保持原样 */
}

.title {
  /* 这个会被处理 */
}

3. 如何覆盖第三方组件样式?

.wrapper :global(.ant-btn) {
  /* 覆盖 Ant Design 按钮样式 */
}

总结

CSS Module 真是个好东西啊!它解决了长期困扰我们的样式冲突问题,让大型项目的样式维护变得轻松多了。

使用建议:

  • 新项目强烈推荐使用 CSS Module
  • 老项目可以逐步迁移,先从新组件开始
  • 结合 CSS 预处理器(Sass/Less)使用效果更佳

不要再被样式冲突折磨了,快去试试 CSS Module 吧!相信我用过一次之后,你就再也回不去了~