预处理语言

CSS是一门标记性语言,对于初学者来者说,很难写出组织良好的且易于维护的CSS代码;

预处理语言扩充了CSS语言,增加了诸如变量、混合、函数等功能,让CSS更容易维护。预处理是CSS的超集,包含一套自定义的语法和一个解析器,根据这些语言写义自己的样式规则,这些规则最终会通过解析器编译生成对应的CSS文件,因此不能直接在浏览器运行,浏览器也不识别。

预编译语言主要包含:Sass、Less和Stylus。


Less 是什么?

Less(Leaner Style Sheets 的缩写) 是CSS预处理语言的一种,它扩充了CSS语言,为CSS赋予了动态语言的特性,如:变量、继承、运算、函数等,更方便的编写和维护CSS,提高开发效率。

Less快速入门: ​​https://less.bootcss.com/​

Less官网: ​​​​​​​​http://lesscss.cn/​

在线编辑器:​​lesscss.org/less-preview/​


1 安装Less

安装node.js 软件,官网:​​https://nodejs.org/en/​​ 。

检查nodejs是否安装成功,管理员身份运行 cmd,看到版本信息,即代表安装成功。

> node -v
// V16.18.0

用npm工具安装Less,再验证Less有没有安装成功,看到版本信息,即代表安装成功。

> npm install -g less
// 1 package is looking for funding

> lessc -v
// lessc 4.1.3 (Less Compiler) [JavaScript]

2 编译Less文件

编译前,需要先有一个Less文件。使用框架开发不用考虑Less编译为CSS。


2.1 命令行编译

2.1.1 未指定编译路径。编译完成后,会在控制台输出编译结果,但不会生成文件。

> lessc style.less

2.1.2 指定编译路径。编译完成后,会生成一个新的 style.css 文件,编译结果不会输出在控制台。

> lessc style.less > style.css

2.1.3 编译并压缩。需要借助 less-plugin-clean-css 插件,会生成同名压缩的CSS文件。

> npm install less-plugin-clean-css -g       //先安装插件
> lessc style.less > style.css --clean-css //使用插件压缩CSS

2.2 外部工具编译

命令行的编译方式比较麻烦,每写一次Less,都需要手动编译一次。借用外部工具可以实时编译。

如考拉Less客户端编译工具,官网:​​http://koala-app.com/​

可以选择压缩编译结果Compress,监听Less文件的变化,自动编译和生成资源地图文件。


2.3 开发工具编译

2.3.1 WebStorm

WebStorm内置File Wathchers,设置方式:

文件 > 设置 > 工具 > File Watchers > 添加选择less > 指定输出目录

2.3.2 VSCode

在VSCode中下载 easy less 插件,使用Less自动编译功能。

VSCode下载插件 > 写好Less文件保存 > 自动生成同名CSS文件

若要设置Less编译文件到指定目录,可以在插件扩展设置中,修改 settings.json 配置文件。

"less.compile": {
"compress": false, //是否压缩
"sourceMap": false, //是否生成map文件,有了这个可以在调试台看到less行数
// "out": true, // 是否输出css文件,false为不输出
"out": "${workspaceRoot}\\assets\\css\\", //输出路径
"outExt": ".css", // 输出文件的后缀
},

其中 out 就是指定生成的路径,注意格式。其中 ${workspaceRoot}是当前项目路径。

Less怎么用?

1 注释

1.1 /**/ 多行注释

这种注释是CSS的注释,可单行,可多行,编译后会保留在CSS文件中。

1.2 // 单行注释

// 这种代码注释CSS并不识别,供我们在Less文件中注释,编译后不会显示在CSS文件中。

/* 这里单行注释 会显示在CSS中 */
/*
编译后会显示在CSS中
编译后会显示在CSS中
*/
// 这个注释只会显示在Less文件,编译后不会显示在CSS文件中

2 变量

在Less中,可以使用变量来统一设置一类可以重复使用的值,方便后期维护。

在Less中,使用@来声明变量


2.1 普通变量

语法:

@变量名:变量值;

变量值要符合CSS属性值的规范,在CSS选择器后使用变量,如:属性名:@变量

// 定义变量,修改变量值会作用在所有使用此变量的位置
@fontColor: #333;
@baseColor: #ccc;

// 使用变量
.box{
color:@fontColor;
border:1px solid @baseColor;
}

div p{
color:@fontColor;
background-color: @baseColor;
}


2.2 字符串中使用变量

如果需要变量名和其他字符串拼接,语法:

"@{变量名}字符串"
@imgAD:"./imgs/ad.jpg"; // 定义图片变量 
@imgPath:"./imgs/"; // 定义图片路径变量

div{
width: 300px;
height: 300px;
background:url(@imgAD) no-repeat;
/* background: url("imgs/ad.jpg") no-repeat; */
// background:url("@{imgPath}banner.jpg") no-repeat;
/* background:url("imgs/banner.jpg") no-repeat; */
}

2.3 选择器使用变量

语法:

@{变量名}{}

html部分

<div id="wrap">大家好</div>

Less部分

@headSelect:#wrap;
@{headSelect}{ // 注意:加上{}是变量
color:#f00;
border: 1px solid #f00;
}

编译后CSS部分

#wrap {
color:#f00;
border: 1px solid #f00;
}

2.4 属性变量

语法:

@变量名:属性名
选择器{
@{变量名}:值
}

Less部分

@baseColor:color; //color是个属性,不是属性没有意义
div{
@{baseColor}:#f00;
border: 1px solid #f00;
}

编译后CSS部分

div {
color: #f00;
border: 1px solid #f00;
}

2.5 导入其他Less

语法:

@变量名:地址;
@import "@{变量名}";

@import "地址";

Less部分

@pubLess:"./pub.less"; //必须要有 pub.less 这个文件
@import "@{pubLess}";

//直接引用地址也可以
@import "./pub.less";

注意,就是将其他的Less文件引入当前的Less文件中,最后统一编译成一个CSS文件。

多个分类@import 可以根据项目设置不同的文件夹。

> [mixin]
> ----mix1.less
> ----mix2.less
> [model]
> ----mod1.less
> ----mod2.less
> mixin.less // 用mixin.less @import mixin里的less
> model.less // 用model.less @import model里的less
> style.less // 用style.less @import mixin.lessmodel.less

2.6 变量作用域

每个元素的CSS样式的{}都是一个独立的作用域,按照JS函数作用域来理解。

Less部分

@fontColor:#f00;
.wrap{
color:@fontColor; // wrap自己的作用域没有fontColor变量,所以用上一级作用变量的值
}
.box{
@fontColor:#00f; // 自己作用内定义了变量
color:@fontColor; // 就会优先使用自己作用域内的变量值
}

编译后的CSS

.wrap {
color: #f00;
}
.box {
color: #00f;
}

注意:变量会被预解析,先使用后定义也没关系,按习惯还是尽量放在前面。

// 先使用变量
.wrap{
color:@fontColor;
}

// 后定义变量
@fontColor:#f00;

2.7 变量的计算

变量的值可以参与运算。

Less部分

@pubLen:300px;
@pubColor:#333;

.box{
width:@pubLen+100; // 加减乘除都可以
height:@pubLen;
border:1px solid @pubColor*3; // 颜色值也可以计算
color:@pubColor;
}

编译后的CSS

.box {
width: 400px;
height: 300px;
border: 1px solid #999999;
color: #333;
}

3 混合

混合(Mixins,也叫混入) 有点像函数,在定义后,可以通过名称调用,也支持动态传参。可以将一个定好的 class A引入到另一个Class B 中,从而实现 class B 继承 Class A 中的所有属性,还可以带参数的调用。

简单理解就是函数,可以封装CSS代码,在别的选择器中调用,提高代码的复用性和可维护性。


3.1 无参数混入

语法:

.混入名(){
封装的CSS代码
}

Less部分

@baseColor:#00f;
/* 定义无参数混入*/
.baseProp(){ // 注意有括号,没有括号就成普通类了,当然,普通类也可以混入。
width: 100px;
height: 100px;
border: 1px solid #f00;
}
.box{
.baseProp(); // 引入混入,没有参数,可以不用加括号,有参数必须要加;
color: @baseColor;
}

编译后CSS部分

/* 定义无参数混入*/
.box {
width: 100px;
height: 100px;
border: 1px solid #f00;
color: #00f;
}

混入中引入变量,变量的作用域在引入前确定。

Less部分

@baseColor:#00f;
/* 混入中引入变量,在定义的地方确定作用域*/
.baseProp(){
width: 100px;
height: 100px;
border: 1px solid @baseColor; // 变量先在自己作用域找,再在父作用域找。
}
.box{
@baseColor:#ff0;
.baseProp(); // 混入的变量已经确定了作用域
color: @baseColor; // 在本类作用域中被定义了
}

编译后的CSS

/* 混入中引入变量,在定义的地方确定作用域*/
.box {
width: 100px;
height: 100px;
border: 1px solid #00f;
color: #ff0;
}


3.2 有参数混入

语法:

.混入名(@参数:默认值){
封装的CSS代码
}

参数后无默认值,表示必传,引入时指定实参。

Less部分

.baseProp(@boxWidth,@boxHeight){
width: @boxWidth;
height:@boxHeight;
}
.box{
color:#f00;
.baseProp(400px,200px);
}

编译后CSS部分

.box {
color: #f00;
width: 400px;
height: 200px;
}

参数后有默认值,可以指定实参,也可以不指定。

Less部分

.baseProp(@boxWidth,@boxHeight:200px,@fontSize:30px){
width: @boxWidth;
height:@boxHeight;
font-size:@fontSize;
}
.box{
color:#f00;
.baseProp(400px,400px); // @fontSizee 有默认值,引入的时候可以不写
}

编译后的CSS部分

.box {
color: #f00;
width: 400px;
height: 400px;
font-size: 30px;
}

想让混入使用当前作用域中的变量,也要传参。

Less部分

@boxHeight:300px;
.baseProp(@boxWidth,@boxHeight:200px,@fontSize:30px){
width: @boxWidth;
height:@boxHeight;
font-size:@fontSize;
}
.box{
color:#f00;
@fontSize:50px;
.baseProp(400px,@boxHeight,@fontSize);
}

编译后的CSS部分

.box {
color: #f00;
width: 400px;
height: 300px;
font-size: 50px;
}


3.3 调用混入

Less部分

// 定义一个混入
.baseProp(@baseColor:#369,@baseHeight:100px){ //定义了默认值
color: @baseColor;
height: @baseHeight;
}

@baseColor:#ff0;
@baseHeight:36px;

.box .item1{
.baseProp(@baseColor,@baseHeight); // 传变量
}
.box .item2{
.baseProp(#00f,52px); // 传实参
}
.box .item3{
.baseProp(); // 传默认值,无参数可不加括号 .baseProp
}
.box .item4{
@baseColor:#963;
@baseHeight:88px;
.baseProp(@baseColor,@baseHeight); // 不同作用域传参
}

编译后的CSS

.box .item1 {
color: #ff0;
height: 36px;
}
.box .item2 {
color: #00f;
height: 52px;
}
.box .item3 {
color: #369;
height: 100px;
}
.box .item4 {
color: #963;
height: 88px;
}

3.4 混入中的“!important”

还可以给混入加上“!important”,最高优先级,一般不建议这么用。

Less部分

.baseProp(@baseColor:#369,@baseHeight:100px){
color: @baseColor;
height: @baseHeight;
}
.box .item{
.baseProp()!important;
height:300px;
}

编译后的CSS部分

.box .item {
color: #369 !important;
height: 100px !important;
height: 300px;
}

3.5 默认值与不定参

Less可以使用默认参数,如果没有传参数,那将使用默认参数。

建议都加上默认值,尤其是在复用场合较多的情况下。

不定参:不确定参数的个数

Less部分

// ... 指剩余参数,会将剩余的所有参数都加到 @arguments
.boxShadow(...){
box-shadow: @arguments;
}
.box{
width: 100px;
height:100px;
.boxShadow(2px,2px,10px,#f00);
}

// @arguments 是处理第一个实参外的所有实参的集合

.itemShadow(@type,...){
box-shadow: @arguments;
}
.box .item{
width: 100px;
height:100px;
.itemShadow(inset,2px,2px,10px,#f00);
}

编译后的CSS部分

.box {
width: 100px;
height: 100px;
box-shadow: 2px 2px 10px #f00;
}
.box .item {
width: 100px;
height: 100px;
box-shadow: inset 2px 2px 10px #f00;
}

4 嵌套

具有层级关系的CSS样式,CSS的层级是由HTML的结构决定的。

4.1 嵌套的优势:

  • 用具有后代关系和父子关系的选择器中;
  • 减少代码量;
  • 代码结构清晰,可折叠;

4.2 嵌套的使用:

语法:

父选择器{
父属样样式
子选择器A{
子选择器A样式
}
子选择器B{
子选择器B样式
}
}

HTML部分

<div class="box">
<h2>标题</h2>
<p>内容</p>
<span><em>日期</em></span>
</div>

Less部分

.box{
background-color: #ccc;
h2{
line-height: 36px;
color: #00f;
}
p{
font-size: 24px;
}
span{
border: 1px solid #333;
em{
font-weight: bold;
}
}
}

编译的CSS部分

.box {
background-color: #ccc;
}
.box h2 {
line-height: 36px;
color: #00f;
}
.box p {
font-size: 24px;
}
.box span {
border: 1px solid #333;
}
.box span em {
font-weight: bold;
}

4.3 &符号的使用

使用场景:父子、兄弟、紧邻、伪类等选择器使用时。

HTML结构

<div class="box box-hd">
<h2 class="box-title">标题</h2>
</div>

Less部分

.box{
background-color: #ccc;
&-title{ // &也可以当父元素的连接符 > .box-title
line-height: 36px;
color: #00f;
&::before{ //& 指向当前父元素,即: .box-title
content: "";
display: block;
}
}
&:hover{ // &用在伪类
background-color: #999;
}
&.box-hd{ // &用在同级class
font-size:36px;
}
}

编译后的CSS部分

.box {
background-color: #ccc;
}
.box-title {
line-height: 36px;
color: #00f;
}
.box-title::before {
content: "";
display: block;
}
.box:hover {
background-color: #999;
}
.box.box-hd {
font-size: 36px;
}

5 变量运算

运算符的作用: 可以对角度、颜色和高宽度等进行运算;

运算符的分类:加+,减-,乘*,除/ (除法使用()括号起来)。

Less部分

@w1:200px;
@w2:300px;
@c1:#333;
@c2:#666;

div{
width:@w1+@w2;
// 16进制的颜色值,只能在#000000-#FFFFFF之间,超出了,就会自动使用最小/大值
background-color: @c1+@c2;
}

编译后的CSS部分

div {
width: 500px;
background-color: #999999;
}

实例1:.btn 的维护

.btn(@size){
width: 100px * @size;
height: 30px * @size;
font-size: 14px* @size;
}
// 可以维护.btn的尺寸
.btn{
.btn(3);
}

编译后的CSS

.btn {
width: 300px;
height: 90px;
font-size: 42px;
}

实例2:.box 的垂直居中

.box{ // 可以方便维护宽高,省去了计算负宽高的问题
@width:100px;
@height:100px;

position: fixed;
top:50%;
left:50%;
background-color: #f00;

width: @width;
height:@height;
margin: (-@height/2) 0 0 (-@width/2); // 插件中除法运算加上()
}

编译后的CSS

.box {
position: fixed;
top: 50%;
left: 50%;
background-color: #f00;
width: 100px;
height: 100px;
margin: -50px 0 0 -50px;
}

6 颜色函数

CSS预处理一般都会内置一些颜色处理函数,用来对颜色值进行处理,例如:加亮、变暗;

色彩的HSL模式,是通过对色调(Hue)、饱和度(Saturation)、亮度(Lightness)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的。

Less 简介、安装和语法_css

亮到一定程序就是白色、暗到一定程序就是黑色。

Less 简介、安装和语法_官网_02

参数:

hue : 0-360的整数,用于表示颜色的度数;

saturation: 0-100%的百分比数或0-1的整数;

lightness:0-100%的百分比数或0-1的整数;

返回值:

color

函数:

增加或降低颜色的饱和度:saturate() / desaturate()

增加或降低颜色的亮度: lighten() / darken()

设置或增加/降低颜色的透明度: fade() / fadein() / fadeout()

任意方向旋转颜色的色相角度: spin(hue agnle)

HTML结构

<div class="box">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>

LESS部分

.box{
margin:20px auto;
padding: 0;
display: flex;
justify-content: space-evenly;
width: 200px;
background-color: #eee;
div{
width: 50px;
height: 50px;
line-height: 50px;
text-align: center;
color: #eee;
}
div:nth-child(1){
background-color: lighten(hsl(90,70%,50%),30%);
//增加30%亮度 输出:hsl(90, 70%, 80%)
}
div:nth-child(2){
background-color: saturate(hsl(90,70%,50%),30%);
//增加30%饱和度 输出:hsl(90, 100%, 50%)
}
div:nth-child(3){
background-color: spin(hsl(90,70%,50%), 30);
// 色相环旋转30度,可负,如:-30 输出:hsl(120, 70%, 50%)
}
div:nth-child(4){
background-color: fade(hsl(90,70%,50%), 30%);
// 设置透明度为30% 输出:hsla(90, 70%, 50%, 0.3);
}
}

效果:

Less 简介、安装和语法_css_03


7 禁止编译

有时Less的编译会使结果不准确,目前版本已经修复了,但此功能还在;

.header{
width: calc(100%-50px);
}

要禁止这一行编译,可以:

.header{
width: ~"calc(100%-50px)";
}


8 数组循环

@arr: 1px, 2px, 3px;

.demo{
width:length(@arr) * 1px; // length 获得@arr长度
height: extract(@arr,3); // extract 获得下标3的值,less里从1开始取下标
}

编译CSS

.demo {
width: 3px;
height: 3px;
}

实例:btn组件

使用数组和循环写的简易btn组件。

HTML结构

<button class="btn btn-default">正常</button>
<button class="btn btn-success disable">成功</button>
<button class="btn btn-warning">警告</button>
<button class="btn btn-danger">失败</button>
<button class="btn btn-info">信息</button>

Less部分

@btnNames: default, success, warning, danger, info;
@btnColors: #409EFF, #67C23A, #E6A23C, #F56C6C, #909399;
@baseColor: rgba(255,255,255,0.7);

body{
padding:20px 0 0 20px;
}
.btn{
padding: 0 16px;
margin: 0;
line-height: 30px;
text-align: center;
color: #fff;
font-size:12px;
border: 0;
border-radius: 3px;
outline: none;
color: rgba(255,255,255,0.8);
}

.loop(@i) when (@i <= length(@btnNames)){
@btnName: extract(@btnNames, @i);
@btnColor:extract(@btnColors, @i);

.btn-@{btnName}{
background-color: @btnColor;
&:hover{
background-color: (@btnColor / 0.9);
color: #fff;
}
&.disable{
background-color: (@btnColor * 0.8);
color: @baseColor;
&:hover{
color: @baseColor;
}
}
}
.loop((@i+1));
}
.loop(1);

效果:

Less 简介、安装和语法_css_04


最后声明:

日常工作中,常用的功能只会用到一部分。

本笔记根据互联网上的文章以及51CTO付费课程学习整理而来。