热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

从Sass过渡到PostCSS

Sass多年来一直是我的首选。最近我有一段时间,想尝试使用PostCSS的cssnext插件来处理CSS样式。我一直想

Sass 多年来一直是我的首选。最近我有一段时间,想尝试使用 PostCSS 的 cssnext 插件来处理CSS样式。我一直想使用工具尝试写一些CSS的新特性。同时自己的个人网站也是一个最佳测试这些新特性的实验地。

第一步先了解我使用Sass写的东西,需要知道我用了些什么功能,以确保找到一个替代的工具(PostCSS插件)。下面这个列表是我项目中用到的一些功能:

  • 引入部分(partial imports)
  • 变量(variables)
  • 嵌套(nesting)
  • 混合宏(mixins)
  • 扩展(extend)
  • 占位符(placeholder classes)
  • 颜色函数(darken and rgba color functions)
  • 压缩(compression)

准备工作

在了解CSS新特性语法和其他有趣的东西之前,需要做一些必要的准备工具。Sass项目的文件结构是有几个典型用法。使用下划线(_)来命名文件名,这些文件都是以.scss作为文件扩展名。其中两个文件夹modulespartials放置对应的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命令一次性完成,所以只能手动每个去修改。

最后一步是将modulespartials目录下的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

cssnext是PostCSS一个插件,把CSS未来特性编译成现在CSS语法特性。特别需要注意的是,这个插件和Sass和LESS都不一样。它提供的特性是CSS正在进行的规范(或者未来CSS将会具备的语法特性)。而且有一些特性已经得到了浏览器的支持。

我使用cssnext来处理Sass不具备的一些特性。

浏览器私有前缀

我在创建这个网站之前我就知道Autoprefixer。我使用了自定义的Sass混合宏来处理浏览器所需的私有前缀。cssnext包括了Autoprefixer插件,所以我可以删除整个混合宏模块。

变量(variables)

接下来我需要使用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()值。当颜色函数在浏览器中运行时,编译将不会是必要的。颜色操作在运行时就可能发生。

嵌套(nesting)

在引入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 更多特性

为了样式能有顺序的回来,我决定使用更多的PostCSS插件。我使用 css mqpacker 使用CSS媒体查询,也使用 cssnano 来优化代码。

这就是我期待的PostCSS设置。Sass只是锁定在当前版本的一些特性,而PostCSS是一些插件集合,它可以扩展。如果我需要一个特定的需求,我可以通过Javascript来为这个需求编写一个插件。这个潜力是令人兴奋的。

小结

使用了这个设置几天后,我一直在使用。也从Sass语法转换CSS的新语法。这也是我使用Sass五六年之后,使用另一个CSS处理器(PostCSS)做过的第一个项目。

我更喜欢这个带来的思想转变。cssnext 也有类似于 Javascript 的 Babel。他们都让你写的语言,具备更多未来的特性。


推荐阅读
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 安卓select模态框样式改变_微软Office风格的多端(Web、安卓、iOS)组件库——Fabric UI...
    介绍FabricUI是微软开源的一套Office风格的多端组件库,共有三套针对性的组件,分别适用于web、android以及iOS,Fab ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
author-avatar
PANJIANSHUANG_406
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有