Sass多年来一直是我的首选。最近我有一段时间,想尝试使用PostCSS的cssnext插件来处理CSS样式。我一直想使用工具尝试写一些CSS的新特性。同时自己的个人网站也是一个最佳测试这些新特性的实验地。
第一步先了解我使用Sass写的东西,需要知道我用了些什么功能,以确保找到一个替代的工具(PostCSS插件)。下面这个列表是我项目中用到的一些功能:
在了解CSS新特性语法和其他有趣的东西之前,需要做一些必要的准备工具。Sass项目的文件结构是有几个典型用法。使用下划线( _
)来命名文件名,这些文件都是以 .scss
作为文件扩展名。其中两个文件夹 modules
和 partials
放置对应的Sass文件,在 modules
文件夹中的不会产生对应的CSS,其中放置是有关于变量、占位符和混合宏之类的文件,在 partials
放置会编译出CSS(CSS-producing)的Sass文件。
开始的文件结构如下:
css/ |--scss/ |----modules/ |------_module.scss |------... |----partials/ |------_partial.scss |------... |----tylergaw.scss
通过 @import
把带有下划线(partial)Sass文件引入到 tylergaw.scss
中:
@import "modules/setup"; @import "modules/reset"; @import "modules/fonts";
重新命名文件。首先把 .scss
的文件换成 .css
。我不想一个一个文件修改,使用一个Bash脚本来帮我一次性修改好:
for f in *.scss; do git mv -- "$f" "${f%.scss}.css"; done;
因为Sass文件前面有下划线( _
),这些都是Sass环境下的,所以我也删除了。我没办法使用Bash命令一次性完成,所以只能手动每个去修改。
最后一步是将 modules
和 partials
目录下的CSS文件移出来。我决定把所有CSS作为模块来管理。
开始使用 PostCSS CLI 。先添加一个临时的 package.json
构建脚本文件:
"scripts": { "postcss": "postcss -o public/css/tylergaw.css src/css/tylergaw.css" }
在不改变任何东西情况下可以编译CSS样式:
npm run postcss
它能正常工作。在控制台上也没有任何的错误提示,但是页面 没有任何的样式 。
接下来要做的事情,就是让页面的样式回来。
通过Chrome浏览器,查看控制台可以看到一大堆的404信息。丢失了第一个特性,那就是内联的 @import
特性。通过 @import
把每个CSS模块引入到 tylergaw.css
文件中。浏览器中看到这些,它知道要做什么。它试图加载每个模块,而且每个模块都会产生一个HTTP请求。我们的构建脚本中只有一个CSS文件,而不是每个模块。因此,浏览器找不到他们(自然而然,就有一大堆的404信息出现)。
我能改变构建脚本,让其默认支持 @import
,但这样的工作方式是低效的。言外之意,需要一个能替代Sass的 @import
的工具来帮助我们。
可以使用 postcss-import
插件来替代Sass样式中的 @import
功能。通过 npm
安装好这个插件之后,就可以更新我们的构建脚本:
"scripts": { "postcss": "postcss -u postcss-import -o public/css/tylergaw.css src/css/tylergaw.css" }
在命令终端再次运行 npm run postcss
。单独的CSS文件中包含所有模块和该网站现在部分样式。
Sass中的 @import
引入样式方式是巨大的,它也改变了我们能够更好的组织样式。我不确定这个功能在本地项目中能生效。也就是说,我们总是需要为这种类型的功能在构建脚本上处理这方面的特性。这样看起来并不坏。
我想 postcss-import
插件将是PostCSS一个主要的设置。而且其它人也应该会这样做。对于这个插件,作者是这样描述的:
This plugin should probably be used as the first plugin of your list. This way, other plugins will work on the AST as if there were only a single file to process, and will probably work as you can expect. —— postcss-import
cssnext 是PostCSS一个插件,把CSS未来特性编译成现在CSS语法特性。特别需要注意的是,这个插件和Sass和LESS都不一样。它提供的特性是CSS正在进行的规范(或者未来CSS将会具备的语法特性)。而且有一些特性已经得到了浏览器的支持。
我使用cssnext来处理Sass不具备的一些特性。
我在创建这个网站之前我就知道 Autoprefixer 。我使用了 自定义的Sass混合宏 来处理浏览器所需的私有前缀。cssnext包括了Autoprefixer插件,所以我可以删除整个混合宏模块。
接下来我需要使用CSS自定义属性(CSS原生变量)来替代Sass中的变量。比如在 _setup.scss
中设置的变量:
$grey: #1e1e1d; $yellow: #ffad15; $offwhite: #f8f8f8; $darkerwhite: darken($offwhite, 15);
这不是所有Sass的变量,但它是最主要的。其余的都是在单独的模块里。
注意:自定义属性和变量的区别。CSS自定义属性仅适用于属性值,他们不能被用于选择器,属性名称或媒体查询。
更新 setup.css
:
:root { --white: #fff; --grey: #1e1e1d; --yellow: #ffad15; --offwhite: #f8f8f8; ... }
使用的示例如下:
a { color: var(--yellow); }
除了语法,CSS自定认属性和Sass变量工作是一样的。因为目前支持的浏览器还有限,所以属性仍然是需要编译的。在上面的示例中,编译后的值是 color:#ffad15;
。
在前面的示例中,我遗漏了一个变量: $darkerwhite: darken($offwhite, 15);
。我需要另一个工具来替代这个Sass特性。在 CSS规范草案 中有CSS颜色函数,可以用来替代Sass这个特性。cssnext包括了这个函数功能,它非常的强大。在 setup.css
中的 darkerwhite
自定义属性可以通过 color()
函数和 shade
调节器来实现 。
:root { ... --offwhite: #f8f8f8; --darkerwhite: color(var(--offwhite) shade(20%)); ... }
color()
函数功能提供了一系列的 颜色调节器 。你可以在一个函数中使用多个调节器:
background-color: color(#d32c3f shade(40%) alpha(40%));
编译出来的CSS如下:
background-color: rgba(127, 26, 38, 0.4);
再次重申。现在cssnext编译出来的颜色结果是十六进制或 rgba()
值。当颜色函数在浏览器中运行时,编译将不会是必要的。颜色操作在运行时就可能发生。
在引入CSS预处理器时,嵌套是不可或缺的。一个比较舒适的样式设置。对于在处理器中的嵌套 规范 ,今天在cssnext中同样可以使用。
CSS的嵌套通过 &
来实现一个前置和后置的嵌套。例如下面的Sass片段:
.projects-list { ... li { & > div {...} } a { ... &:hover, &:focus {...} &::after {...} } @media (min-width: 640px) {...} }
使用CSS的嵌套来改变上面的示例:
.projects-list { ... & li { & > div {...} } & a { ... &:hover, &:focus {...} &::after {...} } @media (min-width: 640px) {...} }
基本的嵌套需要一个前置的 &
。伪类和选择器在Sass和CSS中使用是相同的。对于媒体查询嵌套,不需要前置的 &
。
同样值得一提的是 @nest
。在文档中提到,复杂的嵌套需要 @nest
替代 &
。我没有在这个项目的任何地方使用到 @nest
,或许在以后会用到。
在Sass中使用 @extend
和 %placeholder
是非常常见的。这里有一个简单的示例:
%futura { font-family: 'futura-pt', helvetica, sans-serif; } %futura-heading { @extend %futura; font-weight: 700; line-height: 1.1; text-transform: uppercase; }
另一个使用示例:
.my-heading { @extend %futura-heading; }
我看了早期使用CSS自定义属性的规范,在规范中正在提一个 @apply
规则。 @apply
允许你在选择器中引用一组已存储样式。我将使用 @apply
规则来替代Sass中的 @extend
规则。
回到 setup.css
,使用新特性更新标题样式:
:root { ... --franklin: { font-family: 'futura-pt', helvetica, sans-serif; }; --franklin-heading: { @apply --franklin; font-weight: 700; line-height: 1.1; text-transform: uppercase; }; }
另一个使用示例:
.my-heading { @apply --franklin-heading; }
@apply
不是 @extend
。在cssnext中, @apply
可以复制每个属性的规则和值。这是一个小项目,所以用不用都没关系。在大型项目中要是有一些额外的属性,就可能导致样式的冗余,文件过度膨胀。最好的方多使用一个通用的类名来设置相似的样式。
在这一点上,我的网站跟之前相比有所改变。项目页面是一个例外,它为每个区域使用一个不同的颜色。接下来将描述在没有Sass的情况之下如何正确使用样式,同时减少更多的工作,产出更高。
在项目中使用Sass的混合宏,可以简写样式代码。这个混合宏带一个参数,用来控制不同区域的颜色。这里把这个混合宏命名为 project-block
:
@mixin project-block ($c) { background-color: $c; a { color: $c; &:hover { background-color: $c; color: $offwhite); } } }
可以像下面这样调用已声明好的混合宏:
.p-jribbble { @include project-block(#ff0066); }
到写这篇文章之时,我在CSS中无法找到一个方法来模拟这个功能。CSS自定义属性和 @apply
没有类似的功能,所以你不能为其传递参数。在未来,有可能可以使用自定义选择器,并且可以给它传参数。在 规范草案 中有一个复杂的示例,看起来非常有前途。到目前为止,我还没有完全理解它是如何工作的。
这并不意味着我运气不好。我写CSS的时间比写Sass的长,但也长不了多久。我还在用另一个CSS特性,那就是 :matches
选择器 。
下面的示例是使用CSS的方法来替代 project-block
混合宏:
.p-jribbble, .p-jribbble a:matches(:hover, :focus) { background-color: var(--color-jrb); & a { color: var(--color-jrb); } }
颜色变量在前面的CSS文件中 :root
设置,cssnext来编译上面的CSS:
.p-jribbble, .p-jribbble a:hover, .p-jribbble a:focus { background-color: #ff0066 } .p-jribbble a, .p-jribbble a:hover a, .p-jribbble a:focus a { color: #ff0066; }
最后两个选择器 ... a a:hover
和 ... a a:focus
没有任何元素可匹配。他们是不必要的,但除了多了几个字节,并不会对样式造成任何伤害。其实我更喜欢选择器的嵌套,因为其更具可读性。
为了样式能有顺序的回来,我决定使用更多的PostCSS插件。我使用 css mqpacker 使用CSS媒体查询,也使用 cssnano 来优化代码。
这就是我期待的PostCSS设置。Sass只是锁定在当前版本的一些特性,而PostCSS是一些插件集合,它可以扩展。如果我需要一个特定的需求,我可以通过JavaScript来为这个需求编写一个插件。这个潜力是令人兴奋的。
使用了这个设置几天后,我一直在使用。也从Sass语法转换CSS的新语法。这也是我使用Sass五六年之后,使用另一个CSS处理器(PostCSS)做过的第一个项目。
我更喜欢这个带来的思想转变。cssnext也有类似于JavaScript的 Babel 。他们都让你写的语言,具备更多未来的特性。
本文根据 @tylergaw 的《 From Sass to PostCSS 》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处: https://tylergaw.com/articles/sass-to-postcss 。
常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《 图解CSS3:核心技术与案例实战 》。