image.png

随着前端技术的飞速发展,CSS预处理器已经成为许多项目中不可或缺的一部分。然而,随着原生CSS的不断进化,一个值得思考的问题浮出水面:在2024年,我们是否还需要CSS预处理器?

CSS预处理器的兴起与发展

CSS预处理器诞生于原生CSS能力不足的年代。Sass作为最早的CSS预处理器,诞生于2007年,至今已有17个年头。而相对较新的Stylus也已发布14年之久。这些工具为开发者带来了更灵活、更高效的样式编写体验,极大地提升了CSS的可维护性和可扩展性。

主流的CSS预处理器包括:

  1. Sass: 最成熟的预处理器,拥有强大的Ruby社区支持。
  2. Less: 语法接近CSS,学习曲线平缓,广受欢迎。
  3. Stylus: 来自Node.js社区,为Node项目提供CSS预处理支持。

这些预处理器的主要优势在于:

  • 变量支持
  • 混合(Mixin)功能
  • 嵌套规则
  • 模块化

例如,使用Sass可以这样定义变量和混合:

变量:

$font-size: 10px;
$font-family: Helvetica, sans-serif;

body {
  font: $font-size $font-family;
}

.mark{
  font-size: 1.5 * $font-size;
}

Mixin

@mixin clearfix {
  &:after {
    display: block;
    content: '';
    clear: both;
  }
}

.sidebar{
  @include clearfix;
}

嵌套:

// menu
.nav {
  > li {
    > a:hover {
      background-color: red;
    }
  }
}

模块

@import './common';
@import './github-markdown';
@import './mixin';
@import './variables';

CSS预处理器的局限性

尽管CSS预处理器带来了诸多便利,但它们也存在一些问题:

1.需要额外的编译配置

在编写样式之前,还需要进行额外的编译配置工作。sass-node 的安装和编译配置可能会给前端初学者带来困难。

image.png

2.编译过程消耗时间和资源

每次修改代码都需要重新编译,这将耗费时间和 CPU。

image.png

3.不同预处理器间的语法差异增加了学习成本

不同的 CSS 预处理器语法有不同的学习成本,这会增加总体学习成本。在同一个团队甚至项目中,可能会同时使用多种样式预处理器。

// Sass
$color: #f00;
$images: "../img";
@mixin clearfix {
  &:after {
    content: " ";
    display: block;
    clear: both;
  }
}
body {
  color: $color;
  background: url("#{img}/1.png");
  @include clearfix;
}
// Less
@color: #f00;
@images: "../img";
.clearfix() {
  &:after {
    content: " ";
    display: block;
    clear: both;
  }
}
body {
  color: @color;
  background: url("@{img}/1.png");
  .clearfix;
}

4.调试困难,尤其是在复杂项目中

在使用 CSS 预处理器时,我们通常会配置 SourceMaps 来协助调试。不过,即便如此,还是会出现一些难以调试的情况:

原生CSS的进化

与此同时,W3C的CSS工作组也在不断吸收社区的创新,加速CSS标准的迭代。CSS3的模块化设计使得各个特性可以独立演进,大大提高了标准化进程的效率。

其中,CSS变量(Custom Properties)的引入是一个重要里程碑。它允许我们在样式表中声明变量,并通过var()函数使用它们:

/* declaration */
--VAR_NAME: <declaration-value>;
/* usage */
var(--VAR_NAME)

/* root element selector (global scope), e.g. <html> */
:root {
  /* CSS variables declarations */
  --main-color: #ff00ff;
  --main-bg: rgb(200, 255, 255);
  --logo-border-color: rebeccapurple;

  --header-height: 68px;
  --content-padding: 10px 20px;

  --base-line-height: 1.428571429;
  --transition-duration: .35s;
  --external-link: "external link";
  --margin-top: calc(2vh + 20px);
}

body {
  /* use the variable */
  color: var(--main-color);
}

CSS变量不仅可以在样式表中使用,还可以通过JavaScript动态修改,这为主题切换等功能提供了便利:

document.documentElement.style.setProperty('--primary-color', '#e74c3c');

此外,calc()函数的引入使得CSS中的数值计算变得可能:

.container {
  width: calc(100% - 20px);
}

使用 CSS 变量,还可以自定义和动态切换网站主题非常简单方便:

html {
  --hue: 210; /* Blue */
  --text-color-normal: hsl(var(--hue), 77%, 17%);
  ...
}
html[data-theme='dark'] {
  --text-color-normal: hsl(var(--hue), 10%, 62%);
  ...
}

通过 JS 更改元素属性,动态切换主题

document.documentElement.setAttribute('data-theme', 'dark')
document.documentElement.setAttribute('data-theme', 'light')

CSS 中的Mixin

CSS 有一个提案:CSS @apply 规则。根据该草案,用户可以直接使用 CSS 变量来存储声明块,然后通过 @apply 规则来使用它们。

:root {
    --pink-schema: {
        color: #6A8759;
        background-color: #F64778;
    }
}

body{
  @apply --pink-schema;
}

遗憾的是,这一提议已被放弃。虽然目前 CSS 中还没有很好的标准实现,但我们坚信,最终会有更好的规范出现,填补 CSS 中的这一空白。

原生CSS的未来

虽然原生CSS目前还无法完全替代预处理器,但它正在快速追赶。例如,CSS Nesting Module的提案已经进入了候选推荐阶段,这将带来类似预处理器的嵌套语法:

.card {
  background: white;
  & .title {
    color: black;
  }
}

同时,@container查询、:has()选择器等新特性的出现,大大增强了CSS的表达能力和灵活性。

结语

在2024年,完全抛弃CSS预处理器可能为时尚早。但可以预见的是,随着原生CSS的不断进化,预处理器的重要性将逐渐降低。明智的做法是在项目中逐步引入原生CSS新特性,同时保留预处理器的使用,以获得最佳的开发体验和浏览器兼容性。

未来,我们可能会看到更多像PostCSS这样的工具,它们能够根据项目需求灵活地填补原生CSS与预处理器之间的差距。无论如何,持续关注CSS标准的发展,并在实践中积极尝试新特性,将是每个前端开发者的必修课。

首发于公众号 大迁世界,欢迎关注。📝 每周一篇实用的前端文章 🛠️ 分享值得关注的开发工具 ❓ 有疑问?我来回答

本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试完整考点、资料以及我的系列文章。


王大冶
68k 声望104.9k 粉丝