likes
comments
collection
share

和样式污染说不

作者站长头像
站长
· 阅读数 2

全局样式污染

全局样式污染(Cascading Style Sheets Contamination)通常指的是一个CSS文件或样式规则意外地影响了其他组件或页面的样式。

可能是由以下原因造成:

  1. 选择器优先级不足,导致规则被其他更具体或更靠后的样式覆盖
  2. 使用了全局选择器*,使得所有元素都受到影响
  3. 样式文件被错误地引入到了多个页面或组件中,导致重复应用
  4. 样式文件中的规则被意外复制或合并到其他文件中

可行的解决方法:

  1. 检查并提高样式规则的特异性,使用更具体的选择器,如类选择器或ID选择器
  2. 避免使用全局选择器*,除非绝对必要
  3. 确保样式文件只被引入到需要它的组件或页面中,避免全局污染
  4. 对样式文件进行组织和管理,避免不必要的复制或合并

在实际操作中,可以使用以下方法来减少或避免全局样式污染:

  • 使用CSS模块化,每个模块或组件拥有自己的样式文件,并通过特定的类名或ID将样式局部作用于元素上
  • 使用CSS-in-JS库(如styled-components),它们允许你用JavaScript编写样式,从而避免全局样式污染
  • 使用CSS预处理器(如Sass、Less)的嵌套规则,减少不必要的全局选择器
  • 使用CSS框架时,遵循其命名空间和作用域的最佳实践,避免全局样式污染
  • 进行代码审查,确保没有重复的样式文件被引入到不同的页面或组件中

CSS模块化

CSS模块化是一种组织和管理CSS代码的方法,可以减少样式冲突,提高代码复用性,并增加样式的可维护性。

  1. 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;
}
  1. 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框架避免样式污染

  1. scoped

作用:当前样式只作用于当前组件,不会造成全局样式污染

<style lang="scss" scoped>
  .key {
    width: 250px;
    height: 30px;
  }
</style>
  1. ::v-deep

作用:修改第三方库样式,实现样式穿透

::v-deep .confirm .el-button {
  width: 50px;
  height: 30px;
  padding: 2px 2px 2px 2px;
  border-radius: 3px;
}

React框架避免样式污染

  1. css modules
  2. styled-components
  3. CSS预处理器