非常全的css预编译~

本文深入探讨了CSS预处理器Less、Sass和Stylus的主要特性,包括基本语法、嵌套、变量、混入、继承等功能的比较。预处理器解决了CSS在模块化和样式复用上的痛点,提供了更强大的样式层复用机制。文章详细阐述了三者之间的差异,如Less的懒加载、Sass的@mixin和@import、Stylus的透明mixin等,帮助开发者选择合适的预处理器。
摘要由CSDN通过智能技术生成

CSS 预处理器是什么?一般来说,它们基于 CSS 扩展了一套属于自己的 DSL,来解决我们书写 CSS 时难以解决的问题:

  • 语法不够强大,比如无法嵌套书写导致模块化开发中需要书写很多重复的选择器;
  • 没有变量和合理的样式复用机制,使得逻辑上相关的属性值必须以字面量的形式重复输出,导致难以维护。

所以这就决定了 CSS 预处理器的主要目标:提供 CSS 缺失的样式层复用机制、减少冗余代码,提高样式代码的可维护性。这不是锦上添花,而恰恰是雪中送炭。

网上已经有不少对比目前最主流的三个预处理器 Less、Sass 和 Stylus(按字母顺序排名)的文章了,但是似乎都不是很详细,或者内容有些过时。下面我会更详细地探讨一下这三种预处理器的特性和它们的差异。

下面主要会分为如下几方面来讨论:

  • 基本语法
  • 嵌套语法
  • 变量
  • @import
  • 混入
  • 继承
  • 函数
  • 逻辑控制

事先声明一下,平时我在开发中主要使用的是 Less,所以可能对 Sass 和 Stylus 的熟悉程度稍差一些,比较时主要参考三者官网的语言特性说明,有一些正在开发的功能可能会遗漏。

本文中对 CSS 语法的话术与 MDN 的 CSS 语法介绍一致。

基本语法

Less 的基本语法属于「CSS 风格」,而 Sass、Stylus 相比之下激进一些,利用缩进、空格和换行来减少需要输入的字符。不过区别在于 Sass、Stylus 同时也兼容「CSS 风格」代码。多一种选择在更灵活的同时,在团队开发中也免不了增加更多约定来保持风格统一。而对个人而言,语法风格按自己口味选择即可。

注:后面的 Sass 代码会用被更多人接受的 SCSS 风格给出。

Less & SCSS:

.box {
  display: block;
}

 

Sass:

.box
  display: block

 

Stylus:

.box
  display: block

 

嵌套语法

三者的嵌套语法都是一致的,甚至连引用父级选择器的标记 & 也相同。区别只是 Sass 和 Stylus 可以用没有大括号的方式书写。以 Less 为例:

.a {
  &.b {
    color: red;
  }
}

生成的 CSS 为:

.a.b {
  color: red;
}

 

除了规则集的嵌套,Sass 额外提供了一个我个人认为比较另(jī)类(lèi)的「属性嵌套」:

.funky {
  font: {
    family: fantasy;
    size: 30em;
    weight: bold;
  }
}

 

选择器引用

三者都支持用 & 在嵌套的规则集中引用上层的选择器,这可以是嵌套书写 CSS 时的「惯例」了。语法相同,但是逻辑上有些许差异。在一个选择器中用两次以上 & 且父选择器是一个列表时,Less 会对选择器进行排列组合,而 Sass 和 Stylus 不会这么做。

也就是说,假设上层选择器为 .a, .b,则内部的 & & 在 Less 中会成为 .a .a, .a .b, .b .a, .b .b,而 Sass 和 Stylus 则输出 .a .a, .b .b

假设我们要用预处理器书写 WHATWG 推荐的 section 标题样式,在 Less 中可以方便地书写为:

article, aside, nav, section {
  h1 {
    margin-top: 0.83em; margin-bottom: 0.83em; font-size: 1.50em;
  }
  & & h1 {
    margin-top: 1.00em; margin-bottom: 1.00em; font-size: 1.17em;
  }
  & & & h1 {
    margin-top: 1.33em; margin-bottom: 1.33em; font-size: 1.00em;
  }
  & & & & h1 {
    margin-top: 1.67em; margin-bottom: 1.67em; font-size: 0.83em;
  }
  & & & & & h1 {
    margin-top: 2.33em; margin-bottom: 2.33em; font-size: 0.67em;
  }
}

当然,这个推荐样式十分脑残,编译出来的结果会有 47KB 之巨,根本不可用,这里只是借来演示一下。

除了 &,Sass 和 Stylus 更进一步,分别用 @at-root 和 / 符号作为嵌套时「根」规则集的选择器引用。这有什么用呢?举个例子,假设 HTML 结构是这样的:

<article class="post">
  <h1>我是一篇文章</h1>
  <section>
    <h1 class="section-title"><a href="#s1" class="section-link">#</a>我是章节标题</h1>
    <p>我只是一个<em>例子</em>。</p>
  </section>
</article>

如果我这么写 Sass 代码,是完全符合业务的嵌套关系的:

.post {
  section {
    .section-title {
      color: #333;
      .section-link {
        color: #999;
      }
    }
    /* other section styles */
  }
  /* other post styles */
}

 

但是这样生成出来的选择器会有 .post section .section-title .section-link,很多时候我们觉得写成 .post .section-link 就够了。

于是我们在 Stylus 中可以这么写:

.post
  section
    .section-title
      color #333
      /.post .section-link
        color #999
    /* other section styles */

  /* other post styles */

 

这样输出的 CSS 就会是:

.post section .section-title {
  color: #333;
}
.post .section-link {
  color: #999;
}

 

这就是我们想要的样子了。当然也可以这样写:

.post
  section
    .section-title
      color #333
    /* other section styles */

  .section-link
    color #999
  /* other post styles */

我个人是推荐这种写法(不使用 root 引用)的,因为当你确定 .section-link 的样式不依赖于它位于 section 或 .section-title 下时,就不应该嵌套于此。否则如果为了一点点性能上的考虑(还不一定会是优化),使得设计意图变得更不准确,我觉得得不偿失。

变量

变量无疑为 CSS 增加了一种有效的复用方式,减少了原来在 CSS 中无法避免的重复「硬编码」。

Less:

@red: #c00;

strong {
  color: @red;
}

Sass:

$red: #c00;

strong {
  color: $red;
}

Stylus:

red = #c00

strong
  color: red

Less 的选择有一个问题:@ 规则在 CSS 中可以算是一种「原生」的扩展方式,变量名用 @ 开头很可能会和以后的新 @ 规则冲突。(当然理论上只要 CSS 规范不引入 @a: b 这样的规则,问题也不大。而且规范制定的时候也会参考很多现有的实现。)

相比之下 Sass 的选择中规中矩,而 Stylus 就不同了,不需要额外的标志符。这意味着:在 Stylus 中,我们可以覆写 CSS 原生的属性值!Stylus 的设计让人有一种「你以为你在写 CSS,但其实你不是」的感觉,后面会有更多这样的例子。

顺便说一下,CSS 规范也有关于变量实现的草案,目前的方案是这个样子的:

/* global scope */
:root {
  --red: #c00;
}

strong {
  color: var(--red);
}

不管语法槽点如何,原生 CSS 变量可以通过 DOM 结构来继承,也就是说是代码真正「运行」时(runtime)决定的。元素引用一个变量时会按 DOM 向上查找定义在上层元素上的同名变量。这一点是任何预处理语言都无法做到的。可以用 Firefox 31+ 看一下这个 demo。至于这种机制是不是好用,暂时还没研究过。不过从开发的思维惯性来看,还很难一下子适应这种方式。

变量作用域

三种预处理器的变量作用域都是按嵌套的规则集划分,并且在当前规则集下找不到对应变量时会逐级向上查找,注意这个和原生 CSS 的逻辑是完全不同的。

如果我们在代码中重写某个已经定义的变量的值,Less 的处理逻辑和其他两者有非常关键的区别。在 Less 中,这个行为被称为「

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值