About CSS preprocessors: SASS, LESS, stylus

1. Introduction: CSS stylesheet is mainly a description of the style attribute, write up considerable trouble, therefore, CSS preprocessor defines a new language, its basic idea is to use a specific programming language, for CSS adds some features of programming, the CSS as target generated file, then developers as long as the use of this language coding work. In layman’s terms, CSS preprocessors style Web pages in a specialized programming language and then compile them into normal CSS files for use by projects. CSS preprocessor for CSS to add some features of programming, without considering the browser compatibility problems, for example, you can use the variable in the CSS, simple logic procedures, functions and so on in some of the basic features of the programming language, can let your CSS more concise, more flexible, better readability, more easy to code maintenance, and many other benefits.

2. The syntax.

The less syntax is the same as the traditional writing

/* style.scss or style.less */
p {
  color: #ffffff;
}
Copy the code

Sass also supports traditional CSS syntax, but without curly braces

/* style.sass old syntax */ p color:# FFFFFF /*style.scss sass3.0 new syntax */ h1{color:#936; background-color:#333; }Copy the code

Stylus grammar

/* style.styl */ /* style.styl */ } /* omit brackets */ p color: # FFFFFF; /* omit colons and semi-colons */ p color # FFFFFFCopy the code

In Stylus styles, you can also use different syntax rules in the same style file.

3.Sass, LESS, and Stylus features

  • variable

You can declare variables in CSS preprocessing and use them throughout the stylesheet, supporting any type of variable, for example: color, value (whether it contains units or not), text. You can then call and use this variable as you like

Sass variables must start with $, and the variable name and value must be separated by a colon, in the same way CSS properties are written.

$mainColor: #0982c1;
$siteWidth: 1024px;
$borderStyle: dotted;
 
body {
  color: $publicColor;
  border: 1px $borderStyle $mainColor;
  max-width: $siteWidth;
}
Copy the code

Variable names for Less start with the @ sign:

@mainColor: #0982c1;
@siteWidth: 1024px;
@borderStyle: dotted;
 
body {
  color: @publicColor;
  border: 1px @borderStyle @mainColor;
  max-width: @siteWidth;
}
Copy the code

The Stylus has no restrictions on the name of a variable. You can start with $or any character, and separate the variable from the value with colons or Spaces. Note that Stylus (0.22.4) compiles a variable that starts with @, but does not assign the corresponding value to that variable. Do not start variable names in Stylus with @.

mainColor = #0982c1
siteWidth = 1024px
$borderStyle = dotted
 
body
  color mainColor
  border 1px $borderStyle mainColor
  max-width siteWidth
Copy the code

The result is the same:

body {
  color: #0982c1;
  border: 1px dotted #0982c1;
  max-width: 1024px;
}
Copy the code

Stylus also has a unique ability to define reference properties without assigning values to variables:

Horizontal vertical center / * * / | / * * out of the CSS / -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - # # logo logo | { position absolute | position:absolute; top 50% | top:50%; left 50% | left:50%; width w = 150px | width:150px; height h = 80px | height:80px; margin-left -(w / 2) | margin-left:-75px; margin-top -(h / 2) | margin-top:-40px; |}Copy the code
  • scope

CSS preprocessor variables in language and other languages, can realize the value of reuse, it also exists the life cycle, which is the Scope (variable Scope, developers used to call it Scope), the simple point is the concept of local variable or a global variable, find the variable sequence is to find in local definition first, if you cannot find, Then look up the superior definition, all the way to global. Let’s use a simple example to explain the scope usage of these three CSS preprocessors.

A) Scope of Sass

The scope of Sass is the worst among the three preprocessors, so there is no global variable in Sass. Look at the following code:

/*Sass */ $color: black; .scoped { $bg: blue; $color: white; color: $color; background-color:$bg; } .unscoped { color:$color; }Copy the code

First look at the translated CSS style:

.scoped { color:white; /* is white */ background-color:blue; } .unscoped { color:white; /* White (no global variable concept) */}Copy the code

The example clearly shows that when defining a variable in Sass style, there is no concept of a global variable in calling a variable. Therefore, when defining the same variable name in Sass, you must be careful when calling it, otherwise you will introduce errors in your style.

B) Scope of LESS

The scope in LESS is very much the same as the scope in other programming languages. It first looks for a locally defined variable, and if it doesn’t find one, it bubbles down to the root. In the same example above, let’s see what it does under LESS.

/*LESS */ @color: black; .scoped { @bg: blue; @color: white; color: @color; background-color:@bg; } .unscoped { color:@color; }Copy the code

Translated CSS styles:

.scoped { color:white; /* white (local variable called) */ background-color:blue; } .unscoped { color:black; /* black (global variable called) */}Copy the code

C) Scope of Stylus

Stylus, though a late starter, has the same scoped properties as LESS, supporting both global and local variables. It bubbles up to the root.

  • Hybrid (Mixins)

Mixins are one of the most powerful features of the CSS preprocessor language. In simple terms, Mixins can be used repeatedly by many selectors by pulling out styles as individually defined modules. If you’re writing a CSS style, you’ll have to repeat it multiple times. In CSS preprocessor language, you can define a Mixin for these common CSS styles and then call your Mixin directly where your CSS needs to use those styles. This is a very useful feature, Mixins are treated as a recognized selector, and you can also define variables or default parameters in Mixins.

A) a mixture of Sass

The Sass style declares Mixins using “@mixin”, followed by the name of the Mixins. It can also define parameters, which can be given a default value, but the parameter name starts with a “$” sign and is separated from the parameter value by a colon (:).

To call a defined Mixins in a selector, use @include, followed by the name of the Mixins you are calling. However, Sass also supports the old method of calling Mixins using the plus sign “+” followed by the name of the Mixins.

Let’s take a simple example. For example, if you define a Mixin named “error” in your Sass style, this “error” sets the parameter “$borderWidth”, which defaults to “2px” unless specified:

/* Declare a Mixin called "error" */ @mixin error($borderWidth:2px){border:$borderWidth solid #f00; color: #f00; } /* Call error Mixins*/.generic-error {@include error(); /* call error mixins*/}.login-error {@include error(5px); /* Call error mixins and redefine the value of $borderWidth to 5px*/}Copy the code

B) a mixture of LESS

In LESS, blending means adding another already-defined “Class” to the defined “ClassA”, just as adding an attribute to the current “Class”.

In LESS, Mixins can be treated as a class selector. Of course, Mixins can also set parameters and set default values for the parameters. However, the variable name of the setting parameter starts with “@” and is separated from the default parameter value by a colon (:).

As in the Sass Mixin example, also define a Mixin named “error” in the LESS style. This “error” sets a parameter “@borderWidth”, which defaults to “2px” unless otherwise specified:

/* Declare a Mixin called "error" */. Error (@borderwidth :2px){border: @borderwidth solid #f00; color: #f00; } /* Call error Mixins*/.generic-error {.error(); /* Call error mixins*/}.login-error {.error(5px); /* Call error mixins and redefine @borderWidth to 5px*/}Copy the code

C) a mixture of Stylus

The mixing in Stylus is slightly different from the mixing in the previous two CSS preprocessor languages, which can be done without any symbols, simply declaring the Mixins name and then concatenating the definition parameter with an equal sign (=) between the default value.

/* Declare a Mixin called "error" */ error(borderWidth=2px){border:borderWidth solid #f00; color: #f00; } /* Call error Mixins*/.generic-error {error(); /* Call error mixins*/}.login-error {error(5px); /* Call error mixins and redefine the value of $borderWidth to 5px*/}Copy the code

All three examples will translate to the same CSS code:

.generic-error {
 border: 2px solid #f00;
 color:#f00;
}
.login-error {
 border:5px solid #f00;
 color: #f00;
} 
 
Copy the code
  • Nesting

Nesting in THE CSS preprocessor language refers to nesting a selector within another selector to implement inheritance, thus reducing the amount of code and increasing the readability of code. For example, if multiple elements in CSS have the same parent, writing styles becomes tedious and we need to write the parent over and over again in front of each element, unless we add the class name “class” or ID to a particular element.

section {
 margin:10px;
}
section nav {
 height:25px;
}
section nav a {
 color: #0982c1;
}
section nav a:hover {
 text-decoration: underline;
} 
Copy the code

Instead, using the nesting feature of the CSS preprocessor language, we can write these elements inside curly braces ({}) of their parent elements. The parent selector can also be referenced using the ampersand symbol. For nested selectors for the CSS preprocessor languages Sass, LESS, and Stylus, they all have the same syntax:

section { margin:10px; nav { height:25px; a { color:#0982c1; &:hover { text-decoration:underline; }}}}Copy the code

The CSS code translated by the preprocessor above is the same as the CSS code we showed at the beginning, very convenient!

Inheritance by Inheritance

For those familiar with CSS, inheritance of attributes is no stranger. When writing CSS styles, we often encounter multiple elements applying the same style. We usually write CSS like this:

P,ul,ol{/* style here */Copy the code

This is all well and good, but often we need to add styles to individual elements. In this case, we need to write styles separately from the selectors in the elements, which can be quite troublesome to maintain the styles. To deal with this, the CSS preprocessor language can inherit all styles from one selector to another.

A) Inheritance of Sass and Stylus

Inheritance of Sass and Stylus is the inheritance of all styles from one selector to another. To inherit another selector’s style, start with “@extend”, followed by the inherited selector:

.block {

  margin: 10px 5px;

  padding: 2px;

}

p {

  @extend .block;/*继承.block选择器下所有样式*/

  border: 1px solid #eee;

}

ul,ol {

  @extend .block; /*继承.block选择器下所有样式*/

  color: #333;

  text-transform: uppercase;

}	
Copy the code

The above code translates to CSS:

.block,p,ul,ol {

 margin: 10px 5px;

 padding:2px;

}

p {

 border: 1px solid #eee

}

ul,ol {

 color:#333;

 text-transform:uppercase;

} 
Copy the code

B) LESS inheritance

LESS supports inheritance unlike Stylus in that it does not inherit from selectors, but instead nested styles from Mixins into each selector. The disadvantage of this approach is that repeated styles are generated in each selector.

.block {

  margin: 10px 5px;

  padding: 2px;

}

p {

  .block;/*继承.block选择器下所有样式*/

  border: 1px solid #eee;

}

ul,ol {

  .block; /*继承.block选择器下所有样式*/

  color: #333;

  text-transform: uppercase;

}	
Copy the code

Translated CSS code:

.block {
 margin: 10px 5px;
 padding:2px;
}
p {
 margin: 10px 5px;
 padding:2px;
 border: 1px solid #eee
}
ul,ol {
 margin: 10px 5px;
 padding:2px;
 color:#333;
 text-transform:uppercase;
}
Copy the code

As you can see, the “.block “style of the code above will be inserted into the corresponding selector that you want to inherit, but be aware of the priority issue.

6. Operations

The CSS preprocessor language also has the features of computation. In simple terms, it performs addition, subtraction, multiplication and division on numeric values (such as numbers, colors, and variables). Such features are unthinkable in CSS styles, but there is no problem in CSS preprocessor language to do some style manipulation, such as:

@base_margin: 10px;
@double_margin: @base_margin * 2;
@full_page: 960px;
@half_page: @full_page / 2;
@quarter_page: (@full_page / 2) / 2;	
Copy the code

The code above is an example of LESS. For the record, when getting the “@quarter_page” variable, we can just divide by 4, but here we just want to show the parentheses in the “order of operations” (the order of operations is also known by schoolchildren). In complex operations, parentheses are also necessary, for example:

border: (@width / 2) solid #000;	
Copy the code

Sass is more expert than LESS in numerical calculations, and he can convert units directly. Sass can process unrecognized units of measure and output them. This feature is clearly a foray into the future – proof of some changes made by the W3C.

Stylus is the most powerful of the three preprocessor languages, offering the same capabilities as other programming languages: simple addition, subtraction, multiplication and division, complex relational and logical operations. Limited by space, interested students can go to the official website to read carefully.

7. Color function

Color functions are built-in color functions in the CSS preprocessor language. These functions can be used for color processing, such as lightening, darkening, saturation control, hue control, and gradient color processing.

A)Sass color function

lighten($color, 10%); /* Darken ($color, 10%); /* The returned color darkens 10% based on $color */ saturate($color, 10%); /* Desaturate ($color, 10%); /* Grayscale ($color); /* Grayscale ($color); /* Return $color */ complement($color); Invert ($color); $color = $mix($color1, $color2, 50%); /* $color1 and $color2 */Copy the code

This is just a simple list of the color functions in Sass. You can read the Sass documentation for more details.

The color function can be applied to any element that has a color attribute. Here is a simple example:

$color: #0982C1; h1 { background: $color; border: 3px solid darken($color, 50%); /* The border color will darken 50% from $color */}Copy the code

B)LESS color function lighten(@color, 10%); Darken (@color, 10%); darken(@color, 10%); / The returned color darkens 10% based on @color/saturate(@color, 10%); Desaturate (@color, 10%); desaturate(@color, 10%); / Return color 10% desaturated from @color * spin(@color, 10); /* Return color with @color tone increment by 10 / spin(@color, -10); / The color returned is toned 10 / mix less than @color (@color1, @color2); / The color returned is a mixture of @color1 and @color2 */

For full color functions of LESS, see the LESS documentation.

Here is a simple example of how to use a color function in LESS:

@color: #0982C1;
h1 {
 background: @color;
 border: 3px solid darken(@color, 50%);
} 
Copy the code

C) Color function of the Stylus

lighten(color, 10%); /* Darken (color, 10%); /* Darken (color, 10%); /* Returned color darkens 10% based on 'color' */ saturate(color, 10%); /* Desaturate (color, 10%); /* Desaturate (color, 10%); /* The returned color is desaturated by 10% */ based on the 'color'Copy the code

For an introduction to the color functions of Stylus, read the Stylus documentation.

Here is a simple example of the Stylus color function:

color = #0982C1
h1
  background color
  border 3px solid darken(color, 50%)  
Copy the code

As you can see from some of the color functions shown above, Sass, LESS, and Stylus all have powerful color functions that are similar in their features but differ slightly in how they are used. And they all have the same goal of facilitating manipulation of color values in styles.

8. Import

In CSS, using @import to import styles is not preferred because it increases HTTP requests. The import (@import) rule in the CSS preprocessor is different from that in CSS. It simply imports different files semantically, but the end result is a CSS file. If you import “file. CSS” with “@import ‘file. CSS”, it will have the same effect as normal CSS style files. Note: variables, blends, and other information defined in the import file will also be imported into the main style file, so they need to be avoided.

The methods for importing styles are the same for Sass, LESS, and Stylus:

The style of the imported file:

/* file.{type} */
body {
 background: #EEE;
} 
Copy the code

Files that need to import styles:

@import "reset.css";
@import "file.{type}";
p 
 background: #0982C1;
} 
Copy the code

Translated CSS code:

@import "reset.css";
body {
 background: #EEE;
}
p {
 background: #0982C1;
} 
Copy the code

9. Comment

Comments are a basic part of the CSS preprocessor language. The three preprocessor languages have single-line comments in addition to standard CSS comments, but single-line comments are not translated.

A) Multi-line annotations for Sass, LESS, and Stylus

Multi-line comments and CSS standard comments, which can be output to CSS styles, are output in Stylus translations only if the compress option is not enabled.

/* * I'm a comment */ body padding 5pxCopy the code

B) Single-line notes for Sass, LESS, and Stylus

Single-line comments use the same double slash (//) as comments in the JavaScript language, but single-line comments are not printed to CSS.

// I am a comment @maincolor: #369; // Define the body colorCopy the code

In addition to these two annotations in Stylus, it also has a annotation called multi-line buffer annotation. This comment is similar to a multi-line comment except that it starts with “/*!” . This is equivalent to telling the Stylus to ignore the direct output when it compresses.

/ *! */ add(a, b) a + bCopy the code

The CSS preprocessor languages Sass, LESS and Stylus are the same in some features and have the same functions except for some writing rules. Of course some features are completely different. Here a few from the use of methods as a comparison, the main purpose is to let you after comparison, so that their choice of CSS preprocessor language direction and help.

Advanced applications of CSS preprocessors

We know that Sass, LESS, and Stylus all have features like variables, blending, nesting, functions, and scopes, but these are generic features. In addition to these features, they also have some interesting features to help us develop, such as conditional statements, loop statements, etc. Next, let’s compare and contrast the three CSS preprocessor languages in terms of usage.

A) Conditional statements

Speaking of programming, you are familiar with the basic control flow of programming, except that loops are conditions. Conditions provide control over what is otherwise a purely static language. Conditions are provided for imports, blends, functions, and more. Conditional statements common in programming languages:

if/else if/else	
Copy the code

If the expression satisfies (true), the following natural block is executed; otherwise, the following else if or else continues.

This idea is present in all three CSS3 preprocessor languages, though LESS expresses it in a slightly different way. Let’s take a look at how they are used.

Sass conditional statement

Conditional statements in the Sass style are very similar to conditional statements in other programming languages, and can be judged using “@if” in the style:

p { @if 1 + 1 == 2 { border: 1px solid; } @if 5 < 3 { border: 2px dotted; } @if null { border: 3px double; }}Copy the code

Compiled CSS:

p {
 border: 1px solid; 
}
Copy the code

Conditional statements can also be used with @else if and @else in Sass:

$type: monster; p { @if $type == ocean { color: blue; } @else if $type == matador { color: red; } @else if $type == monster { color: green; } @else { color: black; }}Copy the code

Translated CSS:

p {color:green; }Copy the code

Conditional statements for Stylus

The use of conditional statements in Stylus is similar to that in other programming conditional statements, except that it can omit curly braces ({}) from the style:

box(x, y, margin = false)
  padding y x
  if margin
    margin y x
body
  box(5px, 10px, true)	
Copy the code

Stylus also works with else if and else:

box(x, y, margin-only = false)
  if margin-only
    margin y x
  else
    padding y x	
Copy the code

In addition to this simple use of conditional statements, Stylus also supports postfix conditional statements. This means if and unless (those familiar with the Ruby programming language will know the unless condition, which is basically the opposite of if and is essentially “(! (expr)) “) as an operator; The left-hand action object is executed when the right-hand expression is true.

For example, we define Negative () to perform some basic checks. Here we use block conditions:

Negative (n) unless n is a 'unit' error(' invalid value ') if n < 0 yes else noCopy the code

Next, we use the suffix condition to keep our method simple:

Negative (n) error(' invalid value ') unless N is a 'unit' return yes if n < 0 noCopy the code

Of course, we can go further. Such as this “n < 0? Yes: no can be replaced with Boolean: “n < 0”. Postfix conditions apply to most single-line statements. For example, “@import,@charset” mixed writing. Of course, the following attributes are also available:

pad(types = margin padding, n = 5px)
  padding unit(n, px) if padding in types
  margin unit(n, px) if margin in types

body
  pad()

body
  pad(margin)

body
  apply-mixins = true
  pad(padding, 10) if apply-mixins	
Copy the code

The code above translates to CSS:

body {
 padding: 5px;
 margin: 5px;
}
body {
 margin: 5px;
}
body {
 padding: 10px;
} 
Copy the code

The conditional statement of LESS

The use of LESS conditional statements is somewhat unusual. It is not the usual keywords like if and else if, but is implemented using the keyword “when”.

.mixin (@a) when (@a >= 10) { 
  background-color: black; 
 } 
 .mixin (@a) when (@a < 10) { 
  background-color: white; 
 } 
 .class1 { .mixin(12) } 
 .class2 { .mixin(6) }	
Copy the code

Translated CSS:

.class1 { 
 background-color: black; 
 } 
.class2 { 
 background-color: white; 
 } 
Copy the code

Using When and <, >, =, <=, >= is simple and convenient. LESS doesn’t stop there, and provides many type-checking functions to assist conditional expressions, such as iscolor, isNumber, isString, iskeyword, isURL, and so on.

.mixin (@a) when (iscolor(@a)) { 
  background-color: black; 
 } 
 .mixin (@a) when (isnumber(@a)) { 
  background-color: white; 
 } 
 .class1 { .mixin(red) } 
 .class2 { .mixin(6) }	
Copy the code

Translated CSS

.class1 { 
 background-color: black; 
 } 
 .class2 { 
 background-color: white;
 } 
Copy the code

In addition, the conditional expressions of LESS also support AND AND OR AND NOT to combine conditional expressions, which can be organized into more powerful conditional expressions. It should be pointed out in particular that OR is not the keyword OR in LESS, but is used to express the logical relation of OR.

.smaller (@a, @b) when (@a > @b) { 
  background-color: black; 
} 
.math (@a) when (@a > 10) and (@a < 20) { 
  background-color: red; 
} 
.math (@a) when (@a < 10),(@a > 20) { 
  background-color: blue; 
} 
.math (@a) when not (@a = 10)  { 
  background-color: yellow; 
}
.math (@a) when (@a = 10)  { 
  background-color: green; 
} 
 
.testSmall {.smaller(30, 10) } 
.testMath1 {.math(15)}
.testMath2 {.math(7)} 
.testMath3 {.math(10)}
Copy the code

Translated CSS

.testSmall { 
 background-color: black; 
} 
.testMath1 { 
 background-color: red; 
 background-color: yellow; 
} 
.testMath2 { 
 background-color: blue; 
 background-color: yellow; 
} 
.testMath3 { 
 background-color: green; 
} 
Copy the code

B) loop statements

Sass and Stylus also support for loop statements, while LESS does not, but thankfully you can use When in LESS to simulate the nature of the for loop.

Loop statement of Sass

Sass uses @for with “from” and “through”. The syntax is as follows:

@for $var from <start> through <end>Copy the code

Let’s look at a simple example:

@for $i from 1 through 3 { .item-#{$i} { width: 2em * $i; }}Copy the code

Translated CSS code:

.item-1 {  width: 2em; }
.item-2 {  width: 4em; }
.item-3 {  width: 6em; } 
Copy the code

In Sass, in addition to the @for statement, there are @each statements and @while statements

@each loop syntax:

@each $var in <list>Copy the code

Here’s a simple example:

@each $animal in puma, sea-slug, egret, salamander { .#{$animal}-icon { background-image: url('/images/#{$animal}.png'); }}Copy the code

Translated CSS

.puma-icon {  background-image: url('/images/puma.png'); }
.sea-slug-icon {  background-image: url('/images/sea-slug.png'); }
.egret-icon {  background-image: url('/images/egret.png'); }
.salamander-icon {  background-image: url('/images/salamander.png')	}
Copy the code

The @while loop is used similarly to other programming languages:

$i: 6;
@while $i > 0 {
  .item-#{$i} { width: 2em * $i; }
  $i: $i - 2;
}	
Copy the code

Translated CSS

.item-6 {  width: 12em; }
.item-4 {  width: 8em; }
.item-2 {  width: 4em; } 
Copy the code

The circular statement of Stylus

Loops expressions through for/in in the Stylus style as follows:

for <val-name> [, <key-name>] in <expression>	
Copy the code

Such as:

body
  for num in 1 2 3
    foo num	
Copy the code

Translate out CSS

body {
 foo: 1;
 foo: 2;
 foo: 3;
} 
Copy the code

The following example demonstrates how to use it:

body
  fonts = Impact Arial sans-serif
  for font, i in fonts
    foo i font	
Copy the code

Translated CSS

body {
 foo: 0 Impact;
 foo: 1 Arial;
 foo: 2 sans-serif;
} 
Copy the code

A loop statement for LESS

LESS language does not have the current loop statement, but like its conditional statement, through when to simulate its loop function.

.loopingClass (@index) when (@index > 0) { .myclass { z-index: @index; } // recurse.loopingClass (@index-1); } // stop the loop.loopingClass (0) {} // output.loopingClass (3);Copy the code

Translated CSS

.myclass {z-index: 3; } .myclass {z-index: 2; } .myclass {z-index: 1; }Copy the code