全局样式污染
全局样式污染(Cascading Style Sheets Contamination)通常指的是一个CSS文件或样式规则意外地影响了其他组件或页面的样式。
可能是由以下原因造成:
- 选择器优先级不足,导致规则被其他更具体或更靠后的样式覆盖
- 使用了全局选择器
*
,使得所有元素都受到影响 - 样式文件被错误地引入到了多个页面或组件中,导致重复应用
- 样式文件中的规则被意外复制或合并到其他文件中
可行的解决方法:
- 检查并提高样式规则的特异性,使用更具体的选择器,如类选择器或ID选择器
- 避免使用全局选择器
*
,除非绝对必要 - 确保样式文件只被引入到需要它的组件或页面中,避免全局污染
- 对样式文件进行组织和管理,避免不必要的复制或合并
在实际操作中,可以使用以下方法来减少或避免全局样式污染:
- 使用
CSS模块化
,每个模块或组件拥有自己的样式文件,并通过特定的类名或ID将样式局部作用于元素上 - 使用
CSS-in-JS库
(如styled-components),它们允许你用JavaScript编写样式,从而避免全局样式污染 - 使用
CSS预处理器
(如Sass、Less)的嵌套规则,减少不必要的全局选择器 - 使用CSS框架时,遵循其
命名空间和作用域
的最佳实践,避免全局样式污染 - 进行代码审查,确保没有重复的样式文件被引入到不同的页面或组件中
CSS模块化
CSS模块化是一种组织和管理CSS代码的方法,可以减少样式冲突,提高代码复用性,并增加样式的可维护性。
- BEM (Block Element Modifier) 命名规范
BEM是块、元素、修饰符(Block, Element, Modifier)的缩写。它是一种命名约定,有助于开发人员编写可重复使用、易于维护和扩展的CSS代码。
css
.button {
display: inline-block;
padding: 10px 20px;
border: 1px solid #000;
text-align: center;
}
.button__text {
font-size: 16px;
}
.button--large {
padding: 15px 30px;
}
- Atomic CSS模块化
将每个样式都视为原子,尽量避免组合样式。
css
.mr10 {
margin-right: 10px;
}
.p20 {
padding: 20px;
}
.bg-blue {
background-color: blue;
}
.container {
@extend .mr10;
@extend .p20;
@extend .bg-blue;
}
CSS-in-JS
将CSS和JavaScript混合在一起的方法,它允许你以JavaScript的方式编写样式。
下载安装插件npm install styled-components
css
import styled from "styled-components";
const StyledButton = styled.a`
padding: 20px 40px;
background-color: ${ ({ primary }) => ( primary ? "#07c" : "#333" ) };
color: white;
&:hover {
background-color: #111;
}
`;
export default StyledButton;
创建的标签样式可以在任何组件中使用
javascript
import StyledButton from './components/styles/Button.styled';
function App() {
return (
<div className="App">
<StyledButton href="...">Default Button</StyledButton>
<StyledButton primary href="...">Primary Button</StyledButton>
</div>
);
}
export default App;
CSS预处理
像Sass/LESS这样的第三方插件,都提供了变量、混合(mixins)、嵌套规则等高级功能,可以帮助写出更模块化的CSS代码。
css
$base-font-size: 16px;
// Mixin
@mixin center-block {
display: block;
margin-left: auto;
margin-right: auto;
}
// Usage
.button {
font-size: $base-font-size;
@include center-block;
}
CSS @layer
项目开发中,经常出现第三方库代码和本地代码冲突,最常用的解决办法是增加本地代码的权重,如下所示:
sql
.container .some-button {} 改为 body .container .some-button {}
这样的代码虽然可以解决问题,但是又长又臭,而CSS @layer的出现就是为了解决这个问题。
使用@layer将样式优先级降低
xml
<style>
@layer {
#app .item {
color: black;
width: 100px;
padding: 1em;
}
}
.item {
color: red;
}
</style>
<div id="app">
<div class="item">测试文案</div>
</div>
@import中使用
less
@import './zxx.lib.css' layer(lib);
zxx.lib.css 里面所有 CSS 声明的优先级都会低于常规设置的 CSS 声明。
元素引用(*)
xml
<!-- zxx-lib.css的样式属于名为 lib 的级联层 -->
<link rel="stylesheet" href="zxx-lib.css" layer="lib">
<!-- 样式引入到一个匿名级联层中 -->
<link rel="stylesheet" href="zxx-lib.css" layer>
CSS作用域划分(兼容性差)
CSS处理库提供的:global
和:local
分别表示全局作用域和局部作用域,
:global
:选择器用于指定某个样式规则应用于全局范围内的元素,而不受当前样式封装作用域的影响:local
:标记本地作用域内的样式
css
:global(.map){
color:#333;
}
.map{
padding-top: 45px;
height: 100%;
}
:local(.map) {
color: red;
}
Vue框架避免样式污染
scoped
作用:当前样式只作用于当前组件,不会造成全局样式污染
xml
<style lang="scss" scoped>
.key {
width: 250px;
height: 30px;
}
</style>
::v-deep
作用:修改第三方库样式,实现样式穿透
css
::v-deep .confirm .el-button {
width: 50px;
height: 30px;
padding: 2px 2px 2px 2px;
border-radius: 3px;
}
React框架避免样式污染
- css modules
- styled-components
- CSS预处理器