【架构】如何避免 css 污染

如何避免 css 污染

相关文章

如何避免 css 污染


一、命名约定

使用一致的命名约定来避免命名冲突。可以采用 BEM(块、元素、修饰符)等命名规范,确保每个 CSS 类都有清晰的命名空间,减少命名冲突的可能性。

示例

1
2
3
4
5
6
7
8
9
10
<div class="header">
<div class="header__logo"></div>
<nav class="header__nav">
<ul class="header__nav-list">
<li class="header__nav-item"></li>
<li class="header__nav-item"></li>
<li class="header__nav-item"></li>
</ul>
</nav>
</div>

在这个示例中,.header 是块,.header__logo 和 .header__nav 是元素,.header__nav-list、.header__nav-item 是嵌套元素。这种命名约定使得 CSS 类名更具有语义化,便于开发者理解和维护。

二、使用命名空间

为每个模块添加一个命名空间或前缀,以区分不同模块的选择器。这样可以确保即使选择器相同,也不会发生冲突。例如,给每个模块添加一个唯一的前缀:

1
2
3
4
5
6
7
8
9
// _header.scss
.header {
background-color: #333;
color: #fff;
}

.header .logo {
font-size: 24px;
}
1
2
3
4
5
6
7
8
9
10
11
12
// _button.scss
.button {
padding: 10px 20px;
border: none;
background-color: #007bff;
color: #fff;
cursor: pointer;
}

.button:hover {
background-color: #0056b3;
}

三、CSS Modules

使用 CSS Modules 技术,将样式文件转换为具有局部作用域的模块,避免全局污染和命名冲突。在 CSS Modules 中,每个类名都会自动添加一个唯一的哈希值,以确保其在局部作用域内的唯一性。

JSX语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* button.module.css */

/* 定义按钮的基本样式 */
.button {
padding: 10px 20px;
border: none;
background-color: #007bff;
color: #fff;
cursor: pointer;
}

/* 定义按钮的悬停样式 */
.button:hover {
background-color: #0056b3;
}
1
2
3
4
5
6
7
8
9
10
11
12
// Button.js

import React from 'react';
import styles from './button.module.css'; // 导入 CSS Module

const Button = () => {
return (
<button className={styles.button}>Click me</button> {/* 使用 CSS Module 中定义的样式 */}
);
};

export default Button;

Template语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<template>
<button :class="$style.button" @click="handleClick">{{ text }}</button>
</template>

<script>
export default {
name: 'Button',
props: {
text: {
type: String,
default: 'Click me'
}
},
methods: {
handleClick() {
alert('Button clicked');
}
}
};
</script>

<!-- 使用 CSS Modules -->
<style module>
.button {
padding: 10px 20px;
border: none;
background-color: #007bff;
color: #fff;
cursor: pointer;
}

.button:hover {
background-color: #0056b3;
}
</style>

四、CSS-in-JS

使用 CSS-in-JS 的解决方案,确保每个组件的样式只在其作用域内有效,避免全局污染和命名冲突。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// Button.js

import React from 'react';

// 样式对象
const buttonStyle = {
padding: '10px 20px',
border: 'none',
backgroundColor: '#007bff',
color: '#fff',
cursor: 'pointer',
};

// Button 组件
const Button = ({ primary, children }) => {
// 根据 primary 属性决定是否应用 primary 样式
const style = primary ? { ...buttonStyle } : {};

return (
<button
style={style}
>
{children}
</button>
);
};

export default Button;

五、Shadow DOM

使用 Web Components 中的 Shadow DOM 技术,将组件的样式封装在 Shadow DOM 内部,确保样式只对组件内部有效,避免与外部样式发生冲突。

原生

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// custom-button.js

// 创建一个自定义按钮组件
class CustomButton extends HTMLElement {
constructor() {
super();
// 创建 Shadow DOM
this.attachShadow({ mode: 'open' });
// 在 Shadow DOM 中添加按钮元素和样式
this.shadowRoot.innerHTML = `
<style>
/* 按钮样式 */
button {
padding: 10px 20px;
border: none;
background-color: #007bff;
color: #fff;
cursor: pointer;
}
/* 按钮悬停样式 */
button:hover {
background-color: #0056b3;
}
</style>
<!-- 按钮元素 -->
<button><slot></slot></button>
`;
}
}

// 注册自定义按钮组件
customElements.define('custom-button', CustomButton);

react

定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// ShadowDOMComponent.js
import React, { useEffect, useRef } from 'react';
import ReactDOM from 'react-dom';

function ShadowDOMComponent({ children }) {
const containerRef = useRef(null);

useEffect(() => {
const shadowRoot = containerRef.current.attachShadow({ mode: 'open' });
// 渲染子组件到 Shadow DOM 中
ReactDOM.createPortal(children, shadowRoot);
}, [children]);

return <div ref={containerRef}></div>;
}

export default ShadowDOMComponent;

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// App.js
import React from 'react';
import ShadowDOMComponent from './ShadowDOMComponent';

function App() {
return (
<div>
<h1>React App</h1>
<ShadowDOMComponent>
<div>
<style>
{`
.container {
background-color: #eee;
}
.button {
color: blue;
}
`}
</style>
<div className="container">
<button className="button">Click me</button>
</div>
</div>
</ShadowDOMComponent>
</div>
);
}

export default App;

喜欢这篇文章?打赏一下支持一下作者吧!
【架构】如何避免 css 污染
https://www.cccccl.com/20231205/架构/如何避免 css 污染/
作者
Jeffrey
发布于
2023年12月5日
许可协议