Stylus似乎并不是很有名,以至于很多人不知道它是做什么的,但提到SASS相信有不少人听说过甚至使用过很长时间。其实无论是LESS、SASS还是Stylus甚至是Absurd这些预处理工具,都是对CSS的一种延伸和强化。出现这些工具的原因很简单,CSS本身只是一种描述性质的东西,甚至它不能算是语言而是样式表,所以我们需要一个有条件语句和变量甚至是函数的东西去动态生成CSS代码来达到提高效率和增强可维护性的目的。
本文主要以Stylus语法本身和简单的使用为主要内容,它的目的是介绍和简单指南。将不会过多涉及Javascript的API调用等问题。
介绍
官方的介绍非常简短而精炼:
Expressive, dynamic, robust CSS
富有表现力的动态的强壮的CSS,它反应了一些主要特点。
首先Stylus相较于SASS更加简洁,甚至冒号也都可以省略,初学Stylus时感到它太神奇了,仅仅以空格分隔属性名和多个属性值就可以生成想要的CSS,而且还可以拼接字符串等等。与此同时,类似Ruby或Python完善的缩进语法,Stylus在简约自由中有效的防止了语法歧义。
body |
其次是动态,这正是其精髓所在,Stylus由Javascript编译,其结构语句也和Javascript相差不多,前端人员可以很轻松的上手。虽然这方面Absurd是一个极端,但Stylus较之LESS则要优越不少,不仅仅是可定义变量,如Javascript般的条件语句和循环语句也为Stylus带来各种可能,加上丰富的内置函数,可以轻松判断和操作各种变量。而利用这样的动态性,就可以写出非常强壮的CSS以满足不同环境和条件下的需要。
pos(type, args) |
简单指南
可以看到上面的代码中使用了Mixin(混合)还有三目运算符等手段构建了一个针对position的方法,用来快速生成一个定位代码片段。有底向上来看这段代码,#prompt和#logo是2个ID选择器,在其中调用了一些Mixin,其实Mixin与Function的区别在于,Mixin的内容是一段CSS代码,而Function应该是一个值并自动返回,所以调用它们的时候,前者将会替换为一段CSS,而后者将返回一个Boolean或者像素或者颜色之类的东西,也许用于判断也许直接放入CSS。然后其中的absolute和fixed分别调用了pos这个Mixin。
前缀
而且在调用时,也不一定要使用括号的形式,可以使用CSS的形式,直接Mixin名加空格然后写参数。所以有时候可以直接写一个Mixin来修改CSS属性的功能,比如看看下面这个兼容所有标准浏览器阴影的写法,可以很方便的为标准调用加上各标准浏览器的前缀:
box-shadow() |
可以看到调用时的写法与一般的写法一样,但是因为Mixin的存在,box-shadow不再是一个属性,可以变成5行带有各浏览器前缀的CSS。不仅仅是box-shadow,CSS3的许多属性都需要添加前缀,那是不是可以更近一步呢,来写一个前缀Mixin吧:
// add prefix for attribute |
颜色
如同其他CSS预处理工具一样,Stylus在颜色方面也拥有许多内置函数,无论是判断,提取还是修改都十分强大。函数 red
, blue
, green
, alpha
将分别返回颜色对应的rgba值,dark
和 light
用于判断颜色属于亮色还是暗色,hue
, saturation
, lightness
则分别返回颜色的色相、饱和度以及亮度,其中色相是在色环上的角度,单位是deg。我经常用的是lighten
和 darken
这两个函数,其作用是增加或减少一个颜色的亮度,另外还有饱和度的操作函数 desaturate
和 satucate
。
似乎没有用于修改色相的函数,不过这个需求很容易通过其他办法搞定。首先使用hue等函数将原始色的色相、饱和度、亮度以及透明度取出,然后对色相的角度进行修改,比如加90deg,最后再使用hsla函数,把去除的对应值当作参数传入即可。下面用一组三态按钮来举个栗子:
See the Pen Single Button by Zhang zhengzheng (@tychio) on CodePen
可以看到Stylus中的第一行代码 $clr = #99ff22
只要修改这个颜色值就可以改变按钮的整体风格,并无需考虑hover和active状态时对应的颜色。比如边框使用 darken
来加深,阴影泛光可以使用 lighten
来加亮,在触碰时整体使用了 saturate
来改变饱和度,按下的Active状态我使用了 invert
函数,可以翻转颜色,在视觉设计中这个颜色叫做对位色,即色相处于色环的对面的两种颜色,比如绿对红,黄对蓝,例子中使用了黄绿,所以对位色就是紫色。当然也可以使用上面提到的复杂一些的方法来修改色相,达到使用间隔色之类的效果。
响应式
对于响应式的支持,Stylus的media也可以省略花括号,但和Sass有一些区别。Stylus在@media的括号中会原样输出,也就是说,我们不能使用变量或混合还有计算等手段来直接写media query。比如一般情况下需要写一个min-width,如果这样写
$mobiWidth = 768px |
产生的CSS代码则仍然是
@media screen and (min-width $mobiWidth - 1px) { |
这不是一个bug,尽管在Github上有无数的人提出issue或者在其后+1,作者仍然不为所动,原因不明,不过幸运地是有很多人都提出解决办法,下面是一个比较好的方法:
media() |
这样就可以使用变量来作为media的参数了,只是写起来会比sass麻烦一些,但我觉得这样也许更自由,你可以改进这个方法,比如传一个object来作为query条件,而不是拼接一个字符串。另外这个方法还用到了 join
内置函数,和Javascript中的Array方法join一样,很容易使用,除了它还有 push
, unshift
函数。
关于数组的定义,对于响应式来说有非常好的帮助,因为响应式往往是一系列的尺寸或设备,无论如何,使用数组可以轻松的定义多组对应与索引的配套值。比如我的blog,对于不同宽度的设备中有不同的内容宽度以及边距,来看看简化的代码:
$screen = 1920px 1280px 1024px 768px 640px 320px |
当然响应式不是简单的改变尺寸,如果你需要控制某些内容的显示则可以使用一个Boolean的数组来判断是否显示,控制结构或样式则可以字符串的数组来放置一些预先写好的Mixin名称。
CSS Sprite
对于CSS Sprite相信是所有切图者的主要工作产出,以前我也推荐过一些在线的制作Sprite的工具,不过现在有了Stylus,也许我们可能更快的完成这一切。之前公司有需要国旗icon,所以做了这个小项目national_flag用来创建和维护国旗icon的CSS Sprite。由于国家数目众多,每个国家对应一个国家代码,所以我定义了一个二维数组用来表现图片中国旗的位置,然后在数组中填入代码,用来拼接图标的class名称,然后按照数组中的序号和尺寸就可以生成对应的background-position了。主要代码如下:
iconBuild(id, col, row) |
其中for不同于Javascript,rowList为数组遍历出的一个元素,而$row为索引,可以这样理解 for [value], [index] in [array]
。所以可以在两个嵌套的for中获取纵横的位置以及国家代码,来生成CSS。
Stylue应用
作为预处理工具,Stylus自然也需要预处理器,不过它不像Sass需要Ruby环境,Stylus由Javascript实现,所以有Javascript就可以处理Stylus。
编译工具
- SublimeText2-Stylus2CSS是一款SublimeText2的Stylus插件。另外我使用这个项目的SublimeText2插件来高亮styl文件的代码。
- 另外今年8月WebStorm7也才刚刚支持 - Stylus Support。
- CodePen支持各种CSS预处理,自然包括Stylus,上面的按钮例子就是嵌入的CodePen。
- Stylus官方在线其实是一些示例,不过它是可编辑的,所以你也可以随便写些什么,即时可以看到结果。不过好像还在使用低版本的Stylus,比如一些内置函数就不可用。
Grunt插件
不过说到处理文件,Grunt还是我的最爱,尤其Stylus是由Javascript实现,在Nodejs中自然是得天独厚。npmjs上有许多用来处理Stylus的插件,下面简单介绍一下Grunt的官方Stylus插件grunt-contrib-stylus。先来看看最简单的配置方法:
stylus: { |
如此就可以利用Grunt将source.styl文件中的Stylus代码编译为result.css的CSS代码。当然还可以使用数组来进行多个Stylus文件的打包编译。当然不仅于此,先来看看主要的几个配置项:
paths
将自动使用@import来引入一些Stylus文件,比如一些Mixin集合,放在一个Stylus文件中进行维护,写在paths中后,就可以在每个Stylus文件中调用它们。define
可以定义一些全局变量,然后在Stylus中使用,但我不喜欢使用这个配置,而是更喜欢把全局变量放在一个单独的Stylus文件中,然后将这个文件加入paths的数组中。一句话,把所有不会直接产出CSS的Stylus代码分成若干个Stylus文件,然后全部添加到paths中,这样在所有Stylus文件中都可以随时调用了,但要注意这些Stylus文件的调用关系和使用先后顺序。
compress
及 linenos
是两个Boolean值,用来控制是否压缩处理后的CSS代码以及是否在CSS代码中保留注释。
banner
是一个字符串,会被放置在CSS文件的最前面,一般我用来写注释,比如
banner: '\/** \n * <%= pkg.name %> - <%= pkg.description %>\n * version <%= pkg.version %> \n * author <%= pkg.author %> \n * date <%= grunt.template.today() %> \n**/\n' |
firebug
将控制是否使用一个Firebug的Stylus插件FireStylus for Firebug,可以在Firefox中调试Stylus。
use
可以引入一些Stylus的其他grunt插件。
配合watch等Grunt插件就可以达到自动化的Stylus开发,写样式将会非常有效率。
总结
Stylus是一个由Javascript实现的CSS预处理工具,文件后缀为styl,其拥有变量、函数、混合、条件及循环语句等功能,还有丰富的内置函数用于处理颜色、数字、数组等数据。在grunt的辅助下,Stylus将带来极大的开发效率。
我还在slides上制作了一个Stylus简介的幻灯片,还没有经过实践,可能内容有些空泛,不过将持续改进。