这是一篇简单短小的关于mcss快速指引的介绍,尽量以最简单的例子进行梳理,供学习参考作用。
mcss是开发者leeluolee开发的一款非常优秀的css预处理器,名气不如less响。但功能丝毫不逊色于其他预处理器。具体介绍这里不再赘述,有兴趣的去看官网。下面进入正题:
下面的样例,均可以在线编辑器里面查看效果:McssOnlineParser
概要
语法
注释
mcss支持的常规的注释 //,/**/,/***/这几种注释
变量
mcss变量声明以符号 $为起始,赋值方式三种:=, ^= , ?=
1 | // 定义&赋值 |
1 | a{ color: #333; } |
变量的三种赋值方式
三个符号差异:
- = 常规变量赋值
- ^= 全局变量赋值(mcss有scope的概念,这个后面讲)
- ?= 空变量赋值(仅在变量为‘未赋值’或‘null’时候生效)
数据类型
Mcss的数据类型除开常规的几种(string,function,boolean,null)之外,
还包含css中的一些常规类型(color,dimension,text,values,valuesList)
常规类型
- string : $fontName=’微软雅黑’;等
- color : #000,#7563fd,rgb(255,255,255),rgba(0,0,0,0.1),hls(238,251,102),hlsa(238,251,102,0.1)这几种
- dimension : 尺寸,如10px,15pt,20rem,50%等等
- text : 文本变量,有别于string
如:
1 | $dir = left; //a text var |
↓↓↓1
.demo{float: left;}
特殊类型
- values : 对应css中的组合值,如border:1px solid #ddd;里的1px solid #ddd就是一个values类型
- boolean : true | false,编程需要
- null : 空,编程需要
- valuesList : 对应一些多值的组合,一般用逗号(,)隔开,类似于数组(array)。如$arr = (1,2,3,4,5);
数组元素不受限制,可用于map等其他类似数据结构;如$map = (left 10px, top 20px, color #09c);
数组支持 begin…end 这种简写写法;
valuesList主要用于编程需要。 - function: 详见 函数
index函数获取valueslist或values中元素的值
valueslist,或values类型的数据可以通过 index(list,n)来获取 list[n]
1 | $list = 1px 2em 3pt; |
↓↓↓
1 | p{ |
mcss没有undefined这类型一说,空的就是null
嵌套
作为一个css预处理器最基本也是最常见的功能,mcss支持嵌套
1 | .farther { |
↓↓↓1
2
3.farther{font-size:40px;}
.farther .son{font-size:20px;}
.farther .son .grand-son{font-size:10px;}
使用&符号获取上层引用
1 | a{ |
↓↓↓1
2
3a{font-size:12px;}
a:hover{color:#09c;}
a:active{color:#aaa;}
这里mcss支持的选择器写法与原生css一致,+,>,~,不专属于mcss的范畴,这里就不再赘述
使用%符号获取上除最外层选择器之外的层序列
此属性在可读性和使用逻辑上来说,有一定成本,所以,嫌麻烦的同学(比如我)可以跳过%符号的使用
对于一些具有共同样式属性的选择器,我们在写css的时候,一般会倾向于书写如下的代码
例如实现 .a, .b, .c 在不同容器包围时候的显示隐藏:1
2
3
4
5
6
7
8
9
10.normal-con .a,
.normal-con .b,
.normal-con .c{
display: block;
}
.hide-con .a,
.hide-con .b,
.hide-con .c{
display: none;
}
如果序列不算多,例如本例为 a~c,书写起来还算好,但是一旦选择器序列多起来,那么如此写法不仅累,而且难以维护.
这时,我们可以采用%符号来尝试去解决这个问题
1 | .normal-con{ |
将会输出与上面一样的代码效果,但代码的‘简洁性’,‘可维护性’以及‘优雅性’,都比上面的好
百分符号使用注意点
除开最外层
输出仅仅只与其最外层的选择器无关,如果内层有其他层级嵌套的选择器出现,照样输出。比如,下面我们在normal里面再加一层.mid选择器
1
2
3
4
5
6
7
8
9
10.normal-con{
.mid{
.a, .b, .c{// 序列(.a, .b, .c)
display: block;
.hide-con %{
display: none;
}
}
}
}↓↓↓
1
2
3
4
5
6.normal-con .mid .a,.normal-con .mid .b,.normal-con .mid .c{
display:block;
}
.hide-con .mid .a,.hide-con .mid .b,.hide-con .mid .c{
display:none;
}效果看上去就像:
“将%左边的部分(.hide-con),替换最外层的选择器(.normal-con),而其他层级(如本例中的.mid层级),一切照旧”
序列
里需要说明的是,%符号指代的序列,是指代(.a,.b,.c)这个序列,而序列值,仅仅只有一个,也是允许的,此时,%有点像是“特殊的父引用”
1
2
3
4
5
6
7
8.normal-con{
.a{
display: block;
.hide-con %{
display: none;
}
}
}↓↓↓
1
2
3
4
5
6.normal-con .a{
display:block;
}
.hide-con .a{
display:none;
}
运算
mcss支持的运算
- 一元运算符: -,!,+
- 二元运算符: +,-,*,/,%
- 逻辑运算符: ||,&&
- 关系运算符: ==,>=,<=,>,<,!=
- 括号: (,)
优先级与javascript完全一致,运算结果与js有一点差异
1 | .demo{//这里css的property名写得比较随意,着重点在于value |
mcss运算的注意点
注意点:需要进行二元运算时候,符号两边最好保留空格,不然有可能原样连接输出
原因:css中,值里面是可以出现-,/,%字符的,所以为了区分是值,还是计算表达式,最好两边加上空格以表示是计算
1 | .demo{ |
逻辑
@if, @elseif, @else
1 | $screenWidth = 1200px; |
↓↓↓1
h1{font-size:16px;}
插值
interpolate插值语法与scss一致,#{$变量名}
1 | $status = z-checked; |
↓↓↓1
2
3
4
5
6.u-checkbox{
background-position:0 0;
}
.u-checkbox.z-checked{
background-position:0 -16px;
}
‘插值’操作像上面单独使用的情况不会太多,因为这种情况下作用跟直接使用变量名区别不大,而一般在函数中,逻辑,循环等中进行组合使用比较多。
这里还需要有一个概念,‘插值’并不仅是做文本替换,这里操作的是变量,即:变量的值,不仅为Text,还可以为其他的,比如下面例子中会出现的valueslist
循环
mcss的循环关键字只有一个@for,但循环功能并不单一,自由组合书写能够完成类似while,each等常见操作。
mcss的循环主要分为两种:
- @for of
- @for in
语法:
1 | @for item:VAR[, index:VAR]? ['by' step:expression]? [('of'|'in') valueslist] block |
简单型遍历for-of
常规遍历
配合插值使用时:
1 | $arr = (one,two,three);// a array |
↓↓↓1
2
3.class-one{color:#000;}
.class-two{color:#000;}
.class-three{color:#000;}
这里输出没有做选择器合并,可以考虑使用postCss等css后处理器做后续处理,这里不赘述
循环中的索引值
1 | $arr = (one,two,three);// a array |
↓↓↓1
2
3.class-one{ width: 0px;}
.class-two{ width: 10px;}
.class-three{ width: 20px;}
循环可以用过 by 关键字进行index相关设置,比如实现逆序遍历
1 | $arr = (one,two,three);// a array |
↓↓↓1
2
3.class-one{ width: 20px;}
.class-two{ width: 10px;}
.class-three{ width: 0px;}
Map型遍历for-in
@for-in用于遍历map型的数据,其中map行数据格式定义如下
1 | $map = (k1 v1,k2 v2...,kN vN);//括号可省略,为了可读性,建议保留 |
这里,key值(k1~kN)是允许重复的,不具备唯一性,重复也不会覆盖,即,数据并非一个严格意义上的hashMap!
1 | $propMap = (left 10px, left 20px, left 30px, top 30px, width 40px); |
↓↓↓
1 | .demo{ |
函数
css预处理器的一个重要属性,“封装”,而封装的实现,大多数离不开函数(以及mixin),mcss里的函数与js类似,也作为一种数据类型存在
函数的定义及使用
mixin模式的函数
以实现一个多前缀补全的user-select属性为例
1 | $user-select = ($v){ |
↓↓↓
1 | .txt{ |
函数模式的函数
以实现rem适配移动端为例:
1 | $remRatio ?= 100; // 假设所有分辨率下,固定转换比率为 1rem = 100px |
↓↓↓
1 | .demo{width: 0.36rem;} |
函数的参数
- 函数支持rest param 以及 default param 、named param
- 函数体中,可以使用args(i),以及$arguments关键字去获取参数的值
rest param 以及 default param 、named param:
1 | // 缺省值 |
↓↓↓
1 | body{ |
args(i),$arguments:
1 | $foo = {//函数的声明式括号参数($args...)可以省略 |
内建函数
mcss提供了比较丰富的内建函数,如颜色,列表,定义,js,data-uri,error等等
域
非重点,可跳过
mcss的函数与js类似,会保留当前的作用域
1 | $pos = ($position, $top, $left){ |
↓↓↓
1 | body{ |
继承
与其他预处理器一样,mcss也有“继承”功能,用于复用一些公共样式属性,避免过多的类名声明
extend
采用关键字 @extend 进行样式之间的继承,如下
1 | .demo1{ |
↓↓↓
1 | .demo1, .demo2{ |
导入
mcss的import支持原生css导入,mcss导入,同时,对于循环引用,mcss会给出错误提示
import
与其他css预处理器一样,mcss允许导入,其中,@import 后面可以使*.mcss文件,也可以是 *.css文件
如果是*.css文件时,不做修改,原样输出
文件目录1
2
3
4
5
6
7./
│
├─ base.css
│
├─ var.mcss
│
└─ main.mcss
base.css
1 | .base{color:red;}/*这里是base.mcss中的内容*/ |
var.mcss
1 | $color1 = #09c; |
main.mcss
1 | @import './base.css'; |
↓↓↓
1 | .base{color:red;}/*这里是base.mcss中的内容*/ |
abstract
使用,但不输出
对于一些想要extend的内容,但不确定会用到,或者说一些纯是公共复用代码块的,不希望想@import那样,全部都输出,则可以用@abstract虚拟引入
比如上面的例子,如果var.mcss里面有定义一个.demo1样式,而main.mcss中想要继承
var.mcss
1 | .demo1{ |
main.mcss
1 | //继承.demo1,但是不希望.demo也输出 |
↓↓↓
1 | .hello{ |
可以看出,虽然main.mcss引入了var.mcss,但是var.mcss中的.demo选择器并未输出。
正确使用@abstract, 可避免不需要的冗余样式输出
abstract-block
除了以文件形式出现的内容被@abstract引入之外,显示用@abstract{/*代码…*/}的方式声明的代码块,也会起到‘虚拟导入’
的效果,不过限于文件形式的组织方式会比较方面维护以及复用上也好很多,一般建议以 @abstract ‘path’的方式。
可跳过
比如,使用@abstract-block的方式,改写上面的main.mcss,会得到相同的效果
main.mcss
1 | @abstract { |
debug
可跳过
如果是在控制台,想要确定表达式的正确性,做一些测试之类的,可以采用@debug expression;的方式在控制台输出表达式的值
当然,由于大部分的表达式都可以在线编辑解析,所以建议使用在线转换器 mcss-Online-Parse
库
Mass之于mcss,就好比compass之于sass,它是官方css预处理器函数库,里面预定义了很多常用的函数,比如最常见的css3的prefix
详见mcss官方库Mass
后记
css预处理器的作用,在前端工程化中还是比较重要的一环,可以省去很多不必要的‘劳力操作’
比如,移动端的rem方式适配:js监控分辨率,控制根节点font-size,配合css预处理器实现视觉稿上px到rem的单位转换,省去程序员的计算,减少劳力劳动的同时,保障精确性。篇幅所限,只能讲些基础的东西,关于一些高级操作,比如define函数,一些常用的mixin的用法,后面另开一篇文章说明
css预处理器写得合理,函数库健全的话,理论上是可以完全摆脱css后处理器的(例如postCss的autoPrefix),当然,这里不是说后置处理器不好,而是说过多得的处理,会使得工程化变慢。
比如,在webpack中,同一种资源的loader过多的时候,大内容文件的处理,会变得异常慢,一次pack会让你等到花儿都谢了,谢了又开了。