1. 自定义样式类命名规范手动隔离,比如可以直接使用 BEM 规范;
BEM是一种 css 命名方法论,样式类命名为块(Block)、元素(Element)、修饰符(Modifier)的简写。统一的样式类命名方法让 css 便于统一团队开发规范,方便维护。
样式类以 .block__element--modifier 的形式命名,即模块名 + 元素名 + 修饰名
如 .tab-container__item--active,代表 tab 页组件中激活的 tab 页。
2.vue中可以直接使用<style scoped> 隔离样式
注意:在带有 scoped 的时候,父组件的样式将不会泄露到子组件当中。不过,子组件的根节点会同时被父组件的作用域样式和子组件的作用域样式影响。这是有意为之的,这样父组件就可以设置子组件根节点的样式,以达到调整布局的目的。
本质上是利用的css属性选择器来实现样式隔离的,在编译阶段自动附加上组件id
<style>
.example[data-v-f3f3eg9] { color: red; }
</style>
<template>
<div class="example" data-v-f3f3eg9>hi</div>
</template>
3.使用css module(主要用于Vue(render函数中jsx/tsx)、React中)隔离样式
css module 不是官方标准,也不是浏览器的特性,而是在构建步骤(如使用 webpack)中对 css 类名和选择器限定作用域(类似于命名空间)的一种方式。现在 webpack 已经默认开启 css module 功能。
在webpack的项目中是css-loader提供的能力({ loader: 'css-loader', options: { modules: true/*开启css模块*/} })。在vite中已经适配了vue3单文件组件。
在CSS Module中可以使用:local(className)来声明一个局部作用域的CSS规则进行样式隔离, 使用:global(className)来声明一个全局作用域的规则,不会进行隔离。
:local(.qd_btn) { color: #fff;} //默认为 local,样式隔离
:global(.qd_text) { color: chocolate; } //global不会进行隔离
我们在开发过程一般不需要手动加:local()}。postcss-modules-local-by-default插件已经默认帮我们处理了这一步,只要我们开启了CSS模块化,里面的CSS在编译过程会默认加上:local()
css module样式隔离的原理是:css modules 在打包时会将生成的class哈希化,即给该module里面的class通过一定的配置规则生成一个不重复的名字,从而实现样式隔离。:global全局作用域的class不会进行哈希化。
.qd_btn { color: #fff; }
编译后: .input_css_UjDVoF__qd_btn { color: #fff; }
2-1.React中使用css Module 隔离样式
默认已配置webpack开启css Module({ loader: 'css-loader', options: { modules: true/*开启css模块*/} })
.title { color: blue; }
:global {/* 定义全局样式 */
.global-style { color: red;
}
}
import React from 'react';
import styles from './styles.css'; // 导入CSS模块样式
function MyComponent() {
return (
<div>
<h1 className={styles.title}>Hello, CSS Modules!</h1>
<p className={styles['global-style']}>This is a global style.</p>
</div>
);
}
2-2.vue中<style module> 隔离样式
(1).一个 <style module> 标签会被编译为 CSS Modules 并且将生成的 CSS class 作为 $style 对象暴露给组件。 然后在:class中通过$style.xxx使用class
<template>
<div>
<p :class="$style.red">我是内容</p>
</div>
</template>
<style lang="scss" module>
.red { color: red; }
</style>
(2).我们还可以给style module属性自定义一个名字。
<p :class="classes.red">我是内容</p>
// 给classes自定义一个classes的名字
<style lang="scss" module="classes">
.red { color: red; }
</style>
(3).对于render函数中的JSX/TSX组件,由于其没办法用 scoped style,所以一般会使用 CSS Modules 。
注入的类可以通过 useCssModule API 在vue3 setup() 中使用。
useCssModule() // 默认, 返回 <style module> 中的类
useCssModule('classes')// 命名, 返回 <style module="classes"> 中的类
<script lang="tsx">
import { defineComponent, useCssModule } from 'vue';
export default defineComponent({
setup(){
const classes = useCssModule('classes');
return () => ( <> <div class={ classes.text }>我是内容</div> </> );
}
})
</script>
<style lang="scss" module="classes">
.text { color: red; }
</style>
4.React中还可以使用css in js 隔离样式:
vue自带的css解决方案已经很好了,不需要再引入其它方案。而且就算选择jsx的写法,一般也是因为惯性选择css modules。
css in js主要还是在react中应用的比较多(由于国内用的不多,就不多介绍了,知道有这么个东西即可)。
常用的css in jS实现库是emotion、yarn add @emotion/react