全局样式污染
全局样式污染(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代码。
.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模块化
将每个样式都视为原子,尽量避免组合样式。
.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
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;
创建的标签样式可以在任何组件中使用
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代码。
$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
项目开发中,经常出现第三方库代码和本地代码冲突,最常用的解决办法是增加本地代码的权重,如下所示:
.container .some-button {} 改为 body .container .some-button {}
这样的代码虽然可以解决问题,但是又长又臭,而CSS @layer的出现就是为了解决这个问题。
使用@layer将样式优先级降低
<style>
@layer {
#app .item {
color: black;
width: 100px;
padding: 1em;
}
}
.item {
color: red;
}
</style>
<div id="app">
<div class="item">测试文案</div>
</div>
@import中使用
@import './zxx.lib.css' layer(lib);
zxx.lib.css 里面所有 CSS 声明的优先级都会低于常规设置的 CSS 声明。
元素引用(*)
<!-- 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:标记本地作用域内的样式
:global(.map){
color:#333;
}
.map{
padding-top: 45px;
height: 100%;
}
:local(.map) {
color: red;
}
Vue框架避免样式污染
scoped
作用:当前样式只作用于当前组件,不会造成全局样式污染
<style lang="scss" scoped>
.key {
width: 250px;
height: 30px;
}
</style>
::v-deep
作用:修改第三方库样式,实现样式穿透
::v-deep .confirm .el-button {
width: 50px;
height: 30px;
padding: 2px 2px 2px 2px;
border-radius: 3px;
}
React框架避免样式污染
- css modules
- styled-components
- CSS预处理器
Sass
变量
使用$声明一个变量,变量也存在作用域,可以通过标识符改变变量的作用域。
!global:将局部变量改为全局变量!default:设置变量的默认值,如果在声明变量时赋值了则使用声明的值,否则就使用默认值
变量的数据格式包括以下几种:
- 数字:10px
- 字符串:“foo”, ‘bar’, baz
- 颜色:blue, #04a3f9, rgba(255,0,0,0.5)
- 布尔型:true, false
- 空值:null
- 数组:list,用空格或逗号作分隔符,1.5em 1em 0 2em, Helvetica
- maps:相当于 JavaScript 的 object,(key1: value1, key2: value2)
$main-color: red; // 全局变量
h1 {
$main-color: green; // 局部变量
color:$main-color; // green
}
h2 {
color:$main-color; // red
}
嵌套
- 标签嵌套
div{
height: 100px;
ul{
height: 80px;
li{
height: 50px;
}
}
}
- 选择器嵌套
#app{
color:while;
.content{
color:red;
}
}
- 父级选择器 &
#app{
color:while;
& .content{
color:red;
}
}
运算
- 数学运算
$number: 12px;
p{
width: $number * 2;
}
- 颜色值运算
.color1{
color: #010120 + #234234;
}
- 字符串运算
.string1:before{
font-family: icon + font;
content: "带引号字符串" + 不带引号字符串;
}
- 布尔值运算
.bool1:before{
content: $bool and false;
}
@import导入
@import "test2.scss";
@media特定尺寸样式
@media screen and (orientation: landscape) {
width: 500px;
}
@extend继承
.item{
width:100%;
background:#ffffff;
line-height:40px;
}
.light_item{
//继承上面.item的样式
@extend .item ;//父级并行使用.item的样式
// 特殊样式(其他样式)
background:#f0f0f0;
}
@extend支持多重继承和延续继承
@if
当 @if 的表达式返回值不是 false 或者 null 时,条件成立,输出 {} 内的代码
p {
@if 1 + 1 == 2 { border: 1px solid; }
@if 5 < 3 { border: 2px dotted; }
@if null { border: 3px double; }
}
mixin 混合指令
混合指令(Mixin)用于定义可重复使用的样式,避免了嵌套class。混合指令可以包含所有的 CSS 规则,绝大部分 Sass 规则,甚至通过参数功能引入变量,输出多样化的样式。
- 无参混入
@mixin big_text{
font:{
size:22px;
weight:bold;
}
color:#555;
}
div{
@include big_text;
}
- 带参混入
@mixin big_text2($size,$weight){
font:{
size:$size;
weight:$weight;
}
color:#555;
}
.p_big_text2{
@include big_text2(24px,bold)
}
- 参数默认值
@mixin big_text3($size:20px,$weight:400){
font:{
size:$size;
weight:$weight;
}
color:#555;
}
.p_big_text3{
@include big_text3
}