实战指南:将CSS层叠层整合到现有项目中

本文详细介绍了如何将CSS层叠层技术整合到现有遗留代码库中的完整过程,包括层结构规划、代码重构技巧、媒体查询处理策略,以及在实际项目中遇到的挑战与解决方案。

将CSS层叠层整合到现有项目中

本文旨在分享将CSS层叠层整合到现有遗留代码库的完整、未经过滤的实践经验。实际上,这是关于重构现有CSS以使用层叠层而不会破坏任何功能的过程。

理解项目

在开始使用@layers之前,我们需要充分了解正在处理的内容。项目包含三个文件:index.html、index.css和index.js。

index.css文件超过450行代码,初步浏览就能发现一些明显问题:

  • 相同选择器指向相同HTML元素的代码重复严重
  • 使用了相当多的#id选择器
  • #botLogo被定义了两次,相隔70多行
  • !important关键字在整个代码中被随意使用

规划层结构

我决定将样式分成五个不同的层:

  1. reset:浏览器默认重置,如box-sizing、边距和内边距
  2. base:HTML元素的默认样式,包括默认排版和颜色
  3. layout:控制元素位置的主要页面结构
  4. components:可重用的UI片段,如按钮、卡片和菜单
  5. utilities:单一辅助修饰符

在文件顶部定义层顺序:

1
@layer reset, base, layout, components, utilities;

整合层叠层

重置层

通用选择器(*)样式包含经典的重置样式,非常适合放在@layer reset中:

1
2
3
4
5
6
7
@layer reset {
  * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }
}

基础层

body选择器包含项目的核心样式,如背景和字体:

1
2
3
4
5
6
7
@layer base {
  body {
    background-image: url("bg.svg");
    font-family: "Poppins", sans-serif;
    /* ... 其他样式 */
  }
}

将ID转换为类

我坚信尽可能使用类选择器而不是ID选择器。这默认保持较低的特异性,防止特异性冲突,并使代码更易维护。

我将HTML中id="loader"的元素重构为class="loader",同时修复了一些缺少闭合标签的div元素。

动画

关键帧动画有点棘手,但我最终选择将动画隔离在它们自己的新第五层中:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
@layer reset, base, layout, components, utilities, animations;

@layer animations {
  @keyframes loading {
    /* ... */
  }
  @keyframes loading2 {
    /* ... */
  }
  @keyframes pageShow {
    /* ... */
  }
}

布局

.page选择器主要控制内容的初始可见性,属于布局层:

1
2
3
4
5
@layer layout {
  .page {
    display: none;
  }
}

自定义滚动条

滚动条是跨站点的全局元素,适合放在@layer base中:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
@layer base {
  ::-webkit-scrollbar {
    width: 8px;
  }
  ::-webkit-scrollbar-track {
    background: #0e0e0f;
  }
  ::-webkit-scrollbar-thumb {
    background: #5865f2;
    border-radius: 100px;
  }
  ::-webkit-scrollbar-thumb:hover {
    background: #202225;
  }
}

导航

nav元素是定义导航栏位置和尺寸的主要结构容器,属于布局层:

1
2
3
4
5
6
7
8
9
@layer layout {
  nav {
    display: flex;
    height: 55px;
    width: 100%;
    padding: 0 50px;
    /* ... */
  }
}

组件层

各种可重用组件,如加载器、菜单、按钮等,都放在组件层:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
@layer components {
  .loader {
    width: 100%;
    height: 100vh;
    /* ... */
  }
  
  .mainMenu {
    display: flex;
    flex-wrap: wrap;
    list-style: none;
  }
  
  .btn {
    color: #fff;
    background-color: #1d1e21;
    font-size: 18px;
    /* ... */
  }
}

媒体查询

媒体查询应该与它们影响的元素放在同一层中,这样可以:

  • 将响应式样式与其基本元素样式保持在一起
  • 使覆盖可预测
  • 与现代Web开发中常见的基于组件的架构很好地配合
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
@layer components {
  .mainMenu {
    display: flex;
    flex-wrap: wrap;
    list-style: none;
  }
  
  @media (max-width: 900px) {
    .mainMenu {
      width: 100%;
      text-align: center;
      height: 100vh;
      display: none;
    }
  }
}

工具层

工具层保留用于具有特定目的的辅助类:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@layer utilities {
  .noselect {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -webkit-user-drag: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
  }
}

挑战与经验

遇到的困难

  1. 确定起点困难:对于现有项目,很难确定从哪里开始
  2. 浏览器支持:层叠层目前有94%的支持率,但可能需要支持不支持分层样式的旧版浏览器
  3. 媒体查询定位:媒体查询在过程中的位置不明确
  4. !important关键字:它们颠倒了整个分层优先级系统

层叠层的价值

建立层确实改善了代码,真正的胜利在于更可维护的样式集:

  • 更容易找到所需内容
  • 知道特定样式规则的作用
  • 知道在哪里插入新样式

然而,层叠层并不是银弹解决方案。如果HTML结构混乱,那么解构这种混乱的工作量会更高,并且需要同时重写标记。

结论

重构CSS以使用层叠层绝对值得,仅维护增强就足够了。从零开始定义层可能"更容易",因为需要整理的继承开销和技术债务更少。但如果必须从现有代码库开始,可能需要先解构样式的复杂性,以确定需要多少重构工作。

层叠层展示了使用语言提供的工具(而不是使用变通方法或绕开问题的方法)是有回报的。至少,从重置层开始总是很容易的。这些样式总是会被覆盖,因此将它们放在一个层中使一切变得更容易,并且能够编写更复杂的重置,而无需到处使用:where()

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计