Stylus介绍及特点

基于Node.js的css的预处理框架,其本质上做的事情与 Sass/LESS 等类似, 可以以近似脚本的方式去写CSS代码,创建健壮的、动态的、富有表现力的CSS,默认使用 .styl 的作为文件扩展名,支持多样性的CSS语法。Stylus比LESS更强大,而且基于nodejs比Sass更符合我们的思路。

Stylus的特点如下

  • 基于js

Node.js是一个Javascript运行环境(runtime),是对Google V8引擎进行了封装,V8引擎执行Javascript的速度非常快,性能非常好。对于不了解Node.js的开发人员,不会增加太多学习成本。Stylus基于Node.js,换而言之,就是借助JavaScript让CSS更富有表现力,更动态,更健壮!而且还有专门的JavaScript API。

  • 支持Ruby之类框架

虽然Stylus基于Node.js,但是依然支持Ruby之类框架,还有FireBug插件FireStylus, sublimetext插件,便于开发、调试。

  • 功能强大,使用灵活,支持多样性的CSS语法

Stylus的功能比LESS强大,不逊于Sass。在用法上,支持传统的CSS,而且相对于传统的用法,更加简洁、灵活,像省掉花括号、冒号,分号,甚至使用混合的CSS编程,Stylus都可以接受。

Stylus的优缺点

【优点】

解决样式覆写的问题,尤其是mixin式复用

使用纯CSS,我们可以抽象出一些常用的布局CSS属性组合,通过CSS的类组合来达成常见的mixin式复用,然而这种方案存在一些问题,例如:

当页面重构时,需要频繁修改class name,这个问题在后端人员掌握着视图层的时候格外突出,前后端耗费很多沟通成本;

在约束上下文的时候非常无力,比如“只有在ul下面的img.db允许是display:block”的规则,写成“ul img.db { display: block; }”就完全跑偏了,它违背了创建这个.db类时的本意,造成了代码的可读性和可维护性下降。

如果你要改动规则,需要同时修改HTML和CSS,也可能造成新的样式问题。

而通过Stylus可以建立一种新的代码风格,只允许CSS Class代表UI模块的抽象,这样一来,改动样式时不至于通知后端改模板,然后在CSS Class内部实现mixin。而这正是CSS的短板,CSS体系内的用法只有复制粘贴。

可缓解多浏览器兼容造成的冗余

进入CSS3的时代,旧式CSS hack如filter,新式兼容前缀如-webkit-等,都是冗余,修改的时候也需要修改多处,不容易维护。在Stylus里面,写个函数就能解决,多次复用也不需要看到如此之多的hack。

提高效率,节约成本

用Stylus开发CSS可以提高效率,它类似于一种CSS的方言,可以用更精简的语法表达更多的意思。比如,Stylus中可以使用变量,比如和 UED 同学订好各种样式的规范,做好变量后开发中直接使用,避免页面中的各种杂乱样式。当样式需求有变动时,也可以重新给变量赋值,一下改掉相关样式,不用再一点一点的改。

使CSS开发更加灵活

Stylus可以使用变量、条件、循环,兼容传统的CSS样式,等等,可以让CSS的开发和修改更加灵活。

【缺点】

开发过程增加步骤

CSS的好处在于简便、随时随地被使用和调试,使用Stylus,增加了预编译CSS的步骤,让我们开发工作流中多了一个环节,调试也多了个步骤。

增加学习成本。

虽然Stylus简单易学,可以兼容传统CSS,但是当开发和维护团队都从CSS过渡到Stylus时,还是需要一点学习成本的,而且初学者使用起来,不一定能明显提高效率。

语法:

1. 选择器

Stylus就跟CSS一样,允许你使用逗号为多个选择器同时定义属性。

textarea, input
border 1px solid #eee
使用新行是一样的效果: textarea
input
border 1px solid #eee
等同于: textarea,
input {
border: 1px solid #eee;
}
父级引用

字符&指向父选择器。下面这个例子,我们两个选择器(textareainput)在:hover伪类选择器上都改变了color

textarea
input
color #A7A7A7
&:hover
color #000
等同于:
textarea,
input {
color: #a7a7a7;
}
textarea:hover,
input:hover {
color: #000;
}
消除歧义

类似padding - n的表达式可能既被解释成减法运算,也可能被释义成一元负号属性。为了避免这种歧义,用括号包裹表达式:

pad(n)
padding (- n) body
pad(5px)

编译为:

body {
padding: -5px;
}

然而,只有在函数中才会这样(因为函数同时用返回值扮演混合或回调)。

有Stylus无法处理的属性值?unquote()可以帮你:

filter unquote('progid:DXImageTransform.Microsoft.BasicImage(rotation=1)')
生成为:
filter progid:DXImageTransform.Microsoft.BasicImage(rotation=1)

2.变量

我们可以指定表达式为变量,然后在我们的样式中贯穿使用:

font-size = 14px

body
font font-size Arial, sans-seri

变量甚至可以组成一个表达式列表:

font-size = 14px
font = font-size "Lucida Grande", Arial body
font font sans-serif 编译为: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)

3. 插值

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;
}

4.运算符

运算符优先级:从最高到最低

[]
! ~ + -
is defined
** * / %
+ -
... ..
<= >= < >
in
== is != is not isnt
is a
&& and || or
?:
= := ?= += -= *= /= %=
not
if unless

一元运算符, !,not, -, +,以及~

-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)

范围..  ...

同时提供包含界线操作符(..)和范围操作符(...),见下表达式:

1..5
// => 1 2 3 4 5 1...5
// => 1 2 3 4

加减乘除余 + - * / %  :二元加乘运算其单位会转化,或使用默认字面量值。例如,5s - 2px结果是3s

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);
只有/操作符的时候需要这样。

指数:**

相等与关系运算:== != >= <= > <

相等运算符可以被用来等同单位、颜色、字符串甚至标识符。这是个强大的概念,甚至任意的标识符(例如wahoo)可以作为原子般使用。函数可以返回yesno代替truefalse(虽然不建议)。

别名:

==    is
!= is not
!= isnt
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 == falsenull == false均返回false.

真与假

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。它们优先级相同。

存在操作符:in

检查左边内容是否在右边的表达式中。

元组同样适用:

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   用来检查变量是否已经分配了值。

该操作符必不可少,因为一个未定义的标识符仍是真值,如:

body
if ohnoes
padding 5px
当未定义的时候,产生的是下面的CSS: body {
padding: 5px;
}
显然,这不是我们想要的,如下书写就安全了: body
if ohnoes is defined
padding 5px

三元

num = 15
num ? unit(num, 'px') : 20px
// => 15px

5.混合书写(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;
}

我们可以利用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)创建一个条纹表格。evenodd均提供了默认颜色值,每行也指定了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;
}

stylus笔记的更多相关文章

  1. 学习stylus笔记

    最近在研究v-cli3.0,发现了一种新的预处理器,于是花了一些时间去学习下. 学习网站 基本上这个网站上,讲的已经很详情.我下面把我在学习之中的笔记和觉得自己用的多方法贴出来. 1.缩排 使用缩排和 ...

  2. stylus笔记(三)

    1.@import 导入 Stylus支持字面@import CSS, 也支持其他Stylus样式的动态导入. 任何.css扩展的文件名将作为字面量.例如: @import "reset.c ...

  3. stylus笔记(二)

    1.方法 函数  Stylus强大之处就在于其内置的语言函数定义.其定义与混入(mixins)一致:却可以返回值. 默认参数 可选参数往往有个默认的给定表达.在Stylus中,我们甚至可以超越默认参数 ...

  4. stylus入门学习笔记

    title: stylus入门学习笔记 date: 2018-09-06 17:35:28 tags: [stylus] description: 学习到 vue, 有人推荐使用 stylus 这个 ...

  5. 笔记:使用 stylus stylus-loader

    笔记:使用 stylus stylus-loader 安装 stylus Stylus-loader cnpm i stylus stylus-loader --save 配置 webpack.con ...

  6. 前端学习笔记系列一:10整体移动vscode代码块、VSCode 使用 stylus,配置格式化设置、在vue项目中引入bootstrap

    1.整体移动vscode代码块 凭借操作的经验我们能够轻松地知道将代码整体往右移只需选中代码按Tab键即可.其实往左移也很简单: 选中之后按下 shift+Tab键 即可. 2.VSCode 使用 s ...

  7. 前端学习笔记系列一:6 一种新的css预编译器stylus

    stylus是 CSS 的预处理框架.CSS 预处理,顾名思义,预先处理 CSS.那 stylus 咋预先处理呢?stylus 给 CSS 添加了可编程的特性,也就是说,在 stylus 中可以使用变 ...

  8. CSS预处理器Sass(Scss)、Less、Stylus

    CSS 预处理编译器能让我成程序化其的方式编写CSS代码,可以引入CSS中没有的变量.条件.函数等特性,从而让代码更简单易维护,但一般按预处理器语法编写的代码无法直接在浏览器中运行,需用通过工具比如g ...

  9. font-spider-plus,字体压缩插件使用笔记

    font-spider-plus使用笔记, fsp是一个腾讯的大佬改版后的font-soider 主要思路是 采集线上网页使用到的字体,从字体文件中分离出来,完成大幅度压缩, 1,npm i font ...

随机推荐

  1. Mysql的唯一性索引unique

    目录 唯一性索引unique影响: unique与primary key的区别: 存在唯一键冲突时,避免策略: insert ignore: replace into: insert on dupli ...

  2. FileAttributes Enum

    https://docs.microsoft.com/en-us/dotnet/api/system.io.fileattributes?view=netframework-4.7.2 读取FileA ...

  3. lamp服务器被人恶意绑定域名的解决办法

    还没开始就被别人绑定了域名 事情的起因与发现 刚买了个服务器搭建了一个dz,想着域名还没备案,就先搭建了起来,然后在做DDOS测试时偶然发现服务器被别人恶意把域名绑定了 最初的解决方案 没管..... ...

  4. html 之 区块元素属性(待补充)

    区块标签:(会随着父类的宽度变化而变化) p,div 等(后续补充) 区块标签才能使用以下属性() width,height,min-height,max-height,min-width,max-h ...

  5. C# winform程序防止前台卡死

    https://blog.csdn.net/Emiedon/article/details/51069193 在实际开发中,如果需要实时的显示后台处理的情况,我们可能要在前台用一些控件去显示 所以我们 ...

  6. 深度学习课程笔记(一)CNN 卷积神经网络

    深度学习课程笔记(一)CNN 解析篇 相关资料来自:http://speech.ee.ntu.edu.tw/~tlkagk/courses_ML17_2.html 首先提到 Why CNN for I ...

  7. HDU 5445 Food Problem(多重背包+二进制优化)

    http://acm.hdu.edu.cn/showproblem.php?pid=5445 题意:现在你要为运动会提供食物,总共需要提供P能量的食物,现在有n种食物,每种食物能提供 t 能量,体积为 ...

  8. 聚类算法——KMEANS算法

    聚类概念 无监督问题:我们手里没有标签 聚类:相似的东西分到一组 难点:如何评估,如何调参 基本概念 要得到簇的个数,需要指定K值 质心:均值,即向量各维取平均即可 距离的度量:常用欧几里得距离和余弦 ...

  9. IOS学习笔记一1

    //创建.h文件 界面的类文件(创建一个类) @interface MyClass:NSObject{ //类变量声明 int a; int b; } //类属性声明 (int) p2 //类方法声明 ...

  10. 理解 Redis(1) - Redis 简介

    Redis 的含义 全称: REmote DIctionary Server 远程词典服务器 由于支持 string, list, set, ordered set, hash 等多重数据结构, 因此 ...