CSS 预处理器 Stylus分享
ps:为了分享,内容东拼西凑,并非原创,很多参考了 张鑫旭大大翻译的中文文档。这里放上两个不错的stylus链接:
https://github.com/leeseean/stylus-style-guide github stylus语法规范
http://blog.hooperui.com/561-2/ 预处理器的作用ect 写的很好。。
一、简介
由于原生css有一些缺陷,
一些CSS预处理器应运而生
使用最多的是
变量(variables),代码混合( mixins),嵌套(nested rules)以及 代码模块化(Modules)。
复用,逻辑能力和抽象能力。
Stylus相较于SASS更加简洁,甚至冒号也都可以省略,初学Stylus时感到它太神奇了,仅仅以空格分隔属性名和多个属性值就可以生成想要的CSS,而且还可以拼接字符串等等。与此同时,类似Ruby或Python完善的缩进语法,Stylus在简约自由中有效的防止了语法歧义。
安装
npm install stylus --save
例子
Stylus由Javascript编译,其结构语句也和Javascript相差不多。Stylus较之LESS则要优越不少,不仅仅是可定义变量,如Javascript般的条件语句和循环语句也为Stylus带来各种可能,加上丰富的内置函数,可以轻松判断和操作各种变量。而利用这样的动态性,就可以写出非常强壮的CSS以满足不同环境和条件下的需要。
二、从语法和mixin 混合开始
1、& 指向的是父选择器。
字符&指向父选择器。下面这个例子,我们两个选择器(textarea和input)在:hover伪类选择器上都改变了color值
textarea input color #A7A7A7 &:hover color #000
等同于:
textarea, input { color: #a7a7a7; } textarea:hover, input:hover { color: #000; }
2、mixin 混合书写。混入
先来一段官方描述:如果你发现自己在不停地重复一段样式,那就应该把这段样式构造成优良的混合器,尤其是这段样式本身就是一个逻辑单元。再为其添加一个展示性的描述,能够清晰明了的看出它是用来干嘛的。
显然,你首先会想到的是需要各种浏览器厂商前缀的CSS3代码。一个好的事情是,mixin本身不会被编译到css代码中。
混入和函数定义方法一致,但是应用却大相径庭。
例如,下面有定义的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)
标红括号可以省略。。
也可以把n替换为 arguments 这样就可以传递多个值
如
border-radius 1px 2px / 3px 4px
编译成
form input[type=button] { -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; }
3、而且在调用时,也不一定要使用括号的形式,可以使用CSS的形式,直接Mixin名加空格然后写参数。所以有时候可以直接写一个Mixin来修改CSS属性的功能,比如看看下面这个兼容所有标准浏览器阴影的写法,可以很方便的为标准调用加上各标准浏览器的前缀:
下面这个例子,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;
}
可以看到调用时的写法与一般的写法一样,但是因为Mixin的存在,box-shadow不再是一个属性,可以变成几行带有各浏览器前缀的CSS。
4、插值
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; }
不仅仅是box-shadow,CSS3的许多属性都需要添加前缀~
三、响应式支持
1、变量 可以直接指定表达式的值为变量,可以给变量赋多个值可以组成一个表达式列表
你可以使用"$"符号开始。结尾的分号(;)可有可无,但变量名和变量值之间的等号(=)是需要的。不要用@ (不会赋值)
有了变量,我们不需要为了修改一个颜色而输入许多次,也不需要为了修改一个宽度去到找寻找他.(我们只需要修改定义好的变量,修改一次就足够).
font-size = 14px
font = font-size "Lucida Grande", Arial
body
font font sans-serif
编译为:
body {
font: 14px "Lucida Grande", Arial sans-serif;
}
2、Stylus有另外一个很酷的独特功能,不需要分配值给变量就可以定义引用属性。下面是个很好的例子,元素水平垂直居中对齐(典型的方法是使用百分比和margin负值),如下:
简单地前置@
字符在属性名前来访问该属性名对应的值:
#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
属性会“向上冒泡”查找堆栈直到被发现,或者返回null
(如果属性搞不定)。下面这个例子,@color
被弄成了blue
.(父元素之前定义过的blue。)
3、响应式的例子。关于数组的定义,对于响应式来说有非常好的帮助,因为响应式往往是一系列的尺寸或设备,无论如何,使用数组可以轻松的定义多组对应与索引的配套值。
$screen = 1920px 1280px 1024px 768px 640px 320px $width = 1600px 1080px 840px 600px 480px 300px $margin = 180px 100px 80px 40px 20px 0 media() join(‘ and ‘, arguments) responsive(p_index) body width $width[p_index] margin-left $margin[p_index] responsive(0) for $i in 0 1 2 3 4 5 $media = media(‘screen‘, ‘(max-width: ‘ + $screen[$i] + ‘)‘) @media $media responsive($i) // => body { width: 1600px; margin-left: 180px; } @media screen and (max-width: 1920px) { body { width: 1600px; margin-left: 180px; } } // ... @media screen and (max-width: 320px) { body { width: 300px; margin-left: 0; } }
当然响应式不是简单的改变尺寸,如果你需要控制某些内容的显示则可以使用一个Boolean的数组来判断是否显示,控制结构或样式则可以字符串的数组来放置一些预先写好的Mixin名称。
四、模块化管理、易维护
当我们在做中、大型项目的时候,往往一个功能或者模块,会在很多页面都用到,如果我们把它们单独的放到所有页面对应的代码中,那么每次修改,我们都要去改所有的代码段,这显然是低效的,如果将它们放到一个大的公共文件中,有很可能造成冗余,或许,你会说,可以放在一个单独的文件中,然后引入到页面中,就行了,这样是可以,但是会多出来一个文件的请求,如果有多个,那么从维护性和性能两方面考虑的话,就得不偿失了。所以,我们可以使用处理器中的@import规则,把复用代码段提取,然后在需要的页面引入,这样,同样能达到“一处变、处处变”的效果,而且,不会有多余的请求发出,一个页面可以只有一个css文件即可。
在CSS中,并不喜欢用@import来导入样式,因为这样的做法会增加HTTP的请求。但是在CSS预处理器中的导入(@import)规则和CSS的有所不同,它只是在语义上导入不同的文件,但最终结果是生成一个CSS文件。如果你是通过“@import ‘file.css‘”导入“file.css”样式文件,那效果跟普通CSS导入样式文件一样。注意:导入文件中定义了变量、混合等信息也将会被引入到主样式文件中,因此需要避免他们的相互冲突。
-------------------------------------------------- /* file.{type} */ body { background: #EEE; } ------------------------------------------------ @import "reset.css"; @import "file.{type}"; p { background: #0982C1; } 转译后--------------------------------------------- @import "reset.css"; body { background: #EEE; } p { background: #0982C1; }
嵌套、继承
如果我们在CSS中多个元素有一个相同的父元素,那么写样式会变得很乏味,我们需要一遍一遍的在每个元素前写这个父元素.
section { margin: 10px; } section nav { height: 25px; } section nav a { color: #0982C1; } section nav a:hover { text-decoration: underline; } 相反,使用CSS预处理器,我们可以在父元素的花括号({})写这些元素。同时可以使用“&”符号来引用父选择器。 section { margin: 10px; nav { height: 25px; a { color: #0982C1; &:hover { text-decoration: underline; } } } }
Extend 扩展继承
这可以说是处理器的一个亮点,你定义了一个类,后面如果有另一个类需要用到和已经定义了的类同样的属性和值,那么你可以通过@extend来直接引用已经定义的类,来再次使用它定义过的规则。
这样不会多出来很多重复代码段吗?可能你跟我有过同样的困惑,其实它生成的,是一个群组选择器,也就是多个类共用一段css样式规则,这样做的好处是,在你想定义有共性又有差异的一组元素时,不需要写多个类,只需要写它单独定义的类即可。
在多个元素应用相同的样式时,我们在CSS通常都是这样写:
p,
ul,
ol {
/* 样式写在这 */
}
这样做非常的好,但往往我们需要给单独元素添加另外的样式,这个时候我们就需要把其中选择器单独出来写样式,这样一回来我们维护样式就相当的麻烦。为了应对这个问题,CSS预处理器可以从一个选择继承另一个选择器下的所有样式。
.block { margin: 10px 5px; padding: 2px; } p { @extend .block; /* 继承.block所有样式 */ border: 1px solid #EEE; } ul, ol { @extend .block; /* 继承.block所有样式 */ color: #333; text-transform: uppercase; } 转译后: .block, p, ul, ol { margin: 10px 5px; padding: 2px; } p { border: 1px solid #EEE; } ul, ol { color: #333; text-transform: uppercase; }
五、图片与色彩的处理
1、切图
对于CSS Sprite相信是所有切图者的主要工作产出,以前我也推荐过一些在线的制作Sprite的工具,不过现在有了Stylus。
其中for不同于Javascript,rowList为数组遍历出的一个元素,而$row为索引,可以这样理解 `for [value], [index] in [array]` 。所以可以在两个嵌套的for中获取纵横的位置以及国家代码,来生成CSS。
作为预处理工具,Stylus自然也需要预处理器,不过它不像Sass需要Ruby环境,Stylus由Javascript实现,所以有Javascript就可以处理Stylus。
2、颜色操作
如同其他CSS预处理工具一样,Stylus在颜色方面也拥有许多内置函数,无论是判断,提取还是修改都十分强大。函数 `red` , `blue` , `green` , `alpha` 将分别返回颜色对应的rgba值,`dark` 和 `light` 用于判断颜色属于亮色还是暗色,`hue` , `saturation` , `lightness` 则分别返回颜色的色相、饱和度以及亮度,其中色相是在色环上的角度,单位是deg。我经常用的是`lighten` 和 `darken` 这两个函数,其作用是增加或减少一个颜色的亮度,另外还有饱和度的操作函数 `desaturate` 和 `satucate`。
通过增加或减少百分值调整颜色亮度。颜色亮,加;暗,则减。
我们也可以通过增加或减去色度调整色调。例如,红色增加65deg就变成了黄色。
六、运算符
1、优先级qwq
下标运算符[]
允许我们通过索引获取表达式内部值。括号表达式可以充当元组(如(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])
2、范围.. ...
同时提供包含界线操作符(..)和范围操作符(...),见下表达式:
1..5
// => 1 2 3 4 5
1...5
// => 1 2 3 4
3、存在操作符:in
检查左边内容是否在右边的表达式中。
nums = 1 2 3
1 in nums
// => true
4、条件赋值:?= :=
条件赋值操作符?=(别名?:)让我们无需破坏旧值(如果存在)定义变量。该操作符可以扩展成三元内is defined的二元操作。
color := white
color ?= white
color = color is defined ? color : white
(Is defined 是 是否分配过了值 qwq)
5、方法
函数 函数内方法 标识符 (内置 unit 都换成了px单位 就可以无视单位了)
add(a, b = a)
a = unit(a, px)
b = unit(b, px)
a + b
add(15%, 10deg)
// => 25
可能和 属性赋值 混淆 那么加个括号 或者加个return
swap(a, b)
return (b a)
条件、别名、参数、哈希等等
下面,我们定义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
七、区别(三者对比
1、变量
2、作用域
3、继承
- Sass和Stylus的继承非常像,能把一个选择器的所有样式继承到另一个选择器上。使用『@extend』开始,后面接被继承的选择器。
.test{
margin: 10px5px;
padding: 2px;
}
p{
@extend.test;/*继承.block*/
border: 1pxsolid#aaa;
}
ul,li{
@extend.test; /*继承.block*/
color: #aaa;
}
将被编译成标准 css:
.test,p,ul,ol {
margin: 10px5px;
padding:2px;
}
p {
border: 1px solid #aaa
}
ul,li {
color:#aaa;
}
- Less 继承:与前两者继承方式有所区别,它不是在选择器上继承,而是将Mixins中的样式嵌套到每个选择器里面。然而这样会带来一个明显的缺点:每个选择器中会出现重复的样式
不管什么原因,如果遇到Stylus搞不定的特殊需求,你可以使用@css使其作为CSS字面量解决之。
Less 的发展有 Bootstrap,Sass 的发展有 Compass
虽然各种预处理器功能强大,但使用最多的,还是以下特性:
变量(variables),代码混合( mixins),嵌套(nested rules)以及 代码模块化(Modules)。
原生的css 也有变量的 后来出的 常常给用来 切换背景色(主题模式)
它不需要经过任何转译步骤,因为它是浏览器原生支持的 是动态的
它是DOM 的一部分
是 - - 来命名的用两个“-”开头表示声明变量,
如:--white-color: #FFF
用var(...)引用变量值,
如:background: var(--white-color)
原文地址:https://www.cnblogs.com/lx2331/p/11888284.html