Vue 3 中 CSS Modules 的使用

FreeGuideOnline 最新 2026-07-06

vue

欢迎使用 CSS Modules

这是一个局部作用域的段落。


渲染后的 HTML 类名会变成类似 `_container_abc123` 的形式,确保唯一性。

## 自定义注入名称

`module` 属性可以接收一个自定义名称,这样样式对象就会注入到对应的名称下,而不是 `$style`。

```vue
<template>
  <div :class="styles.container">
    <span :class="styles.highlight">高亮文本</span>
  </div>
</template>

<style module="styles">
.container { padding: 10px; }
.highlight { background-color: yellow; }
</style>

在组合式 API(<script setup>)中使用

<script setup> 语法中,无法直接使用 $style,需要通过 useCssModule() 函数获取样式对象。

<script setup>
import { useCssModule } from 'vue'

// 获取默认的 $style 对象
const $style = useCssModule()

// 如果使用了自定义名称
const styles = useCssModule('styles')
</script>

<template>
  <div :class="$style.card">
    <div :class="styles.footer">底部区域</div>
  </div>
</template>

<style module>
.card { border: 1px solid #eee; border-radius: 8px; }
</style>

<style module="styles">
.footer { padding: 12px; background: #f9f9f9; }
</style>

动态绑定与组合类名

利用 JavaScript 模板字符串或数组语法,可以轻松组合多个模块类名,或者根据条件动态切换。

<template>
  <button :class="[
    $style.button,
    isPrimary ? $style.primary : $style.secondary,
    disabled ? $style.disabled : ''
  ]">
    点我
  </button>
</template>

<script setup>
import { ref } from 'vue'
const isPrimary = ref(true)
const disabled = ref(false)
</script>

<style module>
.button {
  padding: 10px 20px;
  border: none;
  cursor: pointer;
}
.primary { background: #42b883; color: white; }
.secondary { background: #eee; color: #333; }
.disabled { opacity: 0.5; pointer-events: none; }
</style>

如何定义全局样式?

CSS Modules 默认将所有选择器局部化,但你可以使用 :global() 伪类来声明一个全局作用域的样式。

<style module>
.container {
  /* 局部类 */
  background: white;
}
.container :global(.global-class) {
  /* .global-class 不会被 hash 化,直接作用于全局 */
  font-weight: bold;
}
:global(body) {
  margin: 0;
}
</style>

从独立 CSS 文件导入 Modules

你可以将样式写在单独的 .module.css 文件(或 .module.scss 等预处理器文件)中,然后导入到组件使用。

styles/card.module.css:

.card {
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
  padding: 16px;
}
.header {
  font-size: 1.2rem;
  margin-bottom: 12px;
}

组件中导入:

<script setup>
import cardStyles from './styles/card.module.css'
</script>

<template>
  <div :class="cardStyles.card">
    <div :class="cardStyles.header">独立模块化样式</div>
  </div>
</template>

使用预处理器(SCSS/Less 等)

Vue 对 CSS Modules 与预处理器的结合做了完美支持,只需在 <style> 标签上同时指定 modulelang 属性即可。

<style module lang="scss">
$primary: #42b883;

.button {
  background: $primary;
  &:hover {
    background: darken($primary, 10%);
  }
  &.disabled {
    opacity: 0.5;
  }
}
</style>

组合(Composition)与 composes 特性

CSS Modules 规范允许通过 composes 关键词从一个类继承样式,Vue 编译器同样支持该特性。

<template>
  <div :class="$style.card">
    <div :class="$style.header">标题</div>
  </div>
</template>

<style module>
.baseCard {
  border-radius: 12px;
  overflow: hidden;
  background: white;
}
.card {
  composes: baseCard;
  box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}
.header {
  composes: baseCard from global; /* 假设 baseCard 定义在全局样式中 */
  padding: 12px;
}
</style>