Less是一种动态样式语言;为提高css应用的灵活性和效率,LESS 将 CSS 赋予了动态语言的特性,如 变 量, 继承, 运算, 函数。LESS 既可以在 客户端 上运行 (支持IE 6+, Webkit, Firefox),也可以借助 Node.js在服务端运行。
作为前端学习者的我们都要学些 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 更易维护、方便制作主题、扩充。
Less 是一门 CSS 预处理语言,它扩展了 CSS 语言,增加了变量、Mixin、函数等特性,使 CSS 更 易维护和扩展。 Less 扩充了 CSS 语言,增加了诸如变量、混合(mixin)、运算、函数等功能。 Less 既可以运行在服务 器端(Node.js 和 Rhino 平台)也可以运行在客户端(浏览器)。 在 Node.js 环境中使用 Less :
npm i less
在浏览器环境中使用 Less :
<link rel="stylesheet/less" type="text/css" href="styles.less" />
<script src="https://cdn.jsdelivr.net/npm/less@4" >script>
//这种注释,在编译后不会出现在CSS文件上
/*这种注释,编译后会出现在CSS文件上*/
我们常常在 CSS 中 看到同一个值重复多次,这样难易于代码维护。 理想状态,应是下面这样:
//js实现
const bgColor="skyblue";
$(".post-content").css("background-color",bgColor);
$("#wrap").css("background-color",bgColor);
$(".arctive").css("background-color",bgColor);
只要我们修改 bgColor 这一个变量, 整个页面的背景颜色都会随之改变。而 Less 中的变量十分强 大,可化万物,值得一提的是,其变量是常量 ,所以只能定义一次,不能重复使用。
@a:#fff
,a通过@标识为一个变量。属性取值可以直接通过@a使用这个变量
/* 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;
@{mySelector}
将变量的值作为选择器来使用
/* 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 */
@images: "../img";//需要加引号
body {
background: url("@{images}/dog.png");//变量名 必须使用大括号包裹
}
/* 生成的 CSS */
body {
background: url("../img/dog.png");
}
有点类似于下面的混合方法:
@name: { 属性: 值 ;};
@name();
//声明式变量
@common:{
background-color: aquamarine;
font-size: 19px;
}
#main{
//使用声明式变量
@common();
}
/** css样式**/
#main {
background-color: aquamarine;
font-size: 19px;
}
不得不提的是,Less 的变量运算十分强大。
// 变量的基本运算 + - * /
@commonLi:ul>li;
@size:13px;
@color:#222;
@width:100px;
@borderAbout:{
border:1px solid #ccc
}
@{commonLi} {
color: @color+10; //2c2c
font-size: @size+10; //23px;
width: @width+100;
@borderAbout();
}
/** css效果 **/
ul > li {
color: #2c2c2c;
font-size: 23px;
width: 200px;
border: 1px solid #ccc;
}
// 变量的作用域
@var:@a;
@a:100;
#wrap{ //就近原则
width: @a;
@a:43%;
}
/** css效果 **/
#wrap {
width: 43%;
}
// 用变量去定义变量
@content:@b;
@b:'i am not found';
#wrap::after{
content:@content;
}
/** css效果 **/
#wrap::after {
content: 'i am not found';
}
如果想要给选择器的子选择器添加样式,需要另外在子选择器里面写。而在less里面,直接可以在父选择器里面写子选择器的样式,和html的嵌套相似。
// 选择器嵌套 &代表父级 可以省略
.center{
width: 200px;
background-color: aquamarine;
ul{
width: 170px;
& li{ //&代表当前li的父级
list-style: none;
text-shadow: 0px 0px 1px 1px;
}
}
}
/** css样式**/
.center {
width: 200px;
background-color: aquamarine;
}
.center ul {
width: 170px;
}
.center ul li {
list-style: none;
text-shadow: 0px 0px 1px 1px;
}
正常的css写法:
#wrap{
width:500px;
}
//媒体类型为屏幕 并且要满足 最大宽度为768
@media screen and (max-width:768px){
#wrap{
width:100px;
}
}
使用less的写法:符合@规则
//使用less
#wrap{
width:500px;
@media screen{
@media (max-width:768px){
width:100px;
}
}
}
@规则说明:
@ 规则(例如 @media
或 @supports
)可以与选择器以相同的方式进行嵌套。
@ 规则会被放在前面,同一规则集中的其它元素的相对顺序保持不变。这也叫做冒泡(bubbling)。
代码如下:
//less
body{
background-color: aliceblue;
@media screen{
@media (max-width:500px){
background-color:skyblue;
}
}
}
//编译后的css
body {
background-color: aliceblue;
}
@media screen and (max-width: 500px) {
body {
background-color: skyblue;
}
}
可以借助 Less 在元素中,去定义自己的私有样式。
/* Less */
#main{
// something..
&.show{
display:block;
}
}
.show{
display:none;
}
/** css**/
#main.show { //优先级高
display: block;
}
.show {
display: none;
}
const main = document.getElementById("main");
main.classList.add("show");
也称混合方法,和编程语言中的方法差不多。
// .card(){} 括号可以省略 调用:.card/.card()
//如果省略括号,既可以作为普通类样式使用,又可以作为无参方法使用
.card() {
background-color: transparent;
box-shadow: 0px 0px 1px silver;
border: 1px solid silver;
}
#wrap {
font-size: 19px;
//调用方法 .card()
.card;
}
/** css**/
#wrap {
font-size: 19px;
background-color: transparent;
box-shadow: 0px 0px 1px silver;
border: 1px solid silver;
}
其中 .card 与 .card() 是等价的。 建议,为了避免代码混淆,应写成 .card()
。此外,如果写成.card
也会作为正常的css输出,如果是函数则不会被输出,调用的时候,解析的地方输出。
// 默认参数
//参数里面定义变量并且声明值
.borderSet(@a: 3px, @b: 2px, @c: 1px, @color: #dfdfdf) {
color: @color;
//@argument 接收传递的所有参数
box-shadow: @arguments;
}
.border {
.borderSet()
}
/** css **/
.border {
color: #dfdfdf;
box-shadow: 3px 2px 1px #dfdfdf;
}
与面向对象中的多态很相似,根据方法参数进行匹配。所以要求定义的方法,必须能够有区分的。如:小三角案例
//less
// 方法的匹配模式
//如不同方向的三角形
.triangle(top, @width: 10px, @color: #927070) {
border-color: transparent transparent @color transparent;
}
.triangle(right, @width: 10px, @color: #927070) {
border-color: transparent transparent transparent @color;
}
.triangle(bottom, @width: 10px, @color: #927070) {
border-color: @color transparent transparent transparent;
}
.triangle(left, @width: 10px, @color: #927070) {
border-color: transparent @color transparent transparent;
}
//匹配所有方向的方法设置
.triangle(@_, @width: 10px, @color: #927070) {
border-style: solid;
border-width: @width;
}
//调用方法
.tri {
.triangle(top, 50px, #dfdfdf)
}
/** =========css==============**/
.tri {
border-color: transparent transparent #dfdfdf transparent;
border-style: solid;
border-width: 50px;
}
要点
为了让方法更加规范,方法的命名空间一般不需要加括号的,且不同命名空间可以定义相同的方法。
通过>
选择命名空间的下一级,当然可以省略
直接通过命名空间引出下一级
如果命名空间直接调用了,则可以省略命名空间,调用下一级
/* 方法命名空间 */
.nav-set{
.font{
.small(@size:10px){
font-size: @size;
}
.big(@size:20px){
fong-size:@size
}
}
.color(@color:#ccc){
color: @color;
}
}
//调用
.nav{
.nav-set > .font > .small(5px);
.nav-set .color(#666); // 省略 >
}
//或者
.nav{
.nav-set(); //直接调用命名空间
.font .small(5px); //省略命名空间
.color(#666); //省略命名空间
}
css的样式如下:
.nav {
font-size: 5px;
color: #666;
}
只有满足方法的条件才能执行此方法,是通过以下的内置函数来完成的。
when(条件)
判断条件是否满足,如果满足执行对应的方法and(条件)
表示且,通常和when配置使用when not (条件)
:和条件相反when(条件1),(条件2)
条件1或者条件2满足即可#banner(){
// when and
.border-condition(@width:100px,@color) when (@width<=300px) and (@color=#ccc){
border: @width solid #ccc;
}
// when not
.color-condition(@color) when not(@color>#ccc){
color: @color;
}
//, 表示 ||
.font-condition(@size:10px) when (@size<100px),(@size>10px){
font-size:20px;
}
}
//调用
#C{
#banner();
.border-condition(140px,#ccc);
.color-condition(#fff);
.font-condition(20px);
}
编译后的css: 尝试改变条件,如果不满足,则不会输出对应的。
#C {
border: 140px solid #ccc;
color: #fff;
font-size: 20px;
}
如果你希望你的方法接受数量不定的参数,你可以使用...
,犹如 ES6 的扩展运算符。
// 不定长参数
.box-shadow(...){
box-shadow: @arguments;
}
.text-shadow(@a,...){
text-shadow: @arguments;
}
p{
.box-shadow(1px,#ccc);
.text-shadow(2px,3px,#aaa)
}
//=======css输出
p {
box-shadow: 1px #ccc;
text-shadow: 2px 3px #aaa;
}
方法中定义的属性样式,会全部加上!important
// !important
.ant(){
text-align: center;
line-height: 20px;
}
.specail{
.ant() !important;
}
//======css
.special {
text-align: center !important;
line-height: 20px !important;
}
方法中没有像for的使用,一般使用递归完成循环。如下:完成建议栅格化
// 方法中递归调用 实现循环 如栅格化
.generator-col(@n,@i:1) when (@i<@n){
.column-@{i} {
width: (@i*100% /@n);
}
//递归调用
.generator-col(@n,@i+1);
}
.generator-col(4);
//======css
.column-1 {
width: 25%;
}
.column-2 {
width: 50%;
}
.column-3 {
width: 75%;
}
当设置两个相同的属性样式,想要拼接时,可以使用以下关键字:
+_
代表的是 空格;
+
代表的是 逗号。
代码实现如下
.box{
// 相同属性 通过+继续逗号拼接
box-shadow+:-1px 1px 0px #dfdfdf;
box-shadow+:1px -3px 2px #666;
// 相同属性 通过+_进行空格拼接
transform+_: scale(30deg) ;
transform+_: translateX(30px);
}
//css=======
.box {
box-shadow: -1px 1px 0px #dfdfdf, 1px -3px 2px #666;
transform: scale(30deg) translateX(30px);
}
封装一个方法,求平均值
// 实战技巧 求平均值
.average(@a,@b){
@average:((@a+@b) /2);
}
p{
.average(100px,30px);
padding: @average;
}
//css=======
p {
padding: 65px;
}
less通过配合extend关键字使用,能够使得多个元素共用同一个样式,生成的css其实是逗号隔开的联合选择器,如p,div{}。相比较混入函数而已,生成的代码简洁,不重复定义。
// less中extend其实就是一个伪类的使用,需要配合&的使用
.common {
transform: translateX(30px);
//嵌套
.hide {
transform: translateX(-100px);
}
//嵌套
&:after {
content: 'less is good';
}
}
.main {
//复用
&:extend(.common);
}
//.main:extend(.common){} 可以这样
.icon {
//复用
&:extend(.common);
}
编译后的css:
.common,
.main,
.icon {
transform: translateX(30px);
}
.common .hide {
transform: translateX(-100px);
}
.common:after {
content: 'less is good';
}
通过继承实现如下:
/* Less */
#main {
width: 200px;
}
#main {
&:after {
content: "Less is good!";
}
}
#wrap:extend(#main all) {}
编译后的css
/* Less */
#main,
#wrap {
width: 200px;
}
#main:after,
#wrap:after {
content: "Less is good!";
}
通过方法实现如下:
/* ======方法========= */
/* Less */
.Method() {
width: 200px;
&:after {
content: "Less is good!";
}
}
#main {
.Method;
}
#wrap {
.Method;
}
编译后的css:
/* ======方法========= */
/* Less */
#main,
#wrap {
width: 200px;
}
#main:after,
#wrap:after {
content: "Less is good!";
}
#wrap {
width: 200px;
}
#wrap:after {
content: "Less is good!";
}
从表面 看来,extend 与 方法 最大的差别,就是 extend 是同个选择器共用同一个声明,而 方法 是使用 自己的声明,这无疑 增加了代码的重复性。extend使得编译后的css减少了代码的重复。
将同事写的less文件合并一个。
@import "main";
//等价于
@import "main.less";
@import 的位置可随意放置。
#main{
font-size:15px;
}
@import "style";
Less 中 最强大的特性 使用 引入的 Less 文件,但不会编译它。
/* Less */
@import (reference) "bootstrap.less";
@import语句的默认行为。这表明相同的文件只会被导入一次,而随后的导入文件的重复代码都不会解 析。
@import (once) "foo.less";
@import (once) "foo.less"; // this statement will be ignored
使用@import (multiple)允许导入多个同名文件。
/* Less */
// file: foo.less
.a {
color: green;
}
// file: main.less
@import (multiple) "foo.less";
@import (multiple) "foo.less";
/* 生成后的 CSS */
.a {
color: green;
}
.a {
color: green;
}
less内置了许多函数,常用的如下:
带基本条件的 如:when,具体参考官网。
带类型的:判断是否数字isNumber()
,字符串isString()
,urlisUrl
,颜色isColor()
…
// 写一个方法,根据参数类型来赋值
.nav-set(@a,@b) when(isColor(@a)){
color:@a;
width: @b;
}
.nav-set(@a,@b) when(isNumber(@a)){
color:@b;
width: @a;
}
.nav{
.nav-set(13px, #ccc);
& li{
.nav-set(#ccc,13px);
}
}
//css=======
.nav {
color: #ccc;
width: 13px;
}
.nav li {
color: #ccc;
width: 13px;
}
带单位的:监测一个值除了数字外,是否带有单位 ispixel(), ispercentage(), isem()
.nav-width(@width) when (ispixel(@width)),(ispercentage(@width)){
width: @width;
}
.nav{
.nav-width(40%);
}
//css
.nav {
width: 40%;
}
带转换的
color(颜色字符串)
将 带有颜色的字符串转成带有颜色的十六进制值
convert(a,单位)
:将a转成其它单位 如:px——>cm
div{
color:color("red");
font-size:convert(14px,cm);
}
//css=======
div {
color: #ff0000;
font-size: 0.37041667cm;
}