Vue开发中经常会用到第三方UI组件库,如Element Plus,它提供了一套完整的Vue组件,适用于快速开发。然而,在使用过程中,我们可能会遇到需要覆盖默认样式的情况,那我们如何覆盖样式比较好呢?

问题举例

例子A

<style lang="scss">
  .el-input {
    /* ... */
  }
</style>

例子B

<style scoped lang="scss">
  :deep(.el-input) {
    /* ... */
  }
</style>

最佳实践?

※通过自定义父节点类名限制

scoped 中使用 :deep(),且保证在.el-input等组件库原生类名之前使用自定义父节点的类名加以限制。

这样可以将样式作用于当前指定的范围内,降低样式污染的可能性。

:deep(.custom-parent-node .el-input__wrapper){
  /* ... */
}

增加CSS权重

通过使用更具体的选择器或多个类,可以增加样式的优先级。

尽量不要使用!important去提高权重。

.el-dialog.my-custom-dialog {
  /* 覆盖样式 */
}

另一种思路——使用自定义命名空间

文档:Element Plus自定义命名空间

Element Plus 提供的默认命名空间为 el。 在特殊情况下,我们需要自定义命名空间。

设置 ElConfigProvider

使用 ElConfigProvider 包装根组件。

<!-- App.vue -->
<template>
  <el-config-provider namespace="ep">
    <!-- ... -->
  </el-config-provider>
</template>

设置 SCSS 和 CSS 变量

创建 styles/element/index.scss

// styles/element/index.scss
// we can add this to custom namespace, default is 'el'
@forward 'element-plus/theme-chalk/src/mixins/config.scss' with (
  $namespace: 'ep'
);
// ...

vite.config.ts 中导入 styles/element/index.scss

import { defineConfig } from 'vite'
// https://vitejs.dev/config/
export default defineConfig({
  // ...
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `@use "~/styles/element/index.scss" as *;`,
      },
    },
  },
  // ...
})

然后就可以在<el-config-provider></el-config-provider>内部使用自定义命名空间来使用组件了,比如:

<el-config-provider>
    <ep-input />
</el-config-provider>

然后通过.ep-input等类名来覆盖组件样式,并且不会被项目中原有的.el-input等全局样式所污染。


A Student on the way to full stack of Web3.