# Stylus 预处理语言
Stylus 结合了 scss 和 less 语言的特点,有着比 less 语言更强大的功能,同时有着比 scss 更简单的配置(无需安装 sass-node 这样的支持),支持省去花括号和分号的写法。
只需安装 node.js,然后,在命令行中执行如下指令:
$ npm install stylus -g
# 父选择器
&
符号代表父级选择器。
textarea
input
color #A7A7A7
&:hover
color #000
2
3
4
5
编译为:
textarea,
input {
color: #a7a7a7;
}
textarea:hover,
input:hover {
color: #000;
}
2
3
4
5
6
7
8
如果需要在选择器中单纯地使用&
符,不使用其父级引用的功能,可以通过转义符\
来转义:
.foo[title*='\&']
// => .foo[title*='&']
2
# 选择器链
^[N]
表示选择器链的选取,^[0]
表示第一级选择器,^[1]
表示第二级选择器,并以此类推。
.foo
&__bar
width: 10px
^[0]:hover &
width: 20px
2
3
4
5
6
编译为
.foo__bar {
width: 10px;
}
.foo:hover .foo__bar {
width: 20px;
}
2
3
4
5
6
当 N 为负数时表示从结尾开始索引。所以^[-1]将给出链中&之前的最后一个选择器:
.foo
&__bar // ^[-1] 表示这一级的选择器
&_baz
width: 10px
^[-1]:hover &
width: 20px
2
3
4
5
6
7
编译为
.foo__bar_baz {
width: 10px;
}
.foo__bar:hover .foo__bar_baz {
width: 20px;
}
2
3
4
5
6
# 局部引用
之前的选择链都是从根级到指定的层级,但如果是要选择指定范围的选择器链,可以使用 ^[N..M]
, 其表示选择从 N 到 M 范围的选择器链。
.foo
& .bar
width: 10px
^[0]:hover ^[1..-1]
width: 20px
2
3
4
5
6
编译为
.foo .bar {
width: 10px;
}
.foo:hover .bar {
width: 20px;
}
2
3
4
5
6
# 向上索引
使用 ../../
语法可以从当前链向上索引。
.foo
.bar
width: 10px
&,
../ .baz
height: 10px
2
3
4
5
6
7
编译为
.foo .bar {
width: 10px;
}
.foo .bar,
.foo .baz {
height: 10px;
}
2
3
4
5
6
7
# 插值函数
当属性值未知时可以使用函数选择器占位属性
pad(n)
margin (- n)
body
pad(5px)
// 编译为
body { margin: -5px;}
2
3
4
5
6
7
8
9
# 模板语法
使用 {any}
语法可以解析参数。甚至可以嵌套传参。
vendor(prop1,prop2,args)
{prop1}-top:args
{prop2}-top:args
MarginAndPadding()
vendor('margin','padding',arguments)
button
MarginAndPadding 4px
// 编译为
button{margin-top:4px;padding-top:4px}
2
3
4
5
6
7
8
9
10
11
12
13
# 迭代插值 for in
table
for row in 1 2 3 4 5
tr:nth-child({row})
height: 10px * row
2
3
4
编译为
table tr:nth-child(1) {
height: 10px;
}
table tr:nth-child(2) {
height: 20px;
}
table tr:nth-child(3) {
height: 30px;
}
table tr:nth-child(4) {
height: 40px;
}
table tr:nth-child(5) {
height: 50px;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 变量
$fontSize = 14px
$fontStack = "Lucida Grande", Arial, sans-serif
body
font $fontSize $fontStack
//编译为:
body {
font: 14px "Lucida Grande", Arial, sans-serif;
}
2
3
4
5
6
7
8
9
10
变量类型
$var = "Lucida Grande", Arial, sans-serif // 基础类型
$arr = width height margin padding // 数组类型
$keyValue = (width 15px) // 键值对类型
$list = (width 15px) (height 15px) (margin 15px) (padding 15px) // 复合类型
2
3
4
# 属性查找
一个很棒的功能,可以通过前置 @ 符来访问该属性对应值。
属性查找会从当前选择器往上冒泡,查找堆栈直到被发现对应属性。
#logo
position: absolute
top: 50%
left: 50%
width: 150px
height: 80px
margin-left: -(@width / 2) // @width=150px
margin-top: -(@height / 2)// @height=80px
2
3
4
5
6
7
8
# 运算符
# 运算符优先级
.
[]
! ~ + -
is defined
** * / %
+ -
... ..
<= >= < >
in
== is != is not isnt
is a
&& and || or
?:
= := ?= += -= *= /= %=
not
if unless
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 一元运算符
可用的一元运算符包括 !
、not
、-
、+
和 ~
。
!0
// => true
!!0
// => false
!1
// => false
!!5px
// => true
-5px
// => -5px
--5px
// => 5px
not true
// => false
not not true
// => true
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 二元运算符
# 下标运算符 []
list = 1 2 3
list[0]
// => 1
list[-1]
// => 3
2
3
4
5
6
# 范围运算符 .. ...
1..5
// => 1 2 3 4 5
1...5
// => 1 2 3 4
5..1
// => 5 4 3 2 1
2
3
4
5
6
7
8
# 数学运算符
包括 加减乘除,累加累减累乘累除,指数运算符(**),相等与关系运算:(==、 !=、 >=、 <=、 >、<)
# 真值运算符
# 逻辑运算符 && ||
5 && 3
// => 3
0 || 5
// => 5
0 && 5
// => 0
#fff is a 'rgba' and 15 is a 'unit'
// => true
2
3
4
5
6
7
8
9
10
11
# 存在运算符:in
此运算符用于检查 左侧 操作数是否存在于 右侧 表达式中。
简单示例:
nums = 1 2 3
1 in nums
// => true
5 in nums
// => false
words = foo bar baz
bar in words
// => true
HEY in words
// => false
2
3
4
5
6
7
8
9
10
11
12
13
# 条件赋值运算符:?= :=
条件赋值运算符 ?=
(别名 :=
)允许我们定义变量而不删除旧值(如果存在的话)。
例如,以下内容是等效的:
color := white
color ?= white
color = color is defined ? color : white
2
3
使用 ?=
时,第二次的赋值就会失败
color = white
color ?= black
color
// => white
2
3
4
5
# 类型检查运算符:is a
15 is a 'unit'
// => true
#fff is a 'rgba'
// => true
#fff is a 'color'
// => true
15 is a 'rgba'
// => false
2
3
4
5
6
7
8
9
10
11
# 变量定义检查运算符:is defined
foo is defined
// => false
foo = 15px
foo is defined
// => true
#fff is defined
// => 'invalid "is defined" check on non-variable #fff'
2
3
4
5
6
7
8
9
# 三元运算符
num = 15
num ? unit(num, 'px') : 20px
// => 15px
2
3
# 添加单位 unit()
其中内置函数 unit() 的简洁替代写法为
body
n = 5
foo: (n)em
foo: (n)%
foo: (n + 5)%
foo: (n * 5)px
foo: unit(n + 5, '%')
foo: unit(5 + 180 / 2, deg)
2
3
4
5
6
7
8
# 函数
类似于 less 和 scss 中的混入,但是更加强大,可以返回返回值。
# 返回值
add(a, b)
a + b
body
padding add(10px, 5)
// 结果为
body {
padding: 15px;
}
2
3
4
5
6
7
8
9
10
# 默认参数
add(a, b = a)
a + b
add(10, 5)
// => 15
add(10)
// => 20
2
3
4
5
6
7
8
注意: 因为参数默认是赋值,因此我们可以使用函数调用作为默认值:
add(a, b = unit(a, px))
a + b
2
# 命名参数
函数可以接受命名参数。这可以免去记忆参数顺序的麻烦,或者说是提供了代码的可读性。
例如:
subtract(a, b)
a - b
subtract(b: 10, a: 25)
2
3
4
# 返回多个值
sizes()
15px 10px
sizes()[0]
// => 15px
2
3
4
5
swap(a, b)
(b a)
// 或
swap(a, b)
return b a
2
3
4
5
# 条件
compare(a, b)
if a > b
higher
else if a < b
lower
else
equal
2
3
4
5
6
7
用法:
compare(5, 2)
// => higher
compare(1, 5)
// => lower
compare(10, 10)
// => equal
2
3
4
5
6
7
8
# 函数作为变量使用
与为函数起 “别名” 一样,我们可以将函数作为参数传递。如下, invoke()
函数能够接收一个函数作为参数,因此我们可以将 add()
或 sub()
函数作为参数传递给 invoke()
。
add(a, b)
a + b
sub(a, b)
a - b
invoke(a, b, fn)
fn(a, b)
body
padding unit(invoke(5, 10, add),'px')
padding unit(invoke(5, 10, sub),'px')
2
3
4
5
6
7
8
9
10
11
12
生成:
body {
padding: 15px;
padding: -5px;
}
2
3
4
# 匿名函数
利用 @(){}
语法可以在需要的地方使用匿名函数。下面展示了如何利用匿名函数创建一个自定义的 sort()
函数:
sort(list,fn=null)
if fn==null
fn=@(a,b){ // 默认匿名函数函数
a > b
}
for $i in 1..length(list)-1
for $j in 0..$i-1
if fn(list[$i],list[$j])
$temp = list[$i]
list[$i] = list[$j]
list[$j] = $temp
return list
sort('e' 'c' 'f' 'a' 'b' 'd')
// => 'a' 'b' 'c' 'd' 'e' 'f'
sort(5 3 6 1 2 4, @(a, b){
a < b
})
// => 6 5 4 3 2 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 参数
arguments
是所有函数体都能够访问的局部变量,包含了传递过来的所有参数。
例如:
sum()
n = 0
for num in arguments
n = n + num
sum(1,2,3,4,5)
// => 15
2
3
4
5
6
7
# Hash 实例
下面我们定义了 get(hash, key)
函数,返回 key
的值或 null
。我们遍历 hash
中的每个键值对(pair
),如果键(key
)相匹配则返回对应的值。
get(hash, key)
for pair in hash
if pair[0] == key
return pair[1]
2
3
4
如下所示,语言内置的函数功能和 Stylus 表达式相结合,能够提供强大的灵活性:
hash = (one 1) (two 2) (three 3)
get(hash, two)
// => 2
get(hash, three)
// => 3
get(hash, something)
// => null
2
3
4
5
6
7
8
9
10
# 关键字参数
Stylus 支持关键字参数或 “kwargs”。这样就能够通过其关联的参数名来引用参数。
以下示例在功能上是等价的。 然而,我们可以 在参数列表中的任何位置放置关键字参数。 未设置关键字的参数将被用来填充其余尚未填充的参数。
body {
color: rgba(255, 200, 100, 0.5);
color: rgba(red: 255, green: 200, blue: 100, alpha: 0.5);
color: rgba(alpha: 0.5, blue: 100, red: 255, 200);
color: rgba(alpha: 0.5, blue: 100, 255, 200);
}
2
3
4
5
6
# 迭代器
$attrs=width height
body
for $attr in $attrs
for num in (1..5)
$attr unit(num,'px')
2
3
4
5
生成:
body {
width: 1px;
width: 2px;
width: 3px;
width: 4px;
width: 5px;
height: 1px;
height: 2px;
height: 3px;
height: 4px;
height: 5px;
}
2
3
4
5
6
7
8
9
10
11
12
# 后置表达式
就跟 if
/ unless
可以利用后置表达式(post-statement)一样,for
也可以。如下是一些使用后置表达式语法的例子:
sum(nums)
sum = 0
sum += n for n in nums
join(delim, args)
buf = ''
buf += i ? delim + arg : arg for arg, i in args
2
3
4
5
6
7
8
我们还可以从循环中 return (返回),下面就是一个实例,当 n % 2 == 0
的值为 true 时就返回数值。
first-even(nums)
return n if n % 2 == 0 for n in nums
first-even(1 3 5 5 6 3 2)
// => 6
2
3
4
5
# 内置函数
stylus 提供了许多强大的内置函数 (opens new window)来方便使用。
几个实用函数:
# alpha(color, value)
alpha(#fff)
// => 1
alpha(rgba(0,0,0,0.3))
// => 0.3
alpha(#fff, 0.5)
// => rgba(255,255,255,0.5)
2
3
4
5
6
7
8
# rgba(color | r,g,b,a)
rgba(255,0,0,0.5)
// => rgba(255,0,0,0.5)
rgba(255,0,0,1)
// => #ff0000
rgba(#ffcc00, 0.5)
// rgba(255,204,0,0.5)
2
3
4
5
6
7
8
# push(expr, args…)
nums = 1 2
push(nums, 3, 4, 5)
nums
// => 1 2 3 4 5
2
3
4
5
# pop(expr)
nums = 4 5 3 2 1
num = pop(nums)
nums
// => 4 5 3 2
num
// => 1
2
3
4
5
6
7
# shift(expr)
nums = 4 5 3 2 1
num = shift(nums)
nums
// => 5 3 2 1
num
// => 4
2
3
4
5
6
7
# unshift(expr, args…)
nums = 4 5
unshift(nums, 3, 2, 1)
nums
// => 1 2 3 4 5
2
3
4
5
# index(list, value)
list = 1 2 3
index(list, 2)
// => 1
index(1px solid red, red)
// => 2
2
3
4
5
6
7
# keys(pairs)
pairs = (one 1) (two 2) (three 3)
keys(pairs)
// => one two three
2
3
# values(pairs)
pairs = (one 1) (two 2) (three 3)
values(pairs)
// => 1 2 3
2
3
# length([expr])
length((1 2 3 4))
// => 4
length(1 2 3)
// => 3
length(1)
// => 1
length()
// => 0
2
3
4
5
6
7
8
9
10
11
# typeof(node)
type(12)
// => 'unit'
typeof(12)
// => 'unit'
typeof(#fff)
// => 'rgba'
type-of(#fff)
// => 'rgba'
2
3
4
5
6
7
8
9
10
11
# unit(val[, type])
unit(10)
// => ''
unit(15in)
// => 'in'
unit(15%, 'px')
// => 15px
unit(15%, px)
// => 15px
2
3
4
5
6
7
8
9
10
11
# percentage(num)
percentage(.5)
// => 50%
percentage(4 / 100)
// => 4%
2
3
4
5
# sum(nums)
sum(1 2 3)
// => 6
2
# avg(nums)
avg(1 2 3)
// => 2
2
# join(delim, vals…)
join(' ', 1 2 3)
// => "1 2 3"
join(',', 1 2 3)
// => "1,2,3"
join(', ', foo bar baz)
// => "foo, bar, baz"
join(', ', foo, bar, baz)
// => "foo, bar, baz"
join(', ', 1 2, 3 4, 5 6)
// => "1 2, 3 4, 5 6"
2
3
4
5
6
7
8
9
10
11
12
13
14
# split(delim, val)
split(_, bar1_bar2_bar3)
// => bar1 bar2 bar3
split(_, 'bar1_bar2_bar3')
// => 'bar1' 'bar2' 'bar3'
2
3
4
5
# substr(val, start, length)
The substr()
method returns the characters in a string beginning at the specified location through the specified number of characters.
substr(ident, 1, 2)
// => de
substr('string', 1, 2)
// => 'tr'
val = dredd
substr(substr(val, 1), 0, 3)
// => #f00
2
3
4
5
6
7
8
9
# slice(val, start[, end])
slice('lorem' 'ipsum' 'dolor', 1, 2)
slice('lorem' 'ipsum' 'dolor', 1, -1)
// => 'ipsum'
slice('lorem ipsum', 1, 5)
// => 'orem'
slice(rredd, 1, -1)
// => #f00
slice(1px solid black, 1)
// => solid #000
2
3
4
5
6
7
8
9
10
11
# lookup(name)
font-size-1 = 10px
font-size-2 = 20px
font-size-3 = 30px
for i in 1..3
.text-{i}
font-size: lookup('font-size-' + i)
2
3
4
5
6
7
编译为
.text-1 {
font-size: 10px;
}
.text-2 {
font-size: 20px;
}
.text-3 {
font-size: 30px;
}
2
3
4
5
6
7
8
9
# warn(msg)
warn("oh noes!")
# error(msg)
add(a, b)
unless a is a 'unit' and b is a 'unit'
error('add() expects units')
a + b
2
3
4