What is LESS? LESS is a CSS preprocessor that enables customizable, manageable and reusable style sheets for websites. LESS is a dynamic style sheet language that extends the capabilities of CSS. LESS is also cross-browser friendly. A CSS preprocessor is a scripting language that expands CSS and compiles it into regular CSS syntax so it can be read by a web browser. It provides features such as variables, functions, mixins and actions to build dynamic CSS.
1. First experience of using Less
1. Use Less to write styles
Install Less globally using Npm
$ npm install less -g
Create an empty folder, named here:learn-less
Create an index.html file in the root directory, and copy the content as follows:
<!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>
Create a main.less file in the root directory, and copy the content as follows:
// main.less
@width: 100%;
@height: 100px;
@color: red;
.container{
width: @width;
height: @height;
background-color: @color;
margin-bottom: 5px;
}
.container2{
width: @width;
height: @height;
background-color: @color;
margin-bottom: 5px;
}
.container3{
width: @width;
height: @height;
background-color: @color;
margin-bottom: 5px;
}
Now open the browser and take a look, you will find that the style is not loaded. This is because the style file introduced in index.html is main.css instead of main.less. So next, we need to convert main.less to main.css, don't worry, this step does not require you to do it manually, just run a command and the conversion will be done automatically.
$ lessc main.less
After completing the above steps, you will find that a main.css file has been generated in the root directory. At this time, open the browser to see that the style has appeared.
The escaped content of main.css is:
.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;
}
If you use Webstorm as a development tool, you can skip the step of manually entering the command line, because Webstorm will automatically generate the corresponding .css file after your .less file is modified. For specific configuration jump: Webstorm configuration Less Automatically translate to css
2. Feel the convenience of Less
Now there is a new requirement, which needs to change the background color of the three divs to blue (blue). If it is the previous css writing method, you need to find container, container2, and container3 in sequence, and modify the background-color attribute in it accordingly, but use less We just modify the value of the variable defined earlier.
// main.less
@width: 100%;
@height: 100px;
@color: blue;
...
After translating using lessc main.less
to open the browser, you can see that the background colors of the three divs have been changed.
2. Variables
We often see the same value repeated many times in CSS, which makes the code difficult to maintain.
Ideally, it should look like this:
const bgColor="skyblue"; $(".post-content").css("background-color",bgColor); $("#wrap").css("background-color",bgColor); $(".arctive").css("background-color",bgColor);
As long as we modify bgColor
this variable, the background color of the entire page will change accordingly.
The variables in Less are very powerful and can change everything. It is worth mentioning that the variables are constants, so they can only be defined once and cannot be reused.
value variable
/* Less */ @color: #999; @bgColor: skyblue;//Do not add quotes @width: 50%; #wrap { color: @color; width: @width; } /* Generated CSS */ #wrap { color: #999; width: 50%; }
Variables are defined starting with @
, and the name is typed in directly when used @
.
In normal work, we can encapsulate commonly used variables into a file, which is conducive to code organization and maintenance.
@lightPrimaryColor: #c5cae9; @textPrimaryColor: #fff; @accentColor: rgb(99, 137, 185); @primaryTextColor: #646464; @secondaryTextColor: #000; @dividerColor: #b6b6b6; @borderColor: #dadada;
selector variable
Make the selector dynamic
/* Less */ @mySelector: #wrap; @Wrap: wrap; @{mySelector}{ //The variable name must be wrapped in braces color: #999; width: 50%; } .@{Wrap}{ color:#ccc; } #@{Wrap}{ color:#666; } /* Generated CSS */ #wrap{ color: #999; width: 50%; } .wrap{ color:#ccc; } #wrap{ color:#666; }
attribute variable
Can reduce the amount of code writing
/* Less */ @borderStyle: border-style; @Soild:solid; #wrap{ @{borderStyle}: @Soild;//The variable name must be wrapped in braces } /* Generated CSS */ #wrap{ border-style:solid; }
url variable
When the project structure changes, just modify its variables.
/* Less */ @images: "../img";//Need to add quotation marks body { background: url("@{images}/dog.png");//The variable name must be wrapped in braces } /* Generated CSS */ body { background: url("../img/dog.png"); }
declare variables
Somewhat similar to the hybrid approach below
- struct: @name: { attribute: value;}; - Use: @name();
/* Less */ @background: {background:red;}; #main{ @background(); } @Rules:{ width: 200px; height: 200px; border: solid 1px red; }; #con{ @Rules(); } /* Generated CSS */ #main{ background:red; } #con{ width: 200px; height: 200px; border: solid 1px red; }
variable operation
I have to mention that the variable operation of Less has completely exceeded my expectations and is very powerful.
- Add and subtract based on the unit of the first data - When multiplying and dividing, pay attention to the unit must be unified
/* Less */ @width:300px; @color:#222; #wrap{ width:@width-20; height:@width-20*5; margin:(@width-20)*5; color:@color*2; background-color:@color + #111; } /* Generated CSS */ #wrap{ width:280px; height:200px; margin:1400px; color:#444; background-color:#333; }
variable scope
One sentence understanding is: the principle of proximity
With the help of the Demo on the official website
/* Less */ @var: @a; @a: 100%; #wrap { width: @var; @a: 9%; } /* Generated CSS */ #wrap { width: 9%; }
use variables to define variables
/* Less */ @fnord: "I am fnord."; @var: "fnord"; #wrap::after{ content: @@var; //Replace @var with its value content:@fnord; } /* Generated CSS */ #wrap::after{ content: "I am fnord."; }
3. Nesting
The magic of &
& : The name of the upper-level selector represented, as in this example header
.
/* Less */ #header{ &:after{ content:"Less is more!"; } .title{ font-weight:bold; } &_content{//Understanding method: directly replace & with #header margin:20px; } } /* Generated CSS */ #header::after{ content:"Less is more!"; } #header .title{ //Nested font-weight:bold; } #header_content{//No nesting! margin:20px; }
media query
In previous work, we used media queries to write an element separately
#wrap{ width:500px; } @media screen and (max-width:768px){ #wrap{ width:100px; } }
Less provides a very convenient way
/* Less */ #main{ //something... @media screen{ @media (max-width:768px){ width:100px; } } @media tv { width:2000px; } } /* Generated CSS */ @media screen and (maxwidth:768px){ #main{ width:100px; } } @media tv{ #main{ width:2000px; } }
The only downside is that each element will compile its own @media
declaration and not be merged.
Practical skills
You can use Less to define your own private styles in elements.
/* Less */ #main{ // something.. &.show{ display:block; } } .show{ display:none; }
const main = document.getElementById("main"); main.classList.add("show");
result:
#main.show{ display:block; } .show{ display:none; //will be overwritten. }
4. Hybrid method
No parameter method
A method is like a collection of declarations, just type in the name when using it.
/* Less */ .card { // equivalent to .card() background: #f6f6f6; -webkit-box-shadow: 0 1px 2px rgba(151, 151, 151, .58); box-shadow: 0 1px 2px rgba(151, 151, 151, .58); } #wrap{ .card;//equivalent to .card(); } /* Generated CSS */ #wrap{ background: #f6f6f6; -webkit-box-shadow: 0 1px 2px rgba(151, 151, 151, .58); box-shadow: 0 1px 2px rgba(151, 151, 151, .58); }
where .card
and .card()
are equivalent.
Personal suggestion, in order to avoid code confusion, it should be written as:
.card(){ //something... } #wrap{ .card(); }
Main points: Both `.` and `#` can be used as method prefixes. Whether to write `()` after the method depends on personal habits.
default parameter method
Less can use default parameters, if no parameters are passed, then default parameters will be used.
@arguments
arguments
It's like referring to all parameters in JS .
The passed parameter must have a unit.
/* Less */ .border(@a:10px,@b:50px,@c:30px,@color:#000){ border:solid 1px @color; box-shadow: @arguments;//Refers to all parameters } #main{ .border(0px,5px,30px,red);//Must have units } #wrap{ .border(0px); } #content{ .border;//equivalent to .border() } /* Generated 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; }
method matching pattern
Very similar to polymorphism in object-oriented
/* Less */ .triangle(top,@width:20px,@color:#000){ border-color:transparent transparent @color transparent ; } .triangle(right,@width:20px,@color:#000){ 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:20px,@color:#000){ border-style: solid; border-width: @width; } #main{ .triangle(left, 50px, #999) } /* Generated CSS */ #main{ border-color:transparent transparent transparent #999; border-style: solid; border-width: 50px; }
main point
- The first parameter `left` will find the method with the highest matching degree. If the matching degree is the same, all will be selected, and there will be a style override replacement. - Will match if the matched argument is a variable, such as `@_`.
method namespace
Make the method more standardized
/* Less */ #card(){ background: #723232; .d(@w:300px){ width: @w; #a(@h:300px){ height: @h;//You can use the method passed in from the previous layer width: @w; } } } #wrap{ #card > .d > #a(100px); // parent element cannot add brackets } #main{ #card .d(); } #con{ //Must not use namespaced methods alone //.d() If the namespace #card is not introduced earlier, an error will be reported #card; // equivalent to #card(); .d(20px); //Must introduce #card first } /* Generated CSS */ #wrap{ height:100px; width:300px; } #main{ width:300px; } #con{ width:20px; }
main point
- In CSS, the `>` selector selects the child element, that is, the element that must have a direct blood source with the parent element. - When introducing a command space, such as using the `>` selector, the parent element cannot be parenthesized. - A method that cannot use a namespace alone must first introduce a namespace before using its methods. - The sub-method can use the method passed in from the previous layer
Conditional filter of the method
Less doesn't have if else, but it has when
/* Less */ #card{ // The and operator is equivalent to the AND operation &&, and it will only be executed if all conditions are met .border(@width,@color,@style) when (@width>100px) and(@color=#999){ border:@style @color @width; } // not operator, equivalent to not operation!, will be executed only if the condition is not met .background(@color) when not (@color>=#222){ background:@color; } // , comma separator: equivalent to OR operation ||, as long as one of the conditions is met, it will be executed .font(@size:20px) when (@size>50px) , (@size<100px){ font-size: @size; } } #main{ #card>.border(200px,#999,solid); #card .background(#111); #card > .font(40px); } /* Generated CSS */ #main{ border:solid #999 200px; background:#111; font-size:40px; }
main point
- Comparison operations are: > >= = =< <. - = represents equal to - Values other than the keyword true are considered false:
variable number of parameters
If you want your method to accept a variable number of arguments, you can use ... , like the ES6 spread operator.
/* Less */ .boxShadow(...){ box-shadow: @arguments; } .textShadow(@a,...){ text-shadow: @arguments; } #main{ .boxShadow(1px,4px,30px,red); .textShadow(1px,4px,30px,red); } /* Generated CSS */ #main{ box-shadow: 1px 4px 30px red; text-shadow: 1px 4px 30px red; }
The method uses the important!
The method of use is very simple, just add keywords after the method name.
/* Less */ .border{ border: solid 1px red; margin: 50px; } #main{ .border() !important; } /* Generated CSS */ #main { border: solid 1px red !important; margin: 50px !important; }
loop method
Less does not provide a for loop function, but it is not difficult for smart programmers to use recursion to achieve it.
The following is a demo on the official website, which simulates the generated grid system.
/* Less */ .generate-columns(4); .generate-columns(@n, @i: 1) when (@i =< @n) { .column-@{i} { width: (@i * 100% / @n); } .generate-columns(@n, (@i + 1)); } /* Generated CSS */ .column-1 { width: 25%; } .column-2 { width: 50%; } .column-3 { width: 75%; } .column-4 { width: 100%; }
Five, function
Once upon a time, when writing dull css, did you think about making the class name dynamic and generating different styles according to different parameters. See the example below:
// func.less
.border-radius(@radius) {
-webkit-border-radius: @radius;
-moz-border-radius: @radius;
border-radius: @radius;
}
#header {
.border-radius(4px);
}
.button {
.border-radius(6px);
}
Use $ lessc func.less
to translate the contents of the func.css file as follows:
#header {
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
.button {
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
border-radius: 6px;
}
It can be seen that the concept of function is used here, #header
and .button
different parameters are passed in and respectively, and different codes are generated as a result.
There are several ways to write functions in 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) {
Of course, the above are functions customized by developers, and Less also defines many useful built-in functions for us. Regarding built-in functions, if you master them, you can save a lot of time in the development process. Since there are a lot of built-in functions, I won’t introduce them one by one here. Portal: Official documentation of Less built-in functions .
6. The writing method of parent and child elements
Parent-child elements are usually written as follows in css:
.container {
padding: 0;
}
.container .article {
background-color: red;
}
In Less, the writing method is as follows, and the parent-child nesting relationship is clear at a glance.
.container {
padding: 0;
.article {
background-color: red;
}
}
Of course, parent-child elements also need a pseudo-class writing method, which is written in css as follows:
#header :after {
content: " ";
display: block;
font-size: 0;
height: 0;
clear: both;
visibility: hidden;
}
The writing method in less is as follows, you can see that a new symbol has been introduced to&
replace the main class .&
#header
#header {
&:after {
content: " ";
display: block;
font-size: 0;
height: 0;
clear: both;
visibility: hidden;
}
}
7. Magical @import
In traditional css files, each file is independent. In less, you can introduce another less file in a less file like a js module.
Create the one.less file:
.container {
width: 100px;
height: 200px;
}
Create the two.less file:
@import "one";
Use $ lessc two.less
Translate two.css
a file, you can see the content as follows:
.container {
width: 100px;
height: 200px;
}
The role of @import can be seen as copying the contents of one.less to the current .less file.
8. Others
-
note
- /* */ CSS native comments will be compiled in the CSS file.
- // A comment provided by Less, which will not be compiled in the CSS file.
- avoid compiling
/* Less */ #main{ width:~'calc(300px-30px)'; } /* Generated CSS */ #main{ width:calc(300px-30px); }
Structure: `~'value'`
3. Avoid compiling
Because Less is written in JS, Less has a unique feature: Javascript is used in the code.
/* Less */ @content:`"aaa".toUpperCase()`; #randomColor{ @randomColor: ~"rgb(`Math.round(Math.random() * 256)`,`Math.round(Math.random() * 256)`,`Math.round(Math.random() * 256)`)"; } #wrap{ width: ~"`Math.round(Math.random() * 100)`px"; &:after{ content:@content; } height: ~"`window.innerHeight`px"; alert:~"`alert(1)`"; #randomColor(); background-color: @randomColor; } /* Generated CSS */ // pop 1 #wrap{ width: random value (0~100)px; height: 743px;//Varies by computer background: random color; } #wrap::after{ content:"AAA"; }