选择器(Selectors)
缩进(Indentation)
Stylus 类似于 Python,通过缩进对齐表达代码逻辑,如下所示:
body
color white
编译 CSS 为:
body {
color: #fff;
}
如果你喜欢,你可以把冒号加上,用做分隔,便于阅读:
body
color: white
规则集
Stylus 就跟 CSS 一样,允许你使用逗号为多个选择器同时定义属性。
textarea, input
border 1px solid #eee
同样可以用换行达到一样效果:
textarea
input
border 1px solid #eee
编译 CSS 为:
textarea,
input {
border: 1px solid #eee;
}
该规则唯一的例外就是长得像属性的选择器。
例如,下面的foo bar baz
可能是个属性或者是选择器。
foo bar baz
> input
border 1px solid
为解决这个原因,我们可以在尾部加个逗号:
foo bar baz,
form input,
> a
border 1px solid
父级引用
字符&
指向父选择器。下面这个例子,我们两个选择器(textarea
和input
)在:hover
伪类选择器上都改变了color
值
textarea
input
color #A7A7A7
&:hover
color #000
编译 CSS 为:
textarea,
input {
color: #a7a7a7;
}
textarea:hover,
input:hover {
color: #000;
}
消除歧义
像padding - n
这样的表达式,既可以被解释成减法运算,也可以被解释成一元减号。为了避免这种歧义,用括号包裹表达式:
pad(n)
padding (- n)
body
pad(5px)
编译 CSS 为:
body {
padding: -5px;
}
然而,只有在函数中才会存在这问题(因为函数返回值同时扮演了混合或回调)。
下面这个例子就没有问题(产生与上面相同的结果):
body
padding -5px
是否有 Stylus 无法处理的属性值?unquote()
可以帮助你:
filter unquote('progid:DXImageTransform.Microsoft.BasicImage(rotation=1)')
编译 CSS 为:
filter progid:DXImageTransform.Microsoft.BasicImage(rotation=1)
变量(Variables)
变量
我们可以声明变量,并在整个样式表中使用:
font-size = 14px
body
font font-size Arial, sans-serif
编译 CSS 为:
body {
font: 14px Arial, sans-serif;
}
变量甚至可以包含在表达式中:
font-size = 14px
font = font-size "Lucida Grande", Arial
body
font font sans-serif
编译 CSS 为:
body {
font: 14px "Lucida Grande", Arial sans-serif;
}
标识符(变量名、函数等)也可以是$
开始。例如:
$font-size = 14px
body {
font: $font-size sans-serif;
}
属性查找
Stylus 另一个很酷的、特有功能就是可以不用定义变量而引用属性。
下面是个很好的例子,让元素水平垂直居中对齐(典型的方法是使用百分比和margin
负值):
#logo
position: absolute
top: 50%
left: 50%
width: w = 150px
height: h = 80px
margin-left: -(w / 2)
margin-top: -(h / 2)
我们可以不使用变量w
和h
,而是简单地通过@
字符获取属性对应的值:
#logo
position: absolute
top: 50%
left: 50%
width: 150px
height: 80px
margin-left: -(@width / 2)
margin-top: -(@height / 2)
另外一种使用情况就是在混合中根据其他属性来定义属性值。
在下面这个例子中,我们定义在z-index
未被指定情况下默认值为1
。
position()
position: arguments
z-index: 1 unless @z-index
#logo
z-index: 20
position: absolute
#logo2
position: absolute
属性查找通过“冒泡”方式直到找到相应的值,或该属性不存在则返回null
。在以下示例中,@color
被解析为blue
:
body
color: red
ul
li
color: blue
a
background-color: @color
插值(Interpolation)
插值
Stylus 支持通过使用{}
字符包围表达式来插入值,其会变成标识符的一部分。
例如,-webkit-{'border' + '-radius'}
等同于-webkit-border-radius
比较好的例子就是私有前缀属性扩展:
vendor(prop, args)
-webkit-{prop} args
-moz-{prop} args
{prop} args
border-radius()
vendor('border-radius', arguments)
box-shadow()
vendor('box-shadow', arguments)
button
border-radius 1px 2px / 3px 4px
编译 CSS 为:
button {
-webkit-border-radius: 1px 2px / 3px 4px;
-moz-border-radius: 1px 2px / 3px 4px;
border-radius: 1px 2px / 3px 4px;
}
选择器插值
插值也可以在选择器上起作用。例如,我们可以指定表格前 5 行的高度,如下:
table
for row in 1 2 3 4 5
tr:nth-child({row})
height: 10px * row
编译 CSS 为:
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;
}
运算符(Operators)
运算符优先级
下表运算符优先级,从最高到最低:
[]
! ~ + -
is defined
** * / %
+ -
... ..
<= >= < >
in
== is != is not isnt
is a
&& and || or
?:
= := ?= += -= *= /= %=
not
if unless
一元运算符
以下一元运算符可用,!
, not
, -
, +
, 以及~
!0
// => true
!!0
// => false
!1
// => false
5px
// => true
-5px
// => -5px
--5px
// => 5px
not true
// => false
not not true
// => true
逻辑运算符not的优先级较低,因此,下面这个例子可以替换:
a = 0
b = 1
!a and !b
// => false
// 解析为: (!a) and (!b)
用:
not a or b
// => false
// 解析为: not (a or b)
混合书写(Mixins)
混入
混入和函数定义方法一致,但是应用却大相径庭。
例如,下面有定义的border-radius(n)
方法,其却作为一个mixin
(如,作为状态调用,而非表达式)调用。
当border-radius()
选择器中调用时候,属性会被扩展并复制在选择器中。
border-radius(n)
-webkit-border-radius n
-moz-border-radius n
border-radius n
form input[type=button]
border-radius(5px)
编译成:
form input[type=button] {
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
使用混入书写,你可以完全忽略括号,提供梦幻般私有属性的支持。
border-radius(n)
-webkit-border-radius n
-moz-border-radius n
border-radius n
form input[type=button]
border-radius 5px
注意到我们混合书写中的border-radius
当作了属性,而不是一个递归函数调用。
更进一步,我们可以利用arguments
这个局部变量,传递可以包含多值的表达式。
border-radius()
-webkit-border-radius arguments
-moz-border-radius arguments
border-radius arguments
现在,我们可以像这样子传值:border-radius 1px 2px / 3px 4px
!
另外一个很赞的应用是特定的私有前缀支持——例如IE浏览器的透明度:
support-for-ie ?= true
opacity(n)
opacity n
if support-for-ie
filter unquote('progid:DXImageTransform.Microsoft.Alpha(Opacity=' + round(n * 100) + ')')
#logo
&:hover
opacity 0.5
渲染为:
#logo:hover {
opacity: 0.5;
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=50);
}
父级引用
混合书写可以利用父级引用字符&
, 继承父业而不是自己筑巢。
例如,我们要用stripe(even, odd)
创建一个条纹表格。even
和odd
均提供了默认颜色值,每行也指定了background-color
属性。我们可以在tr
嵌套中使用&
来引用tr
,以提供even
颜色。
stripe(even = #fff, odd = #eee)
tr
background-color odd
&.even
&:nth-child(even)
background-color even
然后,利用混合书写,如下:
table
stripe()
td
padding 4px 10px
table#users
stripe(#303030, #494848)
td
color white
另外,stripe()
的定义无需父引用:
stripe(even = #fff, odd = #eee)
tr
background-color odd
tr.even
tr:nth-child(even)
background-color even
如果你愿意,你可以把stripe()
当作属性调用。
stripe #fff #000
混合书写中的混合书写
自然,混合书写可以利用其它混合书写,建立在它们自己的属性和选择器上。
例如,下面我们创建内联comma-list()
(通过inline-list()
)以及逗号分隔的无序列表。
inline-list()
li
display inline
comma-list()
inline-list()
li
&:after
content ', '
&:last-child:after
content ''
ul
comma-list()
渲染:
ul li:after {
content: ", ";
}
ul li:last-child:after {
content: "";
}
ul li {
display: inline;
}
方法(Functions)
函数
Stylus 强大之处就在于其内置的语言函数定义。其定义与混入(mixins)一致;却可以返回值。
返回值
很简单的例子,两数值相加的方法:
add(a, b)
a + b
我们可以在特定条件下使用该方法,如在属性值中:
body
padding add(10px, 5)
渲染:
body {
padding: 15px;
}
默认参数
可选参数往往有个默认的给定表达。在 Stylus 中,我们甚至可以超越默认参数。
例如:
add(a, b = a)
a + b
add(10, 5)
// => 15
add(10)
// => 20
注意:因为参数默认是赋值,我们可可以使用函数调用作为默认值。
add(a, b = unit(a, px))
a + b
函数体
我们可以把简单的add()
方法更进一步。通过内置unit()
把单位都变成px
, 因为赋值在每个参数上,因此,我们可以无视单位换算。
add(a, b = a)
a = unit(a, px)
b = unit(b, px)
a + b
add(15%, 10deg)
// => 25
多个返回值
Stylus 的函数可以返回多个值,就像你给变量赋多个值一样。
例如,下面就是一个有效赋值:
sizes = 15px 10px
sizes[0]
// => 15px
类似的,我们可以在函数中返回多个值:
sizes()
15px 10px
sizes()[0]
// => 15px
有个小小的例外就是返回值是标识符。例如,下面看上去像一个属性赋值给 Stylus(因为没有操作符)。
swap(a, b)
b a
为避免歧义,我们可以使用括号,或是return
关键字。
swap(a, b)
(b a)
swap(a, b)
return b a
条件
比方说,我们想要创建一个名为stringish()
的函数,用来决定参数是否是字符串。我们检查val
是否是字符串或缩进(类似字符)。如下,使用yes
和no
代替true
和false
stringish(val)
if val is a 'string' or val is a 'ident'
yes
else
no
使用:
stringish('yay') == yes
// => true
stringish(yay) == yes
// => true
stringish(0) == no
// => true
注意:yes
和no
并不是布尔值。本例中,它们只是简单的未定义标识符。
另外一个例子:
compare(a, b)
if a > b
higher
else if a < b
lower
else
equal
使用:
compare(5, 2)
// => higher
compare(1, 5)
// => lower
compare(10, 10)
// => equal
别名
给函数起个别名,和简单,直接等于就可以了。例如上面的add()
弄个别名plus()
, 如下:
plus = add
plus(1, 2)
// => 3
变量函数
我们可以把函数当作变量传递到新的函数中。例如,invoke()
接受函数作为参数,因此,我们可以传递add()
以及sub()
invoke(a, b, fn)
fn(a, b)
add(a, b)
a + b
body
padding invoke(5, 10, add)
padding invoke(5, 10, sub)
结果:
body {
padding: 15;
padding: -5;
}
参数
arguments
是所有函数体都有的局部变量,包含传递的所有参数。
例如:
sum()
n = 0
for num in arguments
n = n + num
sum(1,2,3,4,5)
// => 15
哈希示例
下面,我们定义get(hash, key)
方法,用来返回key
值或null
我们遍历每个键值对,如果键值匹配,返回对应的值。
get(hash, key)
return pair[1] if pair[0] == key for pair in hash
下面例子可以证明,语言函数模样的Stylus表达式具有更大的灵活性。
hash = (one 1) (two 2) (three 3)
get(hash, two)
// => 2
get(hash, three)
// => 3
get(hash, something)
// => null
关键字参数(Keyword Arguments)
关键字参数
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);
}
等同于:
body {
color: rgba(255,200,100,0.5);
color: rgba(255,200,100,0.5);
color: rgba(255,200,100,0.5);
color: rgba(255,200,100,0.5);
}
查看函数或混合书写中接受的参数,可以使用p()
方法。
p(rgba)
生成:
inspect: rgba(red, green, blue, alpha)
内置方法(Built-in Functions)
red(color)
返回color中的红色比重。
red(#c00)
// => 204
green(color)
返回color中的绿色比重。
green(#0c0)
// => 204
blue(color)
返回color中的蓝色比重。
red(#00c)
// => 204
alpha(color)
返回color中的透明度比重。
alpha(#fff)
// => 1
alpha(rgba(0,0,0,0.3))
// => 0.3
dark(color)
检查color是否是暗色。
dark(black)
// => true
dark(#005716)
// => true
dark(white)
// => false
light(color)
检查color是否是亮色。
light(black)
// => false
light(white)
// => true
light(#00FF40)
// => true
hue(color)
返回给定color的色调。
hue(hsla(50deg, 100%, 80%))
// => 50deg
saturation(color)
返回给定color的饱和度。
saturation(hsla(50deg, 100%, 80%))
// => 100%
lightness(color)
返回给定color的亮度。
lightness(hsla(50deg, 100%, 80%))
// => 80%