less基础
less是一个简单实用的css工具,它赋予了开发者编写动态css的能力:变量,继承,甚至函数等,很大程度上简化了css的开发且更容易维护
less基础
1. 嵌套
2. 变量
一、嵌套
我们可以在一个选择器中嵌套另一个选择器来实现继承,这样很大程度减少了代码量,并且代码开起来更加清晰
结合效果图来看这块的知识点,
比如考虑一个导航菜单结构,一个宽度通屏100%的盒子,包含一个居中的元素,里面在分左右的两个结构。
下面是导航的代码,在less里是怎样写呢?
<!doctype html> <html> <head> <meta charset="utf-8"> <title>导航菜单</title> <style> body{ margin: 0; } nav { height: 50px; line-height: 50px; background: #033333; } nav .content{ width:1200px; margin:0 auto; } .content .left{ float:left; } .content .right{ float:right; } a{ color:#fff; text-decoration:none; } </style> </head> <style> </style> <body> <nav> <div class="content"> <div class="left"> <a href="">Ruyic.com</a> <a href="">Css</a> <a href="">javasctipt</a> <a href="">jquery</a> </div> <div class="right"> <a href="">login</a> <a href="">register</a> </div> </div> </nav> </body> </html>
less的方式是直接在nav的花括号里,或者说nav作用域里写.content,代表nav是.content的父级,这样父子关系显着非常清晰
body{ margin: 0; } nav { height: 50px; line-height: 50px; background: #033333; .content{ width:1200px; margin:0 auto; .left{ float:left; } .right{ float:right; } } a{ color:#fff; text-decoration:none; } }
这样的方式叫做嵌套,把子级样式直接写在父级大括号里去,less编译后的css
body { margin: 0; } nav { height: 50px; line-height: 50px; background: #033333; } nav .content { width: 1200px; margin: 0 auto; } nav .content .left { float: left; } nav .content .right { float: right; } nav a { color: #fff; text-decoration: none; }
less里 & 符号代表什么意思呢?
现在我们给a标签加上一个hover的样式,鼠标放上去的时候变成红色,在less里有一个更简便的写法就是用&符号
body{ margin: 0; } nav { height: 50px; line-height: 50px; background: #033333; .content{ width:1200px; margin:0 auto; .left{ float:left; } .right{ float:right; } a{ color:#fff; text-decoration:none; //在这里"&"符号就代表了a标签本身 &:hover{ color:#e15617; } } //a:hover{color:red;}//这样写是可以的,但又回到了css里的写法,less里有更简便的写法,用&符号 } }
less编译后的css,可以看到a标签的下面就加上了hover样式,也就是说在这里&符号就代表了a标签本身
body { margin: 0; } nav { height: 50px; line-height: 50px; background: #033333; } nav .content { width: 1200px; margin: 0 auto; } nav .content .left { float: left; } nav .content .right { float: right; } nav .content a { color: #fff; text-decoration: none; } nav .content a:hover { color: #e15617; }
在.left上也可以入其它样式,
比如要给.left本身加上一个.padding-left这样一个class,
注意,.padding_left前要加&符号,不加&符号.padding_left会变成.left下的子级,而不是用在.left本身
body{ margin: 0; } nav { height: 50px; line-height: 50px; background: #033333; .content{ width:1200px; margin:0 auto; .left{ float:left; .padding-left{/* 注意,pading-left前没有加&符号 */ padding-left:20px; } } .right{ float:right; } a{ color:#fff; text-decoration:none; &:hover{ color:#e15617; } } } }
编译后.padding_left是.left下子级
body { margin: 0; } nav { height: 50px; line-height: 50px; background: #033333; } nav .content { width: 1200px; margin: 0 auto; } nav .content .left { float: left; } nav .content .left .padding-left { /*注意 .pading-left前没有加&符号*/ padding-left: 20px; } nav .content .right { float: right; } nav .content a { color: #fff; text-decoration: none; } nav .content a:hover { color: #e15617; }
要把.padding-left用在.left本身,必须加上&符号,在这里&就代表.left
body{ margin: 0; } nav { height: 50px; line-height: 50px; background: #033333; .content{ width:1200px; margin:0 auto; .left{ float:left; &.padding-left{ /* &.pading-left前加上了&符号 */ padding-left:20px; } } .right{ float:right; } a{ color:#fff; text-decoration:none; &:hover{ color:#e15617; } } } }
再看看编译后的CSS,.padding-left用在.left本身
body { margin: 0; } nav { height: 50px; line-height: 50px; background: #033333; } nav .content { width: 1200px; margin: 0 auto; } nav .content .left { float: left; } nav .content .left.padding-left { /* &.pading-left前加上了&符号 */ padding-left: 20px; } nav .content .right { float: right; } nav .content a { color: #fff; text-decoration: none; } nav .content a:hover { color: #e15617; }
二、变量
变量允许我们单独定义一系列通用的样式,然后在需要的时候去调用。所以在做全局样式调整的时候,我们可以只需要修改几行代码就可以了
定义变量语法
@ + name: 16px
变量名是 name
变量值是 16px
1、变量的基本使用
定义一个变量width,值为14
@width:14; // 定义好变量width,就可以在代码里使用了 .box{ width:@width; }
下面是编译后的css
.box { width: 14; }
上面解析后css里的变量没有加px单位,变量是可以参与计算的,
这里让变量乘以一个数字,变量14乘以1还等于14,后面的"1"带上像素单位,这样编译过去就带上了一个单位
@width:14; .box{ width:@width*1px; }
编译后的css就得到了一个14px
.box { width: 14px; }
使用变量时要注意加上单位,最好直接定义变量时就写好像素
@width:14px;//直接写好单位 .box{ width:@width; }
这样编译后就得到我们需要的样子
.box { width: 14px; }
写一个小例子,
有五个盒子都有边框,边框的的粗细,样式,颜色可能不一样,
1). 先把边框的大小、样式、颜色定义出来
2). 通过不同的组合,得到不同的代码
// 先把边框的大小、样式、颜色定义出来 @width:2px; @style:solid; @red:red; @blue:blue; // 通过不同的组合,得到不同的代码 .box1{ width:300px; height:200px; border:@width @style @red; } .box2{ width:300px; height:200px; border:@width @style @blue; } //背景颜色也用到了变量@red颜色 .box3{ width:300px; height:200px; background-color:@red; }
编译后的css,如果改变变量@red的值,那box02的边框,box03的背景也会跟着改变
.box1 { width: 300px; height: 200px; border: 2px solid red; } .box2 { width: 300px; height: 200px; border: 2px solid blue; } .box3 { width: 300px; height: 200px; background-color: red; }
2、变量的作用域
说到变量和变量相伴相生的一个东西叫作用域,字面上来看"域"意思是空间区域,
其实作用域就是变量发生作用的一个区域,这样一个区域其实就是一个花括号,一个花括号里就是一个作用域或作用范围。
.box里声明了一个变量@a,这个@a只能在这个括号里起作用,不能在括号的外边起作用,这就是它的作用范围
.box{ @a:10px; }
下面less代码中.box2里@a报错,错误是未定义,不能被编译,删除box2部分只保留box1可以通过编译
.box1{ @a:10px; .main{ width:@a;//只要在花括号里所包围,无论里面写多少层,都是没问题的 } } .box2{ width:@a; }
首先在.box2自己的作用域找这个@a,但是发现并没定义这个@a,再往外边全局的@a也找不到,
它会在.box2和全局的范围去找,绝对不会去.box1里去找@a,因为里面能看到外面,外面看不到里面,这是变量的一个作用域
三、混合(blend)
1、简单的混合
2、带参数的混合
5、参数带默认值的混合
考虑有这样一个布局,下面有5个div有一个共同点都有边框,边框的粗细、颜色、样式都是一样的,用less来写这样一个布局会有怎样一个方便的点
首先声明一个变量@border,用来写5个div有共同的部分border 1px solid #b7b7b7
@border:'border 1px solid #b7b7b7'; // 声明一个变量 // 注意,样用就报错了 // .box{ // @border;//这行报错了 // }
在属性值的地方调用变量
@border:'border 1px solid #b7b7b7'; .box{ border:@border;// 调用变量 }
编译出来的css
.box { border: 'border 1px solid #b7b7b7'; }
但这样的方式不是我们想要的方式,
我们想要的是变量@border存在一个东西里,用的时候直接调用就可以了,我们来看看混合(blend)
1、简单的混合
将一个定义好的.classA,引入到另一个.classB中,从而简单的实现classB继承classA中所有的属性
// 先定义一个classA .classA{ border:1px solid #b7b7b7; } // 再定义一个classB,在classB中引用classA .classB{ .classA; // 怎么引用呢?把classA直接放到classB里面 }
解析出来,classA样式被解析出来了,classB里也有了classA里的样式
.classA { border: 1px solid #b7b7b7; } .classB { border: 1px solid #b7b7b7; }
这样貌似满足了我们的需求,
5个div里都有一个共同的边框,把边框直接写在classA里,下面5个div调用这个classA就可以了,这是第一种最简单的混合方式
这个需求写css的时候是经常用的,最常用的就是清除浮动,
之前在页面中哪里有浮动,就给他的父级元素加上class="clearFix"清除浮动,在less里有混合不需要再页面里加clearFix样式了,直接在css里加上clearFix就可以了
下面用less写一个清除浮动的例子。需要注意,工具类要写在代码的上面,下面就可以调用到了
.clearFix{ *zoom:1; &:after{ content:''; display: block; clear:both; } } .classA{ border:1px solid #b7b7b7; } // 使用.classA和.clearFix .classB{ .classA; .clearFix; }
less解析后classB里继承了classA和清除浮动的样式了,不需要再页面当中加入清除浮动的class了
.clearFix { *zoom: 1; } .clearFix:after { content: ''; display: block; clear: both; } .classA { border: 1px solid #b7b7b7; } .classB { border: 1px solid #b7b7b7; *zoom: 1; } .classB:after { content: ''; display: block; clear: both; }
2、带参数混合(参数设置默认值)
参数是什么意思呢?
参数就是变量的意思,带着变量去混合这又是什么意思呢?
考虑这样一个问题,同样还是这5个div,
5个box都是1像素实心的边框,其中box02边框颜色不一样,还有box03边框粗细不一样
这时候less该怎么去面对?
.border带上一变量@color,颜色有下面调用时,想加什么颜色就加什么颜色
// border带上一变量@color .border(@color){ border:1px solid @color; } .box01{ .border(#b7b7b7); } .box02{ .border(red);// 这里解析出来是红色的边框 } .box03{ .border(#b7b7b7); } .box04{ .border(#b7b7b7); } .box05{ .border(#b7b7b7); }
解析后的css里传进去的颜色参数被应用到实际的属性里面了,想给他加什么颜色就加什么颜色,这是一个最简单的带参数的混合
.box01 { border: 1px solid #b7b7b7; } .box02 { border: 1px solid red; } .box03 { border: 1px solid #b7b7b7; } .box04 { border: 1px solid #b7b7b7; } .box05 { border: 1px solid #b7b7b7; }
但是我们的需求还有,box03的边框宽是3个像素,再来看看多个参数的混合
.border(@width ,@color){ border:@width solid @color; } .box01{ .border(1px,#b7b7b7); } .box02{ .border(1px ,red); } .box03{ .border(3px ,#b7b7b7); } .box04{ .border(1px,#b7b7b7); } .box054{ .border(1px,#b7b7b7); }
解析出来的css
.box01 { border: 1px solid #b7b7b7; } .box02 { border: 1px solid red; } .box03 { border: 3px solid #b7b7b7; } .box04 { border: 1px solid #b7b7b7; } .box054 { border: 1px solid #b7b7b7; }
同样我们还可以改变边的框样式solid变成dotted
.border(@width ,@style ,@color){ border:@width @style @color; } .box01{ .border(1px ,solid ,#b7b7b7); } .box02{ .border(1px ,solid ,red); } .box03{ .border(3px ,solid ,#b7b7b7); } .box04{ .border(2px ,dotted ,#b7b7b7); }
解析出来的css
.box01 { border: 1px solid #b7b7b7; } .box02 { border: 1px solid red; } .box03 { border: 3px solid #b7b7b7; } .box04 { border: 2px dotted #b7b7b7; }
声明混合 border(@width ,@style ,@color) 的时候写了多少个变量,
下面调用的时就要传多少个值一个都不能省,这样三个参数都要填写,还不如直接写原生的css呢,还要再解析一遍,
面对这样的情况less当然不会坐视不理,下面一种更好玩的方法叫有带默认值的参数混合。
3、带默认值的参数混合
有了参数默认值,有传值的时候就用传的值,没有传值就用默认值
// 定义两个变量,并且设置默认值 .border(@width:1px ,@style:solid){ border:@width @style #b7b7b7; } .box01{ .border(1px ,dotted);//这里改变了@style的默认值 } .box02{ .border(); } .box03{ .border(3px);//这里改变了@width默认值 } .box04{ .border(); } .box05{ .border(); }
解析出来的css
.box01 { border: 1px dotted #b7b7b7; } .box02 { border: 1px solid #b7b7b7; } .box03 { border: 3px solid #b7b7b7; } .box04 { border: 1px solid #b7b7b7; } .box05 { border: 1px solid #b7b7b7; }
带默认值的多个参数混合要注意一个问题,写了几个参数也要传几个值,
1). 如果只是改变第一个参数@width,后面的可以不传,
1). 但如果要改变第二个参数@style的时候,只传一个参数它并不会报错,但他会把width变成style
.border(@width:1px ,@style:solid){ border:@width @style #b7b7b7; } .box01{ .border(dotted);/* 这里出现错误的css */ } .box02{ .border(); } .box03{ .border(3px); } .box04{ .border(); } .box05{ .border(); }
解析出来的box01出现问题,要想改变box01的style,就要传两个值,第一个值是1px,第二个值是改变@stye
.box01 { border: dotted solid #b7b7b7; /*这里出现错误的css*/ } .box02 { border: 1px solid #b7b7b7; } .box03 { border: 3px solid #b7b7b7; } .box04 { border: 1px solid #b7b7b7; } .box05 { border: 1px solid #b7b7b7; }
带默认值多个参数的混合的时候,一定要注意的是带默认值的可以不传,但需要改变的时候就要传多个参数
arguments就代表了传进来的所有的参数,学过js有印象和js有一点点像
.boerder(@width:1px ,@style:solid){ border:@arguments #b7b7b7; // 这里arguments变量代表所有的参数。传一个参数就是一个参数,传两个参数的时候就两个参数 } .box01{ .boerder(2px); // 传一个参数的时候,@width用传的参数,@style用的是默认值 } .box02{ .boerder(1px ,dotted); // 传两个参数的时候@width和@style都用传的参数 } .box03{ .boerder();// 不传参数的时候用的都是默认值 }
解析的css
.box01 { border: 2px solid #b7b7b7; } .box02 { border: 1px dotted #b7b7b7; } .box03 { border: 1px solid #b7b7b7; }
注意arguments变量用的时候,要不在乎顺序的情况下才去使用。如果下面把两个变量互换位置,传的参数顺序不对也会出现问题
// 把两个变量互换位置 .boerder(@style:solid,@width:1px){ border:@arguments #b7b7b7; } .box01{ .boerder(); } .box02{ .boerder(1px ,dotted);// 这里是可以的 } .box03{ .boerder(2px); // 这里就出问题了 }
解析出来的css,box03出现了问题。
.box01 { border: solid 1px #b7b7b7; } .box02 { border: 1px dotted #b7b7b7; // 这里是可以的 } .box03 { border: 2px 1px #b7b7b7; // 这里就出问题了 }
arguments变量就代表了传进来的所有参数(在不在乎参数顺序的时候可以使用)
四、模式匹配
模式匹配和多个变量是差不多的,只不过在前面多加了一个条件
考虑一个需求,有四个div每个div都有一条边框,4个div的边框方向都不一样,这样的需求less应该怎样写?
.border(@width:1px){ border-top:@width solid #b7b7b7; } .box01{ .border(); } .box02{ .border();//box2边框需求是border-right方向 }
box2的需求是border-right方向的边框,属性名不能做变量,所以要用模式匹配解决,模式匹配是在前面,再加上一个值叫首参
// top是首参 .border(top ,@width:1px){ border-top:@width solid #b7b7b7; } // left也是首参 .border(right ,@width:1px){ border-right:@width solid #b7b7b7; } // 函数名称都是border,但是首参名不一样,里面的内容也有一点区别 .box01{ .border(top); } .box02{ .border(right, 2px); }
解析后
.box01 { border-top: 1px solid #b7b7b7; } .box02 { border-right: 2px solid #b7b7b7; }
这里的意思是
1). 把两个首参不同的函数border,当做一个函数去解析的
2). 解析这个函数的时候,要首先传入一个首参,这个首参是不可避免的,一定要传进去一个首参
3). 传的首参是那个就匹配那个border函数,同时在首参后面还可加入后面的变量@width
同样四个方向div边框,首参分别是top,right,bottom,left,每个调用都需要传入首参
.border(top ,@width:1px){ border-top:@width solid #b7b7b7; } .border(right ,@width:1px){ border-right:@width solid #b7b7b7; } .border(bottom ,@width:1px){ border-bottom:@width solid #b7b7b7; } .border(left ,@width:1px){ border-left:@width solid #b7b7b7; } // 每个调用都要传首参 .box01{ .border(top); } .box02{ .border(right,2px); } .box03{ .border(bottom); } .box04{ .border(left,2px); }
解析后每个box都有不同方向的border样式
.box01 { border-top: 1px solid #b7b7b7; } .box02 { border-right: 2px solid #b7b7b7; } .box03 { border-bottom: 1px solid #b7b7b7; } .box04 { border-left: 2px solid #b7b7b7; }
想一问题,
如果想让四个div都加上width:200,height:100,我们第一时间可能会想到的方案,是在每个div里写一遍要写四遍
这样的样式Less要怎么写呢?
1). 模式匹配里面有一个默认函数
2). 这个默认函数的前面需要一个默认的首参@_,并且这个首参是一个变量,这个变量没有用到任何地方
.border(top ,@width:1px){ border-top:@width solid #b7b7b7; } .border(right ,@width:1px){ border-right:@width solid #b7b7b7; } .border(bottom ,@width:1px){ border-bottom:@width solid #b7b7b7; } .border(left ,@width:1px){ border-left:@width solid #b7b7b7; } // 增加一个默认的函数,默认函数第一个参数需要一个首参"@_",并且这个首参是一个变量,这个变量没有用到任何地方 .border(@_ ,@width:1px){ width:200px; height:100px; } // 调用 .box01{ .border(top); } .box02{ .border(right,2px); } .box03{ .border(bottom); } .box04{ .border(left,2px); }
解析出来后的,4个div他们全部都加上同样的宽和高
.box01 { border-top: 1px solid #b7b7b7; width: 200px; height: 100px; } .box02 { border-right: 2px solid #b7b7b7; width: 200px; height: 100px; } .box01 { border-bottom: 1px solid #b7b7b7; width: 200px; height: 100px; } .box02 { border-left: 2px solid #b7b7b7; width: 200px; height: 100px; }
五、Math函数
数学里经常用到的函数
round(1.67) return:1
ceil(2.4) return:3
floor(2.6) return:2
.box1{ width:round(1.67)*1px; // 四舍五入等于2,后面乘以1px加上一个单位 } .box2{ width:ceil(2.4)*1px; // 向上取整 } .box3{ width:floor(2.6)*1px; // 向下取整 }
解析后
.box1 { width: 2px; } .box2 { width: 3px; } .box3 { width: 2px; }
页面上的计算也涉及不到太复杂的函数,这些函数足够使用了
六、命名空间
命名空间其实就是混合,好处是避免了命名上的冲突
声明一个.blue 里面有个 .buttom
声明一个.red 里面也有个 .buttom
这时候就形成一个封闭的命名空间,.blue里面的.buttom和.red里面的.buttom是不冲突的
.blue{ .button{ background:blue; } } .red{ .button{ background:red; } } // 两个button是不冲突的,调用button的时候可以这样用 .box01{ .blue > .button; } .box01{ .red > .button; .blue > .button; }
解析后的css
.blue .button { background: blue; } .red .button { background: red; } .box01 { background: blue; } .box01 { background: red; background: blue; }
这样做的好处避免了命名上的冲突,使用上也是非常方便的使用,可以定义多种不同样式风格去使用,
比如今天的我的主题是蓝色的,所以里面相关的东西都是蓝色的(背景,边框,渐变...),想换一个主题的时候,把 .blue> .buttom换成.red > .buttom
七、注释
// 单行注释,这种注释方法不会被编译到css里面去(通常用于生产环节)只能注释单行 /* 原生css注释,会解析到css文件里面去 */
八、import
@improt和css有一点点的相似,它是关联另外一个less文件
在去开发一个项目的时候,一般会写多个less文件,多个less文件的时候,比如写一个globe.less文件里面会写一些样式重置这些
// globe.less文件 body,h1,h2,h3,p{ margin: 0; } a{ text-decoration: none; } a:hover{ color:#f00; } ul{ list-style:none; padding: 0; margin: 0; } @rem:32rem; //globe里定义的变量
要去用globe.less文件,在页面上引用两个css文件
还可以这么做在less里引入globe.less文件
// blend.less文件 @import "globe.less"; // 如果globe是less文件可以不加.less后缀,可加可不加都是可以的 .box{ width:@rem; }
blend.less解析后是什么样的呢?
body, h1, h2, h3, p { margin: 0; } a { text-decoration: none; } a:hover { color: #f00; } ul { list-style: none; padding: 0; margin: 0; } .box { width: 32rem; }
这些都是globe.less的内容,在页面上引用的话,直接引用blend.less文件就可以了
还有一个重要的一个点,
在globe.less里写了一些变量的时候,在blend.less也是可以使用的,
比如globe.less里定义了一个变量@rem:32rem,在blend.less就不需要再定义了,这个变量他是全局的。
九、避免编译
平时再写less的时候,可能会遇到一些地方不希望被编译,比如这样一个font复合样式,大小20rem,行高20rem,宋体;
.box{ // font:12/px/20px '宋体'; // 这样写当然没有问题 // 在移动端换算的时候要换算一下除以@rem font:12/32rem/20/32rem '宋体';// 明显不是想要的结果 }
编译出来这明显不是想要的结果
.box { font: 12/32rem/20/32rem '宋体'; }
这样的情况怎么办呢?
1. (12/@rem),(20/@rem) 这两个分别用括号括起来
2. 中间的'/'是css自带的不是计算符号,这个符号是不需要被编译的
3. 把斜杠包起来并且前面加上~,避免编译了
@rem:32rem; .box{ font:(12/@rem)~'/'(20/@rem) '宋体'; }
这时候得的结果,才是我们想要的文字复合样式
.box { font: 0.375rem / 0.625rem '宋体'; }