無.Flac's Blog

無.Flac

LESS预处理语言

CSS
97
2024-05-09

⭐️ 有关 LESS预处理语言 的学习



什么是预处理语言

其中常用的有三门语言:Sass、Less、stylus。

1.Sass 诞生于 2007年,Ruby 编写,其语法功能都十分全面,可以说 它完全把 CSS 变成了一门编程语言。在国内外都很受欢迎,并且它的项目团队很是强大,是一款十分优秀的预处理语言。

2. Stylus 诞生于 2010 年,来自 Node.js 社区,语法功能也和 Sass 不相伯仲,是一门十分独特的创新型语言。LESS 是一种动态样式语言,为提高 CSS 应用的灵活性和效率,LESS 将 CSS 赋予了动态语言的特性,如变量、继承、运算、函数。

3. Less 诞生于 2009 年,受Sass的影响创建的一个开源项目。 它扩充了CSS 语言,增加了诸如变量、混合(mixin)、函数等功能,让 CSS 更易维护、方便制作主题、扩充。


CSS的短板

前端开发的三大基石之一,CSS 作为一门标记性语言,在语法更新时,每当新属性提出,浏览器的兼容又会马上变成绊脚石,可以说 CSS 短板不容忽视。

问题的诞生往往伴随着技术的兴起,在 Web 发展的这几年, 为了让 CSS 富有逻辑性,短板不那么严重,涌现出了 一些神奇的预处理语言。 它们让CSS彻底变成一门可以使用变量 、循环 、继承 、自定义方法等多种特性的标记语言,逻辑性得以大大增强。


LESS介绍

Less 是一门 CSS 预处理语言,它扩展了 CSS 语言,增加了变量、Mixin、函数等特性,使 CSS 更易维护和扩展。Less 扩充了 CSS 语言,增加了诸如变量、混合(mixin)、运算、函数等功能。 Less 既可以运行在服务器端(Node.js 和 Rhino 平台)也可以运行在客户端(浏览器)。

在 Node.is 环境中使用 Less

npm insta11 -g less

在浏览器环境中使用 Less

<link rel="stylesheet/less" type="text/css" href_"styles.less" /> 
<script src="//cdnjs.cloudflare.com/ajax/libs/less.js/3.11.1/less.min.js" ></script>

LESS的使用

注释

// 这种注释,在编译后不会出现在CSS文件上
/* 这种注释,在编译后会出现在CSS文件上 */

变量

在 CSS 中 看到同一个值重复多次且难于代码维护。 理想状态应是下面这样:

const bgcolor='skyblue":
$(".post-content").css("background-color",bgcolor);
$("#wrap").css("background-color",bgcolor);
$(".arctive").css("background-color",bgcolor),

只要我们修改 bgcolor 这一个变量,整个页面的背景颜色都会随之改变。而 Less中的变量十分强大,其变量是常量,所以只能定义一次,不能重复使用。

值变量

@color: #999;
@bgcolor: skyblue;
@width: 50%;
.wrap {
	color: @color,
	background: @bgcolor;
	width: @width;
}
/*生成后的 css */
.wrap {
	color:#999;
	background: skyblue;
	width: 50%;
}

以 @开头定义变量,并且使用时直接键入 @名称。这样利于代码组织维护。

@lightPrimarycolor:#c5cae9;
@textPrimarycolor: #fff;
@accentcolor:rgb(99,137,185);
@primaryTextcolor:#646464;
@secondaryTextcolor:#000;
@dividercolor:#b6b6b6;
@bordercolor:#dadada;

LESS变量

选择器变量

让选择器变成动态

/* Less */
@mySelector: #wrap;
@wrap: wrap;

@{mySelector} {
    color: #999;
    width: 50%;
}

.@{wrap} {
    color: #ccc;
}

#@{wrap} {
    color: #666;
}

/*生成的 CSS */
#wrap {
    color: #999;
    width: 50%;
}

.wrap {
    color: #ccc;
}

#wrap {
    color: #666;
}

属性变量

可减少代码书写量

/* Less */
@borderstyle: border-style;
@soild: solid;

#wrap {
    @{borderstyle}: @soild; //变量名 必须使用大括号包裹
}
/* 生成的 css */
#wrap {
    border-style: solid;
}

url变量

项目结构改变时,修改其变量即可

/* Less */
@images: "../img"; //需要加引号

body {
    background:url("@{images}/dog.png"); //变量名 必须使用大括号包裹
}

/* 生成的 CSS */
body {
    background: ur1("../img/dog.png");
}

声明变量

有点类似于下面的混合方法

  • 结构:@name:(属性:值;)

  • 使用:@name();

/* Less */
@background: {background:red;}
@Rules:{
	width:200px;
	height:200px;
	border: solid 1px red;
}

#main {	
	@background()
}

#con {
	@Rules()
}

/* 生成的 CSS */

#main {
  background: red;
}

#con {
  width: 200px;
  height: 200px;
  border: solid 1px red;
}

变量运算

Less 的变量运算十分强大

  • 加减法时,以第一个数据的单位为基准

  • 乘除法时,注意单位一定要统一

/* Less */
@width:300px;
@color:#222;
#wrap{
	width:@width - 20;
	height:@width - 20 * 5;
	margin:(@width - 20) *5;
	color:@color * 2;
	background-color: @color + #111;
}

/* 生成的 CSS */
#wrap{ 
	width:280px;
	height:200px;
	margin:1400px;
	color:#444;
	background-color:#333;
}

变量作用域

简单理解:就近原则

/* Less */
@var: @a;
@a: 100%
#wrap {
	width: @var;
	@a: 9%
}

/* 生成的 CSS */
#wrap {
	width: 9%;
}

变量定义变量

/* Less */
@fnord: "I am fnord";
@var: "fnord";
#wrap::after {
	content: @fnord; //或者替换为var
}

/* 生成的 CSS */
#wrap::after {
  content: "I am fnord";
}

LESS 嵌套

&的妙用

&:代表的上一层选择器的名字

/* Less */
.header {
    &:after {
        content: "Less is more!";
    }

    .title {
        font-weight: bold;
    }

    &_content {
        margin: 20px;
    }
}

/* 生成的 CSS */
.header:after {
  content: "Less is more!";
}
.header .title {
  font-weight: bold;
}
.header_content {
  margin: 20px;
}

媒体查询

在以往的工作中,我们使用媒体查询,都要把元素分开写:

#wrap {
	width:500px;
}
@media screen and (max-width:768px){
	#wrap{
		width:100px;
}

Less提供了一个十分便捷的方式:

/* Less */
#main {
	//something...

	@media screen {
		@media (max-width:768px){
			width:100px;
		}
	}
	@media tv {
		width:2000px;
	}
}

/* 生成的 CSS */
@media screen and (max-width: 768px) {
  #main {
    width: 100px;
  }
}
@media tv {
  #main {
    width: 2000px;
  }
}

唯一的缺点:每一个缺点都会编译出@media 声明,并不会合并。

实战技巧

可以借助Less在元素中,去定义自己的私有样式

/* Less */
#main {
	//something..
	&.show {
		display:block;
	}
}

.show {
	display:none; 
}

<script>
const main = document.getElementById("main");
main.classList.add("show");
</script>

结果:

#main.show {
	display:block;
}
.show {
	display:none; //会被覆盖
}

混合方法

无参数方法

方法类似声明集合,直接键入名称即可

/* Less */
.card {
    background: red;
    box-shadow: 0 1px 2px gray;
    -webkit-box-shadow: 0 1px 2px gray;
}
#wrap {
    .card()
}

/* 生成的 CSS */
.card {
  background: red;
  box-shadow: 0 1px 2px gray;
  -webkit-box-shadow: 0 1px 2px gray;
}
#wrap {
  background: red;
  box-shadow: 0 1px 2px gray;
  -webkit-box-shadow: 0 1px 2px gray;
}

其中.card 与 .card( )是等价的,为避免代码混淆,应写成:

.card(){
	//something..
}
#wrap {
	.card()
}
  • . 与 # 皆可作为方法前缀

  • 方法后 ( ) 看个人习惯

默认参数方法

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

  • @arguments 犹如 JS 中的 arguments 指代的是全部参数

  • 传的参数中,必须带着单位

/* Less */
.border(@a: 10px, @b: 50px, @c: 30px, @color: #000) {
    border: solid 1px @color;
    box-shadow: @arguments; //指代的是全部参数
}

#main {
    .border(0px, 5px, 30px, red)
}

#wrap {
    .border(0px);
}

#content {
    .border;//等价于 .border()
}

/* 生成的 CSS */
#main {
  border: solid 1px red;
  box-shadow: 0px 5px 30px red;
}
#wrap {
  border: solid 1px #000;
  box-shadow: 0px 50px 30px #000;
}
#content {
  border: solid 1px #000;
  box-shadow: 10px 50px 30px #000;
}

方法的匹配模式

与面向对象中的多态很相似

/* Less */
.triangle(top, @width: 20px, @color: #000) {
    border-color: transparent transparent @color transparent;
}

.triangle(right, @width: 20px, @color: #800) {
    border-color: transparent @color transparent transparent;
}

.triangle(bottom, @width: 20px, @color: #000) {
    border-color: @color transparent transparent transparent;
}

.triangle(left, @width: 20px, @color: #000) {
    border-color: transparent transparent transparent @color;
}

.triangle(@_, @width: 2px, @color: #000) {
    border-style: solid;
    border: @width;
}

#main {
    .triangle(left, 50px, #999);
}

/* 生成的 CSS */
#main {
  border-color: transparent transparent transparent #999;
  border-style: solid;
  border: 50px;
}
  • 第一个参数 left 会找到方法中匹配程度最高的,如果匹配程度相同将全部选择,反之并替换或覆盖样式

  • 如果匹配的参数是变量,则将会匹配,如@_

方法的命名空间

让方法更加规范

/* Less */
#card() {
	background:#999;
	.d(@w:300px) {
		width: @w;

		#a(@h:300px) {
			height: @h; //可以使用上一层传进来的方法
		}
	}
}

#wrap {
	#card > .d > #a(100px); //父元素可不加括号
}
#main {
	#card .d();
}
#con {
	//不得单独使用命名空间的方法
	// .d() 如果前面没有引入明明空间 #card .将会报错

	#card; //等价于 #card();
	.d(20px); //必须先引入 #card
}

/* 生成的 CSS */
#wrap {
  height: 100px;
}
#main {
  width: 300px;
}
#con {
  background: #999;
  width: 20px;
}
  • 在 CSS中,>子代选择器,需与父元素有直接血缘关系

  • 在引入命令空间时,如使用>选择器,父元素不加括号

  • 不得单独使用命名空间的方法,必须先引入命名空间,才能使用其方法

  • 子方法可以使用上一层传进来的方法

方法的条件筛选

Less 中没有 if else 语法,有 when

/* Less */
#card {

    //and 运算符 ,相当于 &&与运算 ,条件全部符合则执行
    .border(@width, @color, @style) when (@width>100px) and (@color=#999) {
        border: @style color @width;
    }

    // not 运算符,相当于 !非运算 ,条件不符合则执行
    .background(@color) when not (color>=#222) {
        background: @color;
    }

    // ,逗号分隔符,相当于 |或运算 ,一个符合条件就会执行
    .font(@size: 20px) when (size>50px),(@size<100px) {
        font-size: @size;
    }
}

#main {
	#card>.border(200px,#999,soild);
	#card>.background(#111);
	#card>.font(40px);
}

/* 生成的 CSS */
#main {
  border: soild color 200px;
  background: #111;
  font-size: 40px;
}
  • Less中的比较运算可参见 JS语法 中的运算符

  • Less中 = 代表的是等于

  • 除去关键字 true 以外的值都被视为 false

数量不定的参数

方法接受数量不定的参数,可以使用... ,例如ES6扩展运算符

/* Less */
.boxShadow(...){
	box-shadow: @arguments;
}
.textShadow(@a,...){
	text-shadow: @arguments;
}
#main {
	.boxShadow(1px,3px,10px,gray);
	.textShadow(1px,5px,15px,green);
}

/* 生成的 CSS */
#main {
  box-shadow: 1px 3px 10px gray;
  text-shadow: 1px 5px 15px green;
}

方法使用 important!

/* Less */
.border {
	border: solid 1px red;
	margin: 50px;
}
#main {
	.border()!important;
}

#main {
	border: solid 2px yello !important;
	margin: 50px !important;
}

/* 生成的 CSS */
#main {
  border: solid 1px red !important;
  margin: 50px !important;
}
#main {
  border: solid 2px yello !important;
  margin: 50px !important;
}

循环方法

Less中没有提供 for 循环功能,但可通过递归实现

/* Less */
.generate-columns(4);

.generate-columns(@n, @i: 1)when(@i =< @n) {
    .column-@{i} {
        width: (@i * 100% / @n);
    }

    .generate-columns(@n, (@i + 1));
}

/* 生成的 CSS */
.column-1 {
  width: 25%;
}
.column-2 {
  width: 50%;
}
.column-3 {
  width: 75%;
}
.column-4 {
  width: 100%;
}

属性拼接方法

+_ 代表的是空格;+代表的是逗号

>逗号

/* Less */
.boxShadow(){
	boex-shadow+: inset 0 0 10px #555;
}
.main {
	.boxshadow();
	box-shadow+: 0 0 20px balck;
}

/* 生成的 CSS */
.main {
  box-shadow: inset 0 0 10px #555, 0 0 20px balck;
}
>空格

/* Less */
.Animation(){
	transForm+_: scale(2);
}
.main {
	.Animation();
	transForm+_:  rotate(15deg);
}

/* 生成的 CSS */
.main {
  transForm: scale(2) rotate(15deg);
}

实战技巧

/* Less */
.average(@x, @y) {
    @average: ((@x+@y) / 2);
}

div {
    .average(16px, 50px);
    padding: @average
}

/* 生成的 CSS */
div {
  padding: 33px;
}

继承

extend关键字的使用

extend 是 Less 的一个伪类,它可继承所匹配声明中的全部样式

/* Less */
.animation {
    transform: all .3s ease-out;

    .hide {
        transform: scale(0);
    }
}
#main {
    &:extend(.animation);
}
#con {
    &:extend(.animation .hide);
}

/* 生成的 CSS */
.animation,#main {
  transform: all 0.3s ease-out;
}
.animation .hide,#con {
  transform: scale(0);
}

all全局搜索替换

使用选择器匹配到的全部声明

/* Less */
#main {
    width: 200px;
}
#main {
    &:after {
        content: 'less is good';
    }
}
#wrap:extend(#main all) {}

/* 生成的 CSS */
#main,
#wrap {
  width: 200px;
}
#main:after,
#wrap:after {
  content: 'less is good';
}

减少代码的重复性

extend 与方法最大的差别:是extend 是同个选择器共用同一个声明,而方法是使用自己的声明,这增加了代码的重复性。

方法与extend对比:

/* Less */
.Method {
    width: 200px;

    &:after {
        content: 'less is googd';
    }
}
#main {
    .Method
}

/* 生成的 CSS */
.Method {
  width: 200px;
}
.Method:after {
  content: 'less is googd';
}
#main {
  width: 200px;
}
#main:after {
  content: 'less is googd';
}

继承的使用要点

1、选择和扩展之间是允许有空格的:pre:hover :extend(div pre)

2、可以有多个扩展:pre:hover:extend(div pre):extend(.bucket tr),注意,这与pre:hover:extend(div pre,.bucket tr)一样

3、扩展必须在最后:pre:hover:extend(div pre).nth-child(odd)

4、如果一个规则集包含多个选择器,所有的选择器都可以使用 extend 关键字


导入

文件导入

导入Less文件,可省略后缀

import "main";
// 等价于
import "main.less";

@import 的位置可以随意放置

#main {
	font-size:15px;
}
@import "style";

reference

Less中最强大的特性,使用引入的Less文件,但不会编译它

/* Less */
@import (reference)"nav";

once

@import 语句的默认行为,这表明相同的文件只会被导入一次,而随后的导入文件的重复代码都不会解析。

/* Less */
@import (once)"nav";
@import (once)"nav"; // this statement will be ignored 

multiple

@import(multiple) 允许导入多个同名文件

/* Less */

//file foo.less
.a {
    color: red;
}

//file main.less
@import(multiple)"foo.less";
@import(multiple)"foo.less";

/* 生成的 CSS */
.a {
    color: red;
}
.a {
    color: red;
}

条件表达式

带条件的混合

  • 比较运算符:>,>=,=,=<,<

  • 格式:when( )

// lightness() 是检测亮度的函数,用%度量
.mixin(@a) when(lightness(@a)>=50%) {
    background:black;
}

.mixin(@a) when(lightness(@a)<50%) {
    background:white;
}
.mixin(@a){
	color:@a;
}
.class1{
	.mixin(#ddd);
}
.class2{
	.mixin(#555);
}

//编译输出
.class1 {
  background: black;
  color: #ddd;
}
.class2 {
  background: white;
  color: #555;
}

类型检测函数

检测值的类型

  • iscolor

  • isnumber

  • isstring

  • iskeyword

  • isurl

.mixin(@a:#fff; @b:0) when(isnumber(@b)) {
	color: @a;
    font-size: @b;
}

.mixin(@a;@b:#999) when(iscolor(@b)) {
	font-size: @a;
	color: @b;
}

单位检测函数

检测一个值除了数字是否是一个特定的单位

  • ispixel

  • ispercentage

  • isem

  • isunit

.mixin(@a) when(ispixel(@a)) {
    width: @a;
}

.mixin(@a) when(ispercentage(@a)) {
    width: @a;
}

.class1 {
    .mixin(960px);
}

.class2 {
    .mixin(95%);
}

//编译输出
.class1 {
  width: 960px;
}
.class2 {
  width: 95%;
}

函数

函数库

  • Less中封装了非常多函数库,例如颜色定义,颜色混合,字符串处理等

  • 例如:color( ):用于解析颜色,将代表颜色字符串转换为颜色值

body {
    color: color("#f60");
    background: color("red");
}

//编译输出
body {
  color: #f60;
  background: #ff0000;
}、
  • 例如:convert( ): 将数字从一种类型(单位)转换为另一种类型

  • 长度单位:m,cm,mm,in,pt,px,pc

  • 时间单位:s,ms

  • 角度单位:rad(弧度),deg(度),grad(梯度),tum(圆)

body {
    width: convert(20cm, px);
}

//编译输出
body {
  width: 755.90551181px;
}

>更多函数前往官网查看!https://less.bootcss.com/

  • 5