选择器(Selectors)
缩排(Indentation)
Stylus 蛮“玄幻”的(如基于缩进),空格有重要的意义,所以,我们使用缩排和凹排代替花括号{以及}
body
color white上面代码就对应于:
body {
color: #fff;
}如果你喜欢,你可以把冒号加上,用做分隔,便于阅读:
body
color: white规则集
Stylus 就跟 CSS 一样,允许你使用逗号为多个选择器同时定义属性。
textarea, input
border 1px solid #eee使用新行是一样的效果:
textarea
input
border 1px solid #eee等同于:
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等同于:
textarea,
input {
color: #a7a7a7;
}
textarea:hover,
input:hover {
color: #000;
}下面这个例子,IE 浏览器利用了父级引用以及混合书写来实现2px的边框。
box-shadow()
-webkit-box-shadow arguments
-moz-box-shadow arguments
box-shadow arguments
html.ie8 &,
html.ie7 &,
html.ie6 &
border 2px solid arguments[length(arguments) - 1]
body
#login
box-shadow 1px 1px 3px #eee其变身后面目:
body #login {
-webkit-box-shadow: 1px 1px 3px #eee;
-moz-box-shadow: 1px 1px 3px #eee;
box-shadow: 1px 1px 3px #eee;
}
html.ie8 body #login,
html.ie7 body #login,
html.ie6 body #login {
border: 2px solid #eee;
}消除歧义
类似padding - n的表达式可能既被解释成减法运算,也可能被释义成一元负号属性。为了避免这种歧义,用括号包裹表达式:
pad(n)
padding (- n)
body
pad(5px)编译为:
body {
padding: -5px;
}然而,只有在函数中才会这样(因为函数同时用返回值扮演混合或回调)。
例如,下面这个就是 OK 的(产生与上面相同的结果):
body
padding -5px有 Stylus 无法处理的属性值?unquote()可以帮你:
filter unquote('progid:DXImageTransform.Microsoft.BasicImage(rotation=1)')生成为:
filter progid:DXImageTransform.Microsoft.BasicImage(rotation=1)变量(Variables)
变量
我们可以指定表达式为变量,然后在我们的样式中贯穿使用:
font-size = 14px
body
font font-size Arial, sans-seri编译为:
body {
font: 14px Arial, sans-serif;
}变量甚至可以组成一个表达式列表:
font-size = 14px
font = font-size "Lucida Grande", Arial
body
font font sans-serif编译为:
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,但是,只有在z-index之前未指定的时候才这样:
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变身:
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也就是:
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)二元运算符
下标运算符[]允许我们通过索引获取表达式内部值。括号表达式可以充当元组(如(15px 5px), (1, 2, 3))。
下面这个例子使用错误处理的元组(并展示了该结构的多功能性):
add(a, b)
if a is a 'unit' and b is a 'unit'
a + b
else
(error 'a 和 b 必须是 units!')
body
padding add(1,'5')
// => padding: error "a 和 b 必须是 units";
padding add(1,'5')[0]
// => padding: error;
padding add(1,'5')[0] == error
// => padding: true;
padding add(1,'5')[1]
// => padding: "a 和 b 必须是 units";这儿有个更复杂的例子。现在,我们调用内置的error()函数,当标识符(第一个值)等于error的时候返回错误信息。
if (val = add(1,'5'))[0] == error
error(val[1])范围.. ...
同时提供包含界线操作符(..)和范围操作符(...),见下表达式:
1..5
// => 1 2 3 4 5
1...5
// => 1 2 3 4加减:+ -
二元加乘运算其单位会转化,或使用默认字面量值。例如,5s - 2px结果是3s.
15px - 5px
// => 10px
5 - 2
// => 3
5in - 50mm
// => 3.031in
5s - 1000ms
// => 4s
20mm + 4in
// => 121.6mm
"foo " + "bar"
// => "foo bar"
"num " + 15
// => "num 15"乘除:/ * %
2000ms + (1s * 2)
// => 4000ms
5s / 2
// => 2.5s
4 % 2
// => 0当在属性值内使用/时候,你必须用括号包住。否则/会根据其字面意思处理(支持 CSS 的line-height)。
font: 14px/1.5;但是,下面这个却等同于14px ÷ 1.5:
font: (14px/1.5);只有/操作符的时候需要这样。
指数:**
指数操作符:
2 ** 8
// => 256相等与关系运算:== != >= <= > <
相等运算符可以被用来等同单位、颜色、字符串甚至标识符。这是个强大的概念,甚至任意的标识符(例如wahoo)可以作为原子般使用。函数可以返回yes和no代替true和false(虽然不建议)。
5 == 5
// => true
10 > 5
// => true
#fff == #fff
// => true
true == false
// => false
wahoo == yay
// => false
wahoo == wahoo
// => true
"test" == "test"
// => true
true is true
// => true
'hey' is not 'bye'
// => true
'hey' isnt 'bye'
// => true
(foo bar) == (foo bar)
// => true
(1 2 3) == (1 2 3)
// => true
(1 2 3) == (1 1 3)
// => false只有精确值才匹配,例如,0 == false和null == false均返回false.
别名:
== is
!= is not
!= isnt真与假
Stylus 近乎一切都是true, 包括有后缀的单位,甚至0%, 0px等都被认作true.
不过,0在算术上本身是false.
表达式(或“列表”)长度大于 1 被认为是真。
true例子:
0%
0px
1px
-1
-1px
hey
'hey'
(0 0 0)
('' '')false例子:
0
null
false
''逻辑操作符:&& || 和 or
逻辑操作符&&和||别名是and / or。它们优先级相同。
5 && 3
// => 3
0 || 5
// => 5
0 && 5
// => 0
#fff is a 'rgba' and 15 is a 'unit'
// => true存在操作符: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元组同样适用:
vals = (error 'one') (error 'two')
error in vals
// => false
(error 'one') in vals
// => true
(error 'two') in vals
// => true
(error 'something') in vals
// => false混合书写适用例子:
pad(types = padding, n = 5px)
if padding in types
padding n
if margin in types
margin n
body
pad()
body
pad(margin)
body
pad(padding margin, 10px)对应于:
body {
padding: 5px;
}
body {
margin: 5px;
}
body {
padding: 10px;
margin: 10px;
}条件赋值:?= :=
条件赋值操作符?=(别名?:)让我们无需破坏旧值(如果存在)定义变量。该操作符可以扩展成三元内is defined的二元操作。
例如,下面这些都是平起平坐的:
color := white
color ?= white
color = color is defined ? color : white如果我们使用等号=, 就只是简单地赋值。
color = white
color = black
color
// => black但当使用?=,第二个相当就嗝屁了(因为变量已经定义了):
color = white
color ?= black
color
// => white实例检查:is a
Stylus 提供一个二元运算符叫做is a, 用做类型检查。
15 is a 'unit'
// => true
#fff is a 'rgba'
// => true
15 is a 'rgba'
// => false另外,我们可以使用type()这个内置函数。
type(#fff) == 'rgba'
// => true注意:color是唯一的特殊情况,当左边是RGBA或者HSLA节点时,都为true.
变量定义:is defined
此伪二元运算符右边空荡荡,左边无计算。用来检查变量是否已经分配了值。
foo is defined
// => false
foo = 15px
foo is defined
// => true
#fff is defined
// => 'invalid "is defined" check on non-variable #fff'另外,我们可以使用内置lookup(name)方法做这个活动态查找。
name = 'blue'
lookup('light-' + name)
// => null
light-blue = #80e2e9
lookup('light-' + name)
// => #80e2e9该操作符必不可少,因为一个未定义的标识符仍是真值。如:
body
if ohnoes
padding 5px当未定义的时候,产生的是下面的 CSS:
body {
padding: 5px;
}显然,这不是我们想要的,如下书写就安全了:
body
if ohnoes is defined
padding 5px三元
三元运算符的运作正如大部分语言里面的那样。三个操作对象的操作符(条件表达式、真表达式以及假表达式)。
num = 15
num ? unit(num, 'px') : 20px
// => 15px铸造
作为替代简洁的内置unit()函数,语法(expr) 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)颜色操作
颜色操作提供了一个简洁,富有表现力的方式来改变其组成。例如,我们可以对每个 RGB:
#0e0 + #0e0
// => #0f0另外一个例子是通过增加或减少百分值调整颜色亮度。颜色亮,加;暗,则减。
#888 + 50%
// => #c3c3c3
#888 - 50%
// => #444我们也可以通过增加或减去色度调整色调。例如,红色增加65deg就变成了黄色。
#f00 + 50deg
// => #ffd500值适当固定。例如,我们可以"旋转"180 度的色调,如果目前的值是320deg, 将变成140deg.
我们也可能一次调整几个值(包括 alpha),通过使用rgb(), rgba(), hsl(), 或 hsla():
#f00 - rgba(100,0,0,0.5)
// => rgba(155,0,0,0.5)格式化字符串
格式化字符串模样的字符串%可以用来生成字面量值,通过传参给内置s()方法。
'X::Microsoft::Crap(%s)' % #fc0
// => X::Microsoft::Crap(#fc0)多个值需要括起来:
'-webkit-gradient(%s, %s, %s)' % (linear (0 0) (0 100%))
// => -webkit-gradient(linear, 0 0, 0 100%)混合书写(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)
// => 204green(color)
返回color中的绿色比重。
green(#0c0)
// => 204blue(color)
返回color中的蓝色比重。
red(#00c)
// => 204alpha(color)
返回color中的透明度比重。
alpha(#fff)
// => 1
alpha(rgba(0,0,0,0.3))
// => 0.3dark(color)
检查color是否是暗色。
dark(black)
// => true
dark(#005716)
// => true
dark(white)
// => falselight(color)
检查color是否是亮色。
light(black)
// => false
light(white)
// => true
light(#00FF40)
// => truehue(color)
返回给定color的色调。
hue(hsla(50deg, 100%, 80%))
// => 50degsaturation(color)
返回给定color的饱和度。
saturation(hsla(50deg, 100%, 80%))
// => 100%lightness(color)
返回给定color的亮度。
lightness(hsla(50deg, 100%, 80%))
// => 80%push(expr, args…)
后面推送给定的args给expr.
nums = 1 2
push(nums, 3, 4, 5)
nums
// => 1 2 3 4 5别名为append().
unshift(expr, args…)
起始位置插入给定的args给expr.
nums = 4 5
unshift(nums, 3, 2, 1)
nums
// => 1 2 3 4 5别名为prepend().
keys(pairs)
返回给定pairs中的键。
pairs = (one 1) (two 2) (three 3)
keys(pairs)
// => one two threevalues(pairs)
返回给定pairs中的值。
pairs = (one 1) (two 2) (three 3)
values(pairs)
// => 1 2 3typeof(node)
字符串形式返回node类型。
type(12)
// => 'unit'
typeof(12)
// => 'unit'
typeof(#fff)
// => 'rgba'
type-of(#fff)
// => 'rgba'别名有type-of和type.
unit(unit[, type])
返回unit类型的字符串或空字符串,或者赋予type值而无需单位转换。
unit(10)
// => ''
unit(15in)
// => 'in'
unit(15%, 'px')
// => 15px
unit(15%, px)
// => 15pxmatch(pattern, string)
检测string是否匹配给定的pattern.
match('^foo(bar)?', foo)
match('^foo(bar)?', foobar)
// => true
match('^foo(bar)?', 'foo')
match('^foo(bar)?', 'foobar')
// => true
match('^foo(bar)?', 'bar')
// => falseabs(unit)
绝对值。
abs(-5px)
// => 5px
abs(5px)
// => 5pxceil(unit)
向上取整。
ceil(5.5in)
// => 6infloor(unit)
向下取整。
floor(5.6px)
// => 5pxround(unit)
四舍五入取整。
round(5.5px)
// => 6px
round(5.4px)
// => 5pxmin(a, b)
取较小值。
min(1, 5)
// => 1max(a, b)
取较大值。
max(1, 5)
// => 5even(unit)
是否为偶数。
even(6px)
// => trueadd(unit)
是否为奇数。
odd(5mm)
// => truesum(nums)
求和。
sum(1 2 3)
// => 6avg(nums)
求平均数。
avg(1 2 3)
// => 2join(delim, vals…)
给定vals使用delim连接。
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"hsla(color | h,s,l,a)
转换给定color为HSLA节点,或 h,s,l,a 比重值。
hslaa(10deg, 50%, 30%, 0.5)
// => HSLA
hslaa(#ffcc00)
// => HSLAhsla(color | h,s,l)
转换给定color为HSLA节点,或 h,s,l 比重值。
hsla(10, 50, 30)
// => HSLA
hsla(#ffcc00)
// => HSLArgba(color | r,g,b,a)
从 r,g,b,a 通道返回RGBA, 或提供color来调整透明度。
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)另外,stylus 支持#rgba以及#rrggbbaa符号。
#fc08
// => rgba(255,204,0,0.5)
#ffcc00ee
// => rgba(255,204,0,0.9)rgb(color | r,g,b)
从 r,g,b 通道返回RGBA或生成一个RGBA节点。
rgb(255,204,0)
// => #ffcc00
rgb(#fff)
// => #ffflighten(color, amount)
给定color增亮amount值。该方法单位敏感,例如,支持百分比,如下:
lighten(#2c2c2c, 30)
// => #787878
lighten(#2c2c2c, 30%)
// => #393939darken(color, amount)
给定color变暗amount值。该方法单位敏感,例如,支持百分比,如下:
darken(#D62828, 30)
// => #551010
darken(#D62828, 30%)
// => #961c1cdesaturate(color, amount)
给定color饱和度减小amount.
desaturate(#f00, 40%)
// => #c33saturate(color, amount)
给定color饱和度增加amount.
saturate(#c33, 40%)
// => #f00invert(color)
颜色反相。红绿蓝颜色反转,透明度不变。
invert(#d62828)
// => #29d7d7unquote(str | ident)
给定str引号去除,返回Literal节点。
unquote("sans-serif")
// => sans-serif
unquote(sans-serif)
// => sans-serif
unquote('1px / 2px')
// => 1px / 2pxs(fmt, …)
s()方法类似于unquote(),不过后者返回的是Literal节点,而这里起接受一个格式化的字符串,非常像 C 语言的sprintf(). 目前,唯一标识符是%s.
s('bar()');
// => bar()
s('bar(%s)', 'baz');
// => bar("baz")
s('bar(%s)', baz);
// => bar(baz)
s('bar(%s)', 15px);
// => bar(15px)
s('rgba(%s, %s, %s, 0.5)', 255, 100, 50);
// => rgba(255, 100, 50, 0.5)
s('bar(%Z)', 15px);
// => bar(%Z)
s('bar(%s, %s)', 15px);
// => bar(15px, null)为表现一致检测这个%字符串操作符。
operate(op, left, right)
在left和right操作对象上执行给定的op.
op = '+'
operate(op, 15, 5)
// => 20length([expr])
括号表达式扮演元组,length()方法返回该表达式的长度。
length((1 2 3 4))
// => 4
length((1 2))
// => 2
length((1))
// => 1
length(())
// => 0
length(1 2 3)
// => 3
length(1)
// => 1
length()
// => 0warn(msg)
使用给定的error警告,并不退出。
warn("oh noes!")error(msg)
伴随着给定的错误msg退出。
add(a, b)
unless a is a 'unit' and b is a 'unit'
error('add() expects units')
a + blast(expr)
返回给定expr的最后一个值。
nums = 1 2 3
last(nums)
last(1 2 3)
// => 3
list = (one 1) (two 2) (three 3)
last(list)
// => (three 3)p(expr)
检查给定的expr.
fonts = Arial, sans-serif
p('test')
p(123)
p((1 2 3))
p(fonts)
p(#fff)
p(rgba(0,0,0,0.2))
add(a, b)
a + b
p(add)标准输出:
inspect: "test"
inspect: 123
inspect: 1 2 3
inspect: Arial, sans-serif
inspect: #fff
inspect: rgba(0,0,0,0.2)
inspect: add(a, b)opposite-position(positions)
返回给定positions相反内容。
opposite-position(right)
// => left
opposite-position(top left)
// => bottom right
opposite-position('top' 'left')
// => bottom rightimage-size(path)
返回指定path图片的width和height. 向上查找路径的方法和@import一样,paths设置的时候改变。
width(img)
return image-size(img)[0]
height(img)
return image-size(img)[1]
image-size('tux.png')
// => 405px 250px
image-size('tux.png')[0] == width('tux.png')
// => trueadd-property(name, expr)
使用给定的expr为最近的块域添加属性name。
例如:
something()
add-property('bar', 1 2 3)
s('bar')
body
foo: something()真实面目:
body {
bar: 1 2 3;
foo: bar;
}接下来,“神奇”的current-property局部变量将大放异彩,这个变量自动提供给函数体,且包含当前属性名和值的表达式。
例如,我们使用p()检查这个局部变量,我们可以得到:
p(current-property)
// => "foo" (foo __CALL__ bar baz)
p(current-property[0])
// => "foo"
p(current-property[1])
// => foo __CALL__ bar baz使用current-property我们可以让例子走得更远点,使用新值复制该属性,且确保功能的条件仅在属性值中使用。
something(n)
if current-property
add-property(current-property[0], s('-webkit-something(%s)', n))
add-property(current-property[0], s('-moz-something(%s)', n))
s('something(%s)', n)
else
error('something() must be used within a property')
body {
foo: something(15px) bar;
}生成为:
body {
foo: -webkit-something(15px);
foo: -moz-something(15px);
foo: something(15px) bar;
}如果你注意上面这个例子,会发现bar只在一开始调用的时候出现,因为我们返回something(15px), 其仍留在表达式里,然而,其他人并不重视其余的表达式。
更强大的解决方案如下,定义一个名为replace()的函数,其克隆表达式,以防止出现变化,用另外一个替换表达式的字符串值,并返回克隆的表达式。然后我们继续在表达式中替换__CALL__,表示循环调用something().
replace(expr, str, val)
expr = clone(expr)
for e, i in expr
if str == e
expr[i] = val
expr
something(n)
if current-property
val = current-property[1]
webkit = replace(val, '__CALL__', s('-webkit-something(%s)', n))
moz = replace(val, '__CALL__', s('-moz-something(%s)', n))
add-property(current-property[0], webkit)
add-property(current-property[0], moz)
s('something(%s)', n)
else
error('something() 必须在属性中使用')生成:
body {
foo: foo -webkit-something(5px) bar baz;
foo: foo -moz-something(5px) bar baz;
foo: foo something(5px) bar baz;
}无论是内部调用的使用还是调用的位置上,我们实现的方法现在是完全透明的了。这个强大概念有助于在一些私有属性使用时调用,例如渐变。
未定义方法
未定义方法一字面量形式输出。例如,我们可以在 CSS 中调用rgba-stop(50%, #fff), 其会按照你所期望的显示,我们也可以使用这些内部助手。
下面这个例子中我们简单定义了方法stop(), 其返回了字面上rgba-stop()调用。
stop(pos, rgba)
rgba-stop(pos, rgba)
stop(50%, orange)
// => rgba-stop(50%, #ffa500)其余参数(Rest Params)
其余参数
Stylus 支持name...形式的其余参数。这些参数可以消化传递给混写或函数的参数们。这在处理浏览器私有属性,如-moz或-webkit的时候很管用。
下面这个例子中,所有的参数们(1px, 2px, ...)都被一个args参数给简单消化了:
box-shadow(args...)
-webkit-box-shadow args
-moz-box-shadow args
box-shadow args
#login
box-shadow 1px 2px 5px #eee生成为:
#login {
-webkit-box-shadow: 1px 2px 5px #eee;
-moz-box-shadow: 1px 2px 5px #eee;
box-shadow: 1px 2px 5px #eee;
}我们想指定特定的参数,如x-offset,我们可以使用args[0], 或者,我们可能希望重新定义混入。
box-shadow(offset-x, args...)
got-offset-x offset-x
-webkit-box-shadow offset-x args
-moz-box-shadow offset-x args
box-shadow offset-x args
#login
box-shadow 1px 2px 5px #eee生成为:
#login {
got-offset-x: 1px;
-webkit-box-shadow: 1px 2px 5px #eee;
-moz-box-shadow: 1px 2px 5px #eee;
box-shadow: 1px 2px 5px #eee;
}参数们
arguments变量可以实现表达式的精确传递,包括逗号等等。这可以弥补args...参数的一些不足,见下面的例子:
box-shadow(args...)
-webkit-box-shadow args
-moz-box-shadow args
box-shadow args
#login
box-shadow #ddd 1px 1px, #eee 2px 2px结果并非称心如意:
#login {
-webkit-box-shadow: #ddd 1px 1px #eee 2px 2px;
-moz-box-shadow: #ddd 1px 1px #eee 2px 2px;
box-shadow: #ddd 1px 1px #eee 2px 2px;
}逗号给忽略了。我们现在使用arguments重新定义这个混合书写。
box-shadow()
-webkit-box-shadow arguments
-moz-box-shadow arguments
box-shadow arguments
body
box-shadow #ddd 1px 1px, #eee 2px 2px于是,一下子雨过天晴了:
body {
-webkit-box-shadow: #ddd 1px 1px, #eee 2px 2px;
-moz-box-shadow: #ddd 1px 1px, #eee 2px 2px;
box-shadow: #ddd 1px 1px, #eee 2px 2px;
}注释(Comments)
注释
Stylus 支持三种注释,单行注释,多行注释,以及多行缓冲注释。
单行注释
跟 JavaScript 一样,双斜杠,CSS 中不输出。
// 我是注释!
body
padding 5px // 蛋疼的padding多行注释
多行注释看起来有点像 CSS 的常规注释。然而,它们只有在compress选项未启用的时候才会被输出。
/*
* 给定数值合体
*/
add(a, b)
a + b多行缓冲注释
跟多行注释类似,不同之处在于开始的时候,这里是/*!. 这个相当于告诉 Stylus 压缩的时候这段无视直接输出。
/*!
* 给定数值合体
*/
add(a, b)
a + b条件(Conditionals)
条件
条件提供了语言的刘控制,否则就是纯粹的静态语言。提供的条件有导入、混入、函数以及更多。下面的例子纯粹示例,并不是使用建议。
if / else if / else
这没什么好说的,跟一般的语言一致,if表达式满足(true)的时候执行后面语句块,否则,继续后面的else if或else.
下面这个例子,根据 overload 的条件,决定是使用padding还是margin.
overload-padding = true
if overload-padding
padding(y, x)
margin y x
body
padding 5px 10px另外的例子:
box(x, y, margin = false)
padding y x
if margin
margin y x
body
box(5px, 10px, true)另外的box()帮手:
box(x, y, margin-only = false)
if margin-only
margin y x
else
padding y x除非(unless)
熟悉 Ruby 程序语言的用户应该都知道unless条件,其基本上与if相反,本质上是(!(expr)).
下面这个例子中,如果disable-padding-override是undefined或false, padding将被干掉,显示margin代替之。但是,如果是true, padding将会如期继续输出padding 5px 10px.
disable-padding-override = true
unless disable-padding-override is defined and disable-padding-override
padding(x, y)
margin y x
body
padding 5px 10px后缀条件
Stylus 支持后缀条件,这就意味着if和unless可以当作操作符;当右边表达式为真的时候执行左边的操作对象。
例如,我们定义negative()来执行一些基本的检查。下面我们使用块式条件:
negative(n)
unless n is a 'unit'
error('无效数值')
if n < 0
yes
else
no接下来,我们利用后缀条件让我们的方法简洁。
negative(n)
error('无效数值') unless n is a 'unit'
return yes if n < 0
no当然,我们可以更进一步。如这个n < 0 ? yes : no可以用布尔代替:n < 0.
后缀条件适用于大多数的单行语句。如,@import, @charset, 混合书写等。当然,下面所示的属性也是可以的:
pad(types = margin padding, n = 5px)
padding unit(n, px) if padding in types
margin unit(n, px) if margin in types
body
pad()
body
pad(margin)
body
apply-mixins = true
pad(padding, 10) if apply-mixins生成为:
body {
padding: 5px;
margin: 5px;
}
body {
margin: 5px;
}
body {
padding: 10px;
}迭代(Iteration)
迭代
Stylus 允许你通过for/in对表达式进行迭代形式如下:
for <val-name> [, <key-name>] in <expression>例如:
body
for num in 1 2 3
foo num生成:
body {
foo: 1;
foo: 2;
foo: 3;
}下面这个例子演示了如何使用<key-name>:
body
fonts = Impact Arial sans-serif
for font, i in fonts
foo i font生成为:
body {
foo: 0 Impact;
foo: 1 Arial;
foo: 2 sans-serif;
}混合书写(Mixins)
我们可以在混写中使用循环实现更强大的功能,例如,我们可以把表达式对作为使用插值和循环的属性。
下面,我们定义apply(), 利用所有的arguments,这样逗号分隔以及表达式列表都会支持。
apply(props)
props = arguments if length(arguments) > 1
for prop in props
{prop[0]} prop[1]
body
apply(one 1, two 2, three 3)
body
list = (one 1) (two 2) (three 3)
apply(list)函数(Functions)
Stylus 函数同样可以包含 for 循环。下面就是简单使用示例:
求和:
sum(nums)
sum = 0
for n in nums
sum += n
sum(1 2 3)
// => 6连接:
join(delim, args)
buf = ''
for arg, index in args
if index
buf += delim + arg
else
buf += arg
join(', ', foo bar baz)
// => "foo, bar, baz"后缀(Postfix)
就跟if/unless可以利用后面语句一样,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我们也可以从循环返回,下例子就是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导入(@import)
导入
Stylus 支持字面@import CSS, 也支持其他 Stylus 样式的动态导入。
字面 CSS
任何.css扩展的文件名将作为字面量。例如:
@import "reset.css"渲染如下:
@import "reset.css"Stylus 导入
当使用@import 没有.css扩展,会被认为是 Stylus 片段(如:@import "mixins/border-radius")。
@import 工作原理为:遍历目录队列,并检查任意目录中是否有该文件(类似 node 的require.paths)。该队列默认为单一路径,从filename选项的dirname衍生而来。 因此,如果你的文件名是/tmp/testing/stylus/main.styl,导入将显现为/tmp/testing/stylus/。
@import 也支持索引形式。这意味着当你@import blueprint, 则会理解成blueprint.styl或blueprint/index.styl. 对于库而言,这很有用,既可以展示所有特征与功能,同时又能导入特征子集。
如下很常见的库结构:
./tablet
|-- index.styl
|-- vendor.styl
|-- buttons.styl
|-- images.styl下面这个例子中,我们设置paths选项用来为 Stylus 提供额外路径。在./test.styl中,我们可以@import "mixins/border-radius"或@import "border-radius"(因为./mixins 暴露给了 Stylus)。
/**
* 依赖模块
*/
var stylus = require('../')
, str = require('fs').readFileSync(__dirname + '/test.styl', 'utf8');
var paths = [
__dirname
, __dirname + '/mixins'
];
stylus(str)
.set('filename', __dirname + '/test.styl')
.set('paths', paths)
.render(function(err, css){
if (err) throw err;
console.log(css);
});JavaScript 导入 API
当使用.import(path)方法,这些导入是被推迟的,直到赋值。
var stylus = require('../')
, str = require('fs').readFileSync(__dirname + '/test.styl', 'utf8');
stylus(str)
.set('filename', __dirname + '/test.styl')
.import('mixins/vendor')
.render(function(err, css){
if (err) throw err;
console.log(css);
});下面语句:
@import 'mixins/vendor'等同于:
.import('mixins/vendor')媒体(@media)
@media工作原理和在常规 CSS 中一样,但是,要使用 Stylus 的块状符号。
@media print
#header
#footer
display none生成为:
@media print {
#header,
#footer {
display: none;
}
}自定义字体(@font-face)
@font-face跟其在 CSS 中作用表现一样,在后面简单地添加个块状属性即可,类似下面:
@font-face
font-family Geo
font-style normal
src url(fonts/geo_sans_light/GensansLight.ttf)
.ingeo
font-family Geo生成为:
@font-face {
font-family: Geo;
font-style: normal;
src: url("fonts/geo_sans_light/GensansLight.ttf");
}
.ingeo {
font-family: Geo;
}关键帧(@keyframes)
@keyframes
Stylus 支持@keyframes规则,当编译的时候转换成@-webkit-keyframes:
@keyframes pulse
0%
background-color red
opacity 1.0
-webkit-transform scale(1.0) rotate(0deg)
33%
background-color blue
opacity 0.75
-webkit-transform scale(1.1) rotate(-5deg)
67%
background-color green
opacity 0.5
-webkit-transform scale(1.1) rotate(5deg)
100%
background-color red
opacity 1.0
-webkit-transform scale(1.0) rotate(0deg)生成为:
@-webkit-keyframes pulse {
0% {
background-color: red;
opacity: 1;
-webkit-transform: scale(1) rotate(0deg);
}
33% {
background-color: blue;
opacity: 0.75;
-webkit-transform: scale(1.1) rotate(-5deg);
}
67% {
background-color: green;
opacity: 0.5;
-webkit-transform: scale(1.1) rotate(5deg);
}
100% {
background-color: red;
opacity: 1;
-webkit-transform: scale(1) rotate(0deg);
}
}扩展
使用@keyframes,通过vendors变量,会自动添加私有前缀(webkit moz official)。这意味着你可以子啊任意时候立即高效地做修改。
考虑下面的例子:
@keyframes foo {
from {
color: black
}
to {
color: white
}
}扩增两个默认前缀,官方解析:
@-moz-keyframes foo {
0% {
color: #000;
}
100% {
color: #fff;
}
}
@-webkit-keyframes foo {
0% {
color: #000;
}
100% {
color: #fff;
}
}
@keyframes foo {
0% {
color: #000;
}
100% {
color: #fff;
}
}如果我们只想有标准解析,很简单,修改vendors:
vendors = official
@keyframes foo {
from {
color: black
}
to {
color: white
}
}生成为:
@keyframes foo {
0% {
color: #000;
}
100% {
color: #fff;
}
}继承(@extend)
继承
Stylus 的@extend 指令受SASS 实现的启发,基本一致,除了些轻微差异。此功能大大简化了继承其他语义规则集的语义规则集的维护。
混合书写下的“继承”
尽管你可以使用混写实现类似效果,但会导致重复的 CSS. 典型的模式式定义如下的几个类名,然后归结到一个元素中,例如"warning message".
该技术实现是没什么问题,但是维护就比较麻烦了。
message,
.warning {
padding: 10px;
border: 1px solid #eee;
}
.warning {
color: #E2E21E;
}使用**@extend**
使用__@extend__得到同样的输出,只要把对应的选择器传给@extend即可。然后.warning选择器就会继承已经存在的.message规则。
.message {
padding: 10px;
border: 1px solid #eee;
}
.warning {
@extend .message;
color: #E2E21E;
}这儿是个更复杂的例子,演示了__@extend__如何级联。
red = #E33E1E
yellow = #E2E21E
.message
padding: 10px
font: 14px Helvetica
border: 1px solid #eee
.warning
@extends .message
border-color: yellow
background: yellow + 70%
.error
@extends .message
border-color: red
background: red + 70%
.fatal
@extends .error
font-weight: bold
color: red生成 CSS 如下:
.message,
.warning,
.error,
.fatal {
padding: 10px;
font: 14px Helvetica;
border: 1px solid #eee;
}
.warning {
border-color: #e2e21e;
background: #f6f6bc;
}
.error,
.fatal {
border-color: #e33e1e;
background: #f7c5bc;
}
.fatal {
font-weight: bold;
color: #e33e1e;
}目前 Stylus 与 SASS 不同之处在于 SASS 不允许__@extend__嵌套选择器。
form
button
padding: 10px
a.button
@extend form button
Syntax error: Can't extend form button: can't extend nested selectors
// 解析错误: 无法继承自 button: 不能继承嵌套选择器
on line 6 of standard input
Use --trace for backtrace.Stylus 中,只要选择器匹配,就可以生效:
form
input[type=text]
padding: 5px
border: 1px solid #eee
color: #ddd
textarea
@extends form input[type=text]
padding: 10px生成:
form input[type=text],
form textarea {
padding: 5px;
border: 1px solid #eee;
color: #ddd;
}
textarea {
padding: 10px;
}函数之 url()
内联 Data URI 图像
Stylus 捆绑了一个可选函数,名叫url(),其替换了字面上的url()调用(且使用 base64 Data URIs有条件地内联它们)。
示例
通过require('stylus').url该函数本身是可用的,其接受一个options对象,当看到url()时候,返回 Stylus 内部调用的函数。
.define(name, callback)方法指定了一个可被调用的 JavaScript 函数。在这种情况下,因为我们图片在./css/images中,我们可以忽视paths选项(默认情况下,会查找相关要呈现的图像文件)。如果愿意,该行为时可以改变的。
stylus(str)
.set('filename', __dirname + '/css/test.styl')
.define('url', stylus.url())
.render(function(err, css){
});例如,想象图片在./public/images, 我们想要使用url(images/tobi.png), 我们可以传递paths公共目录。这样,它就成为了向上查找进程的一部分。
同样,如果我们想替换为url(tobi.png), 我们可以传递paths: [__dirname + '/public/images'].
stylus(str)
.set('filename', __dirname + '/css/test.styl')
.define('url', stylus.url({ paths: [__dirname + '/public'] }))
.render(function(err, css){
});选项(Options)
limit大小默认限制 30Kb(30000)paths图像解析路径
CSS 字面量(CSS Literal)
字面量 CSS
不管什么原因,如果遇到 Stylus 搞不定的特殊需求,你可以使用@css使其作为 CSS 字面量解决之。
@css {
body {
font: 14px;
}
}编译为:
body {
font: 14px;
}CSS 样式解析(CSS Style Syntax)
CSS 样式
Stylus 完全支持常规的 CSS 样式解析,这意味着你无需寻求其它解析器,或指定特别的文件使用特别的样式。
例子
下面是个使用缩进方法的小样式:
border-radius()
-webkit-border-radius arguments
-moz-border-radius arguments
border-radius arguments
body a
font 12px/1.4 "Lucida Grande", Arial, sans-serif
background black
color #ccc
form input
padding 5px
border 1px solid
border-radius 5px因为括号,冒号及分号都是可选的,因此上面的例子我们可以按照正常的 CSS 书写:
border-radius() {
-webkit-border-radius: arguments;
-moz-border-radius: arguments;
border-radius: arguments;
}
body a {
font: 12px/1.4 "Lucida Grande", Arial, sans-serif;
background: black;
color: #ccc;
}
form input {
padding: 5px;
border: 1px solid;
border-radius: 5px;
}因为我们可以混合和匹配的两个变体,因此下面也是有效的:
border-radius()
-webkit-border-radius: arguments;
-moz-border-radius: arguments;
border-radius: arguments;
body a {
font: 12px/1.4 "Lucida Grande", Arial, sans-serif;
background: black;
color: #ccc;
}
form input
padding: 5px;
border: 1px solid;
border-radius: 5px;Stylus 支持的变量,函数,混写以及其他特征也可以使之按预期工作:
main-color = white
main-hover-color = black
body a {
color: main-color;
&:hover { color: main-hover-color; }
}
body a { color: main-color; &:hover { color: main-hover-color; }}此规则有一些注意事项:因为这两种风格可以混合和匹配,一些缩进规则仍然适用。所以,虽然不是每一个普通的 CSS 样式零修改都起作用,此功能仍然允许那些喜欢 CSS 语法的同学们继续这样做,同时又可以利用 Stylus 的强大功能。
字符转码(Char Escaping)
转码
Stylus 可以字符转码。这可以让字符变成标识符,或是渲染成字面量。
例如:
body
padding 1 \+ 2编译成:
body {
padding: 1 + 2;
}注意 Stylus 中/当作为属性使用的时候需要用括号括起来:
body
font 14px/1.4
font (14px/1.4)生成:
body {
font: 14px/1.4;
font: 10px;
}可执行性(Executable)
Stylus 可执行代码
正因有stylus可执行性,Stylus 才能将自身转换成 CSS.
Usage: stylus [options] [command] [< in [> out]]
[file|dir ...]
Commands:
help <prop> Opens help info for <prop> in
your default browser. (OS X only)
Options:
-u, --use <path> Utilize the stylus plugin at <path>
-i, --interactive Start interactive REPL
-w, --watch Watch file(s) for changes and re-compile
-o, --out <dir> Output to <dir> when passing files
-C, --css <src> [dest] Convert CSS input to stylus -I, --include <path> Add <path> to lookup paths
-c, --compress Compress CSS output
-d, --compare Display input along with output
-f, --firebug Emits debug infos in the generated css that
can be used by the FireStylus Firebug plugin
-l, --line-numbers Emits comments in the generated CSS
indicating the corresponding Stylus line
-V, --version Display the version of stylus -h, --help Display help informationSTDIO 编译范例
stylus读取自stdin输出到stdout, 因此,如下例:
$ stylus --compress < some.styl > some.css在终端机上尝试 Stylus,书写下面的内容,然后为__EOF__按下CTRL-D:
$ stylus body
color red
font 14px Arial, sans-serif编译文件范例
stylus亦接受文件和目录。例如,一个目录名为css将在同一目录编译并输出.css文件。
$ stylus css下面的将会输出到./public/stylesheets:
$ stylus css --out public/stylesheets或一些文件:
$ stylus one.styl two.styl为了开发的目的,你可以使用linenos选项发出指令在生成的 CSS 中显示 Stylus 文件名以及行数。
$ stylus --line-numbers <path>或是firebug选项,如果你想使用 firebug 的FireStylus 扩展。
$ stylus --firebug <path>转换 CSS
如果你想把 CSS 转换成简洁的 Stylus 语法,可以使用--css标志。
通过标准输入输出:
$ stylus --css < test.css > test.styl输出基本名一致的.styl文件。
$ stylus --css test.css输出特定的目标:
$ stylus --css test.css /tmp/out.stylCSS 属性的帮助
在 OS X 上,stylus help <prop>会打开你默认浏览器并显示给定的<prop>属性的帮助文档。
$ stylus help box-shadow壳层交互(Interactive Shell)
Stylus REPL (Read-Eval-Print-Loop)或“壳层交互(Interactive Shell)”允许你直接在终端机上把玩 Stylus 的表达式。
注意只有表达式可以生效,而不是选择器之类。为了简单,我们添加-i或--interactive标志:
$ stylus -i
> color = white
=> #fff
> color - rgb(200,50,0)
=> #37cdff
> color
=> #fff
> color -= rgb(200,50,0)
=> #37cdff
> color
=> #37cdff
> rgba(color, 0.5)
=> rgba(55,205,255,0.5)利用插件
本例我们将使用nibStylus 插件来说明它的 CLI 使用。
假设我们有如下的 Stylus, 其导入 nib 并使用 nib 的linear-gradient()方法:
@import 'nib'
body
background: linear-gradient(20px top, white, black)我们是使用stylus(1)通过标准输入输出试图渲染的第一个东西可能就像下面这样:
$ stylus < test.styl这可能会生成如下的错误,因为 Stylus 不知道去哪里找到 nib.
Error: stdin:3
1|
2|
> 3| @import 'nib'
4|
5| body
6| background: linear-gradient(20px top, white, black)对于简单应用 Stylus API 们的插件,我们可以添加查找路径。通过使用--include或-I标志:
$ stylus < test.styl --include ../nib/lib现在生成内容如下。您可能注意到了,gradient-data-uri()以及create-gradient-image()以字面量形式输出了。这是因为,当插件提供 JavaScript API 的时候,光暴露插件的路径是不够的。但是,如果我们仅仅想要的是纯粹 Stylus nib 函数,则足够了。
body {
background: url(gradient-data-uri(create-gradient-image(20px, top)));
background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #fff), color-stop(1, #000));
background: -webkit-linear-gradient(top, #fff 0%, #000 100%);
background: -moz-linear-gradient(top, #fff 0%, #000 100%);
background: linear-gradient(top, #fff 0%, #000 100%);
}因此,我们需要做的是使用--use或-u标志。其会找寻 node 模块(有或者没有.js扩展名)路径,这里的require()模块或调用style.use(fn())来暴露该插件(定义 js 函数等)。
$ stylus < test.styl --use ../nib/lib/nib生成为:
body {
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAUCAYAAABMDlehAAAABmJLR0QA/wD/AP+gvaeTAAAAI0lEQVQImWP4+fPnf6bPnz8zMH358oUBwkIjKJBgYGNj+w8Aphk4blt0EcMAAAAASUVORK5CYII=");
background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #fff), color-stop(1, #000));
background: -webkit-linear-gradient(top, #fff 0%, #000 100%);
background: -moz-linear-gradient(top, #fff 0%, #000 100%);
background: linear-gradient(top, #fff 0%, #000 100%);
}错误报告(Error Reporting)
错误报告
Stylus 内置梦幻般的错误报告,针对语法、解析以及计算错误,完整的堆栈跟踪,行号和文件名。
解析错误
解析错误例子:
body
form input
== padding 5px呈现为:
Error: /Users/tj/Projects/stylus/testing/test.styl:4
3: ' form input'
4: ' == padding 5px'
illegal unary ==计算错误
这种“运行”或计算错误类似于传递字符串给border-radius(),而不是单位值。
ensure(val, type)
unless val is a type
error('expected a ' + type + ', but got ' + typeof(val))
border-radius(n)
ensure(n, 'unit')
-webkit-border-radius n
-moz-border-radius n
border-radius n
body
border-radius '5px'呈现为:
Error: /Users/tj/Projects/stylus/examples/error.styl:12
11: ''
12: 'body'
13: ' border-radius \'5px\''
14: ''
expected a unit, but got string
at ensure() (/Users/tj/Projects/stylus/examples/error.styl:2)
at border-radius() (/Users/tj/Projects/stylus/examples/error.styl:5)
at "body" (/Users/tj/Projects/stylus/examples/error.styl:10)连接中间件(Connect Middleware)
连接中间件
有了连接中间件,无论 Stylus 片段什么时候改变,这些片段都能够自动编译。
stylus.middleware(options)
选项
返回给定options下的连接中间件。
`serve` Serve the stylus files from `dest` [true]
`force` Always re-compile
`src` Source directory used to find .styl files
`dest` Destination directory used to output .css files
when undefined defaults to `src`.
`compile` Custom compile function, accepting the arguments
`(str, path)`.
`compress` Whether the output .css files should be
compressed
`firebug` Emits debug infos in the generated css that can
be used by the FireStylus Firebug plugin
`linenos` Emits comments in the generated css indicating
the corresponding stylus line上面中文翻译如下:
`serve` 从 `dest` 提供stylus文件 [true]
`force` 总是重新编译
`src` 资源目录用来查找 .styl 文件
`dest` `src`默认为undefined时,用来输出 .css 文件的目标目录
`compile` 自定义编译函数,接受参数`(str, path)`.
`compress` 是否输出的 .css 文件要被压缩
`firebug` 生成的CSS中发出调试信息,可被Firebug插件FireStylus使
用
`linenos` 生成的CSS中发出注解,表明响应的stylus行例子
从./public提供.styl文件。
var app = connect();
app.middleware(__dirname + '/public');改变src以及dest项来修改.styl文件哪里被加载,哪里被保存。
var app = connect();
app.middleware({
src: __dirname + '/stylesheets',
dest: __dirname + '/public'
});这里我们建立自定义的编译函数,这样,我们就能设置compress项,或是定义附加的函数。
默认情况下,编译函数是简单地设置filename以及渲染 CSS. 在下面这个例子中,我们压缩输出内容,使用"nib"库插件,以及自动导入。
function compile(str, path) {
return stylus(str)
.set('filename', path)
.set('compress', true)
.use(nib())
.import('nib');
}作为选项传递应该像这样:
var app = connect();
app.middleware({
src: __dirname
, dest: __dirname + '/public'
, compile: compile
})自检 API(Introspection API)
自检 API
Stylus 支持自我检测的 API, 这允许混写以及函数反应调用者的相关性。
混写(mixin)
mixin这个局部变量在函数体内自动赋值。如果调用的函数在根级别,则mixin包含字符串root, 如果其他情况,则是block, 如果调用函数有返回值,最终为false.
下面这个例子中,我们定义reset(), 根据其是混入了根部,还是混入块状域,还是混入返回值中,来修改其值,并作为foo属性的值呈现:
reset()
if mixin == 'root'
got
root true
else if mixin
got 'a mixin'
else
'not a mixin'
reset()
body
reset()
foo reset()编译为:
got {
root: true;
}
body {
foo: "not a mixin";
got: "a mixin";
}JavaScript API
JavaScript API
require模块,用给定的 Stylus 代码字符串调用render(),以及(可选的)optional对象。
传递filename参数可以利用 Stylus 框架提供更好的错误报告。
var stylus = require('stylus');
stylus.render(str, { filename: 'nesting.css' }, function(err, css){
if (err) throw err;
console.log(css);
});我们可以用更渐进的方式实现做一样的事:
var stylus = require('stylus');
stylus(str)
.set('filename', 'nesting.css')
.render(function(err, css){
// logic
});.set(setting, value)
应用诸如filename的设置,或导入paths:
.set('filename', __dirname + '/test.styl')
.set('paths', [__dirname, __dirname + '/mixins']).include(path)
渐进替换.set('paths',...)的就是.include(). 当其他 Stylus 库(已暴露路径)暴露的时候,这个是理想的选择。
stylus(str)
.include(require('nib').path)
.include(process.env.HOME + '/mixins')
.render(...).import(path)
推迟给定path导入,直到计算被执行。下面这个例子基本上跟在 Stylus 片段中执行@import 'mixins/vendor'一样:
var stylus = require('../')
, str = require('fs').readFileSync(__dirname + '/test.styl', 'utf8');
stylus(str)
.set('filename', __dirname + '/test.styl')
.import('mixins/vendor')
.render(function(err, css){
if (err) throw err;
console.log(css);
});.define(name, node)
通过传递一个Node,我们可以定义一个全局变量。当库(该库依赖于其它库可用性)里面暴露某些条件特征的时候,这个就很有用。例如 Nib 扩展库条件支持 node-canvas, 提供图片生成。
但这并不是一直可用的,因此 Nib 可以定义:
.define('has-canvas', stylus.nodes.false);
.define('some-setting', new stylus.nodes.String('some value'));如果可能,Stylus 也会转换 JavaScript 值为 Stylus 值。
.define('string', 'some string')
.define('number', 15.5)
.define('some-bool', true)
.define('list', [1,2,3])
.define('list', [1,2,[3,4,[5,6]]])
.define('list', { foo: 'bar', bar: 'baz' })
.define('families', ['Helvetica Neue', 'Helvetica', 'sans-serif'])下面是一些规则应用在 js 函数返回值上:
.define('get-list', function(){
return ['foo', 'bar', 'baz'];
}).define(name, fn)
该方法允许你未 Stylus 提供 JavaScript 定义的函数。正如想到 JavaScript 用 C++绑定。当有一些事情无法用 Stylus 完成的时候,就在 JavaScript 中定义它。
下面这个例子,我们定义了 4 个函数:add(), sub(), image-width(), image-height(). 这些函数必须返回一个Node, 通过stylus.nodes该构造以及其它 nodes 都可以了。
var stylus = require('../')
, nodes = stylus.nodes
, utils = stylus.utils
, fs = require('fs');
function add(a, b) {
return a.operate('+', b);
}
function sub(a, b) {
return a.operate('-', b);
}
function imageDimensions(img) {
// 宣告 node (img) 是一个 String 节点,
// 为错误报告传递参数名
utils.assertType(img, 'string', 'img');
var path = img.val;
// 得到尺寸有必要取得字节数
// 如果这是真的,你会每种格式都处理下,
// 而不是读取整个图片 :)
var data = fs.readFileSync(__dirname + '/' + path);
// GIF
// 当然,你可以支持更多 :)
if ('GIF' == data.slice(0, 3).toString()) {
var w = data.slice(6, 8)
, h = data.slice(8, 10);
w = w[1] << 8 | w[0];
h = h[1] << 8 | h[0];
}
return [w, h];
}
function imageWidth(img) {
return new nodes.Unit(imageDimensions(img)[0]);
}
function imageHeight(img) {
return new nodes.Unit(imageDimensions(img)[1]);
}
stylus(str)
.set('filename', 'js-functions.styl')
.define('add', add)
.define('sub', sub)
.define('image-width', imageWidth)
.define('image-height', imageHeight)
.render(function(err, css){
if (err) throw err;
console.log(css);
});为了进一步的参考(直到本文档全部结束),请看下面的文件:
lib/nodes/*lib/utils.js
.use(fn)
当被调用时,给定fn被渲染器调用,允许所有上面的方法被使用。这允许插件轻易地暴露自己,定义函数,路径等。
var mylib = function(style){
style.define('add', add);
style.define('sub', sub);
};
stylus(str)
.use(mylib)
.render(...)文档来源: 张鑫旭-stylus 文档