CSS的短板
作为前端学习者的我们 或多或少都要学些 CSS ,它作为前端开发的三大基石之一,时刻引领着 Web 的发展潮向。 而 CSS 作为一门标记性语言,可能 给初学者第一印象 就是简单易懂,毫无逻辑,不像编程该有的样子。在语法更新时,每当新属性提出,浏览器的兼容又会马上变成绊脚石,可以说 CSS 短板不容忽视。
问题的诞生往往伴随着技术的兴起, 在 Web 发展的这几年, 为了让 CSS 富有逻辑性,短板不那么严重,涌现出了 一些神奇的预处理语言。 它们让 CSS 彻底变成一门 可以使用 变量 、循环 、继承 、自定义方法等多种特性的标记语言,逻辑性得以大大增强。
预处理语言的诞生
其中 就我所知的有三门语言:Sass、Less 、Stylus 。
Sass 诞生于 2007 年,Ruby 编写,其语法功能都十分全面,可以说 它完全把 CSS 变成了一门编程语言。另外 在国内外都很受欢迎,并且它的项目团队很是强大 ,是一款十分优秀的预处理语言。
Stylus 诞生于 2010 年,来自 Node.js 社区,语法功能也和 Sass 不相伯仲,是一门十分独特的创新型语言。
Less 诞生于 2009 年,受Sass的影响创建的一个开源项目。 它扩充了 CSS 语言,增加了诸如变量、混合(mixin)、函数等功能,让 CSS 更易维护、方便制作主题、扩充(引用于官网)。
选择预处理语言
这是一个十分纠结的问题。
在我看来,这就好比 找女朋友,有人喜欢 贤惠安静的,就有人喜欢 活泼爱闹的,各有各的爱好,可晚上闭灯后 其实都差不多,所以你不用太过纠结。当然了 ,首先 你要有女朋友。
在网上讨论看来,Sass 与 Stylus 相比于 Less 功能更为丰富,但对于学习成本以及适应时间 ,Less 稍胜一筹,这也是我选择 Less 的原因。
Less 没有去掉任何 CSS 的功能,而是在现有的语法上,增添了许多额外的功能特性,所以学习 Less 是一件非常舒服的事情。
如果你之前没有接触过预处理语言,纠结应该学哪一个,不如先看看 下面 Less 的介绍,我相信你会爱上它的。
每一门技术的出现都是为了解决现存的问题,同样的,Less 的出现是为了解决 CSS 中过于呆板的写法。Less 官方文档 中对 Less 的使用有详细的介绍,总结一下为:Less = 变量 + 混合 + 函数。如果你对 js 和 css 有所了解,那么就可以很快的掌握并在你的项目中使用 Less。
一、Less 使用初体验
1. 使用 Less 写样式
使用 Npm 全局安装 Less
$ npm install less -g
创建一个空文件夹,这里命名为:learn-less
在根目录下创建 index.html 文件,复制内容如下:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>初识 Less</title>
<link href="./main.css" rel="stylesheet">
</head>
<body>
<div class="container">1</div>
<div class="container2">2</div>
<div class="container3">3</div>
</body>
</html>
在根目录下创建 main.less 文件,复制内容如下:
<span class="hljs-comment">// main.less</span>
<span class="hljs-meta">@width</span>: <span class="hljs-number">100</span>%;
<span class="hljs-meta">@height</span>: <span class="hljs-number">100</span>px;
<span class="hljs-meta">@color</span>: red;
.container{
width: <span class="hljs-meta">@width</span>;
height: <span class="hljs-meta">@height</span>;
background-color: <span class="hljs-meta">@color</span>;
margin-bottom: <span class="hljs-number">5</span>px;
}
.container2{
width: <span class="hljs-meta">@width</span>;
height: <span class="hljs-meta">@height</span>;
background-color: <span class="hljs-meta">@color</span>;
margin-bottom: <span class="hljs-number">5</span>px;
}
.container3{
width: <span class="hljs-meta">@width</span>;
height: <span class="hljs-meta">@height</span>;
background-color: <span class="hljs-meta">@color</span>;
margin-bottom: <span class="hljs-number">5</span>px;
}
现在打开浏览器看一下,会发现并没有加载样式。这是因为 index.html 中引入的样式文件是 main.css 而不是 main.less。所以接下来,我们需要将 main.less 转换为 main.css,不用担心,这一步骤并不需要你手动操作,仅仅是运行一条命令就会自动完成转换。
$ lessc main.less
操作完以上步骤就会发现在根目录下生成了一个 main.css 文件,此时再打开浏览器看看,样式已经出现了。
main.css 转义内容为:
.container {
width: 100%;
height: 100px;
background-color: red;
margin-bottom: 5px;
}
.container2 {
width: 100%;
height: 100px;
background-color: red;
margin-bottom: 5px;
}
.container3 {
width: 100%;
height: 100px;
background-color: red;
margin-bottom: 5px;
}
如果你使用了 Webstorm 作为开发工具,那么连手动输入命令行这一步都可以跳过,因为 Webstorm 会在你的 .less 文件被修改后自动生成对应的 .css 文件,具体配置跳转:Webstorm 配置 Less 自动转译成 css
2. 感受 Less 的便利
现在有一个新的需求,需要将三个 div 的背景颜色改成蓝色(blue),如果是之前 css 的写法需要依次找到 container、container2、container3,对应修改里面的 background-color 属性,但是使用 less 我们仅仅修改前面定义过的变量值即可。
// main.less
@width: 100%;
@height: 100px;
@color: blue;
…
使用 lessc main.less
进行转译后打开浏览器可以看到三个 div 的背景颜色已经被改变了。
二、变量
在前面介绍的案例中已经使用了“变量”的概念,是不是感觉和 js 很像,事实上 less 就是用 js 的写法来写 css。
官网在介绍变量的时候会给出很多应用场景,总结一下就是使用 @ 符号定义变量,使用 @ 符号获取变量,仅仅将 @变量名
看成是一个字符串。
@classname: main;
@color: red;
@classname{
background-color: @color
}
从上面例子中可以看到,变量不仅仅可以作为样式属性值:background-color: @color;
,还可以作为类名:.@classname
表示的就是 .main
。这也就是为什么说仅仅将 @变量名 看成是一个字符串。
三、混合
先看一个 example.css 文件:
#menu a {
color: #111;
border-top: dotted 1px black;
border-bottom: solid 2px black;
}
#menu span {
height: 16px;
border-top: dotted 1px black;
border-bottom: solid 2px black;
}
#menu p {
color: red;
border-top: dotted 1px black;
border-bottom: solid 2px black;
}
可以看到上面三个样式中都有 border-top
和 border-bottom
两个属性,并且内容完全相同;在传统 CSS 写法中只能这样一遍有一遍的去书写重复的内容,在 Less 中通过将公共属性抽取出来作为一个公共类
的方式规避这一点。
// example2.less
.bordered {
border-top: dotted 1px black;
border-bottom: solid 2px black;
}
#menu a {
color: #111;
.bordered;
}
#menu span {
height: 16px;
.bordered;
}
#menu p {
color: red;
.bordered();
}
将以上 example2.less 进行转译成 example2.css 文件为:
.bordered {
border-top: dotted 1px black;
border-bottom: solid 2px black;
}
#menu a {
color: #111;
border-top: dotted 1px black;
border-bottom: solid 2px black;
}
#menu span {
height: 16px;
border-top: dotted 1px black;
border-bottom: solid 2px black;
}
#menu p {
color: red;
border-top: dotted 1px black;
border-bottom: solid 2px black;
}
可以看到 examle2.css 与 example.css 很相似,只是多了一个 .bordered 样式。
修改 example2.less,将 .bordered 写成 .bordered(),此时在进行转译之后会看到 example2.css 和 example.css 文件就完全一样了,使用 less 书写更加简单。
// example2.less
.bordered() {
border-top: dotted 1px black;
border-bottom: solid 2px black;
}
…
总结:
混合也是减少代码书写量的一个方法;
混合的类名在定义的时候加上
小括弧 ()
,那么在转译成 css 文件时就不会出现;-
混合的类名在被调用的时候加上
小括弧 ()
和不加上小括弧 ()
是一样的效果,看个人习惯,如:第三行和第八行转译成 css 是一样的。1 #menu span { 2 height: 16px; 3 .bordered; 4 } 5 6 #menu p { 7 color: red; 8 .bordered(); 9 }
四、函数
曾几何时,在书写呆板的 css 时有没有想过让类名动态化,根据不同的参数生成不同的样式。看下面的示例:
// func.less
.border-radius(@radius) {
-webkit-border-radius: @radius;
-moz-border-radius: @radius;
border-radius: @radius;
}
#header {
.border-radius(4px);
}
.button {
.border-radius(6px);
}
使用 $ lessc func.less
进行转译 func.css 文件内容如下:
#header {
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
.button {
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
border-radius: 6px;
}
可以看到,这里就用到了函数的概念,在 #header
和 .button
中分别传入不同的参数,结果也就生成不同的代码。
关于 less 中函数的写法还有以下几种:
// 函数的参数设置默认值:
.border-radius(@radius: 5px) {
-webkit-border-radius: @radius;
-moz-border-radius: @radius;
border-radius: @radius;
}
// 函数有多个参数时用分号隔开
.mixin(@color; @padding:2) {
color-2: @color;
padding-2: @padding;
}
// 函数如果没有参数,在转译成 css 时就不会被打印出来,详见上面混合中的示例
.wrap() {
text-wrap: wrap;
}
// 函数参数如果有默认,调用时就是通过变量名称,而不是位置
.mixin(@color: black; @margin: 10px; @padding: 20px) {
color: @color;
margin: @margin;
padding: @padding;
}
.class1 {
.mixin(@margin: 20px; @color: #33acfe);
}
// 函数参数有个内置变量 @arguments,相当于 js 中的 arguments
.box-shadow(@x: 0; @y: 0; @blur: 1px; @color: #000) {
-webkit-box-shadow: @arguments;
-moz-box-shadow: @arguments;
box-shadow: @arguments;
}
// 函数名允许相同,但参数不同,类似于 java 中多态的概念
.mixin(@color: black) {
.mixin(@color: black; @margin: 10px) {
当然,上面是开发人员自定义的函数,Less 也为我们定义了很多好用的内置函数。关于内置函数,如果掌握,可以在开发过程中节约很多时间,由于内置函数数量很多,这里就不一一介绍,传送门:Less 内置函数官方文档。
五、父子元素的写法
在 css 中父子元素的写法通常如下:
.container {
padding: 0;
}
.container .article {
background-color: red;
}
在 Less 写法如下,父子嵌套关系一目了然。
.container {
padding: 0;
.article {
background-color: red;
}
}
当然,父子元素还要一种是伪类的写法,在 css 中写法如下:
#header :after {
content: " ";
display: block;
font-size: 0;
height: 0;
clear: both;
visibility: hidden;
}
在 less 中写法如下,可以看到引入了新的符号 &
,以 &
来代替主类 #header
。
#header {
&:after {
content: " ";
display: block;
font-size: 0;
height: 0;
clear: both;
visibility: hidden;
}
}
六、神奇 @import
在传统 css 文件中,每个文件都是独立的。在 less 中可以像 js 的模块那样在一个 less 文件中引入另一个 less 文件。
创建 one.less 文件:
.container {
width: 100px;
height: 200px;
}
创建 two.less 文件:
@import "one";
使用 $ lessc two.less
转译成 two.css
文件,可以看到内容如下:
.container {
width: 100px;
height: 200px;
}
@import 的作用可以看成是将 one.less 的内容复制一份到当前 .less 文件中。
那么如果 two.less 中也有一个类名叫 container 的,使用 @import 之后会变成什么样子呢?这个留给自行测试好啦。
参考:
https://segmentfault.com/a/1190000012360995?utm_source=tag-newest#articleHeader0
https://www.jianshu.com/p/48018e5da7dd