Selecting a CSS preprocessor. CSS preprocessors and the benefits of using them

NetTuts+ article written by Johnathan Croom in 2012.

The main goal of the article is to show the advantage of using any of the three preprocessors described in it: Sass, LESS and Stylus. The review is perfect for beginners who are just discovering this facet of web design.

In this article, we will look at the advantages and benefits of using three different preprocessors - Sass, LESS and Stylus.

Introduction

CSS preprocessors were created with one goal in mind: to add power and flexibility to CSS style sheets without breaking cross-browser compatibility. All preprocessors compile the code generated using their syntax into standard CSS code that any browser, no matter how ancient, can understand and use ( browser) was not.

There are many benefits that preprocessors bring to CSS stylesheets, and in this article we'll look at just a few of them, both well-known and less common. Let's get started with the review.

Syntax

The most important part when writing code in any CSS preprocessor is its syntax. Luckily for us, the syntax of all three preprocessors we'll be looking at is CSS-like.

SASS & LESS

Both Sass and LESS preprocessors have standard CSS syntax. This makes the task of converting existing CSS code into the syntax of any of these preprocessors simple and fast. Sass uses the extension for its files

1 .scss
, LESS - extension
1 .less
.

A typical file in Sass or LESS syntax is shown below:

/* style.scss or style.less */ h1 ( color : #0982c1 ; )

You can clearly see that this is normal CSS syntax, which converts perfectly to Sass (SCSS) or LESS.

It's important to note that Sass (SCSS) also has an older version of Sass syntax that omits semicolons and curly braces.

Although this syntax can still be used in practice, it is obsolete and we will not use it in our examples.

Sass Syntax ( old version) as follows:

/* style.sass */ h1 color : 0982c1 Stylus

This preprocessor uses the extension for its files

1 .style
. The Stylus preprocessor syntax is more verbose ( approx. translator: the author has confused something here) it uses standard CSS syntax as a basis, but allows for varying combinations of parentheses, colons, and semicolons.

Stylus syntax examples:

/* CSS-like syntax */ h1 ( color : #0982C1 ; ) /* omitted curly braces */ h1 color : #0982C1 ;

/* omitted curly braces, colons and semicolons */ h1 color #0982C1

All syntax options shown above are valid and will result in correct CSS code when compiled. For example, this code will compile to standard CSS without errors:

h1 ( color #0982c1 ) h2 font-size : 1 .2em Variables

In preprocessors, variables are declared and used within CSS style files. Variables can take on any value allowed in CSS (color, number, or text) and can be referenced from anywhere in the CSS document.

Sass

1 $
In the Sass preprocessor, a variable is declared using the symbol

, while the variable name and its value are separated from each other by a colon, as is done in CSS: $ mainColor: #0982c1;

1 @
$siteWidth: 1024px;

$borderStyle: dotted;

body ( color : $mainColor ; border : 1px $borderStyle $mainColor ; max-width : $siteWidth ; ) LESS

Variables in LESS are exactly the same as in Sass, except that the variable name is preceded by a symbol

: @mainColor : #0982c1 ;

@siteWidth : 1024px ;

@borderStyle : dotted ;

body ( color : @ mainColor ; border : 1px @ borderStyle @ mainColor ; max-width : @ siteWidth ; ) Stylus

Variables in Stylus do not need any sign for their declaration, but can still use the symbol

If your CSS code is tasked with accessing multiple elements that have the same parent at the same time, then writing that parent over and over again is tedious.

For example, like this:

Instead, using the power of the preprocessor, we can place all child selectors inside the parent element's parentheses. In addition, the symbol

1 &
is a link ( reduction) to the parent element selector. Sass, LESS & Stylus

All three preprocessors have exactly the same syntax for nested selectors:

section ( margin : 10px ; nav ( height : 25px ; a ( color : #0982C1 ; &:hover ( text-decoration : underline ; ) ) ) ) Compiled CSS

Below is the compiled CSS output of the code above. Compare with the code that we wrote at the very beginning - absolutely the same. But what a convenience it is to take advantage of the preprocessor!

section ( margin : 10px ; ) section nav ( height : 25px ; ) section nav a ( color : #0982C1 ; ) section nav a :hover ( text-decoration : underline ; ) mixins
1 mixins
are functions that allow you to reuse grouped properties within CSS code. Instead of going through your entire code to find the right lines to change, you can now make changes only once, inside the mixin.

The use of mixins is especially worthwhile when creating specific styles for elements or setting browser prefixes. When a mixin is called inside a CSS selector, the mixin's arguments are parsed, then its styles are applied to the selector that called it.

Note translator: in the examples below, it is worth paying attention to the difference in the syntax of declaring and calling a mixin inside a CSS selector for all three preprocessors.

Sass /* Sass mixin named error with argument $borderWidth whose default value is 2px */ @mixin error ($ borderWidth : 2px ) ( border : $ borderWidth solid #F00 ; color : #F00 ; ) .generic-error ( padding : 20px ; margin : 4px ; @include error(); .login-error ( left : 12px ; position : absolute ; top : 20px ; @include error(5px); ) LESS /* LESS mixin named error with argument $borderWidth, which defaults to 2px */ .error (@borderWidth : 2px ) ( border : @ borderWidth solid #F00 ; color : #F00 ; ) .generic-error ( padding : 20px ; margin : 4px ; .error( ); /* Connect a mixin named error */ ) .login-error ( left : 12px ; position : absolute ; top : 20px ; .error(5px); /* Connect a mixin named error with the value of the $borderWidth argument equal to 5px ; that is, the value of the argument is overridden */ ) Style /* Stylus mixin named error with the argument $borderWidth, whose default value is 2px */ error (borderWidth = 2px ) ( border : borderWidth solid #F00 ;

color : #F00 ;

) .generic-error ( padding : 20px ; margin : 4px ; error(); /* Connects a mixin named error */ ) .login-error ( left : 12px ; position : absolute ; top : 20px ; error(5px); /* A mixin called error is connected with the value of the argument $borderWidth equal to 5px; that is, the value of the argument is overridden */ ) Compiled CSS

The result of compilation from all three preprocessors will be the same CSS code:

.generic-error ( padding : 20px ; margin : 4px ; border : 2px solid #f00 ; color : #f00 ; ) .login-error ( left : 12px ; position : absolute ; top : 20px ; border : 5px solid #f00 ; color : #f00 ; ) Inheritance

When writing CSS styles in the “classic” way, in order to apply the same properties to multiple elements in an HTML document, we would create code like this:

p , ul , ol ( /* some styles here */ )

Note translator: note the same syntax for connecting (declaring) inheritance inside a CSS selector using a directive

1 @extend
.

Sass & Stylus .block ( margin : 10px 5px ; padding : 2px ; ) p ( @extend .block; border : 1px solid #EEE ; ) ul , ol ( @extend .block; /* Inherit properties from class selector.block * / Compiled CSS .block , p , ul , ol ( margin : 10px 5px ; padding : 2px ; ) p ( border : 1px solid #EEE ; ) ul , ol ( color : #333 ; text-transform : uppercase ; ) LESS

The LESS preprocessor does not fully support inheritance in the same way as Sass or Stylus. Instead of adding multiple selectors to a single property set, inheritance is treated as a no-argument mixin.

Styles are imported for each selector. The downside of this approach is the constant repetition of property lines in the compiled CSS style.

Here's what LESS code with inheritance might look like:

.block ( margin : 10px 5px ; padding : 2px ; ) p ( .block; border : 1px solid #EEE ; ) ul , ol ( .block; /* Inheriting properties from the class selector.block */ color : #333 ; text -transform : uppercase ; ) Compiled CSS .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 ;

As you can clearly see from the code, class styles

. Importing

1 In the CSS community to importing styles using a directive
@import

There is a persistent negative attitude, since this approach generates multiple HTTP requests to the server, which slows down the browser and loads the server itself. However, in preprocessors the import technology works differently.

In any of the three preprocessors, importing one file inside another effectively inserts the code from one file into the other when compiled, resulting in a single CSS file.

Note translator: in other words, in preprocessors, importing is necessary to compile one file from several. In standard CSS, importing results in substituting one code inside another.

1 Please note that when compiling a file with a standard connection using the directive
the latter is not compiled inside it. But mixins or variables are imported and used in the style file as expected. Import technology is very convenient because it allows you to create many separate files to properly organize your project.

/* file.(type) */ body ( background : #EEE ; ) @import "reset.css" ;

1 @import "file.(type)" ;
p ( background : #0982C1 ; ) Compiled CSS @import "reset.css" ;

body ( background : #EEE ; ) p ( background : #0982C1 ; ) Color functions

“Color” functions are designed to transform colors during compilation. Such functions are extremely useful when creating gradients, darkening colors when

1 hover
and much more. Sass lighten($color, 10%);

darken($color, 10%);

saturate($color, 10%);

@color : #0982C1 ;

h1 ( background : @ color ; border : 3px solid darken ( @ color , 50% ); ) Stylus lighten ( @color , 10% );

/* returns a color 10% lighter than $color */ darken (@color , 10% );

/* returns a color 10% darker than $color */ saturate (@color , 10% );

/* returns a color 10% more saturated than $color */ desaturate (@color , 10% );

/* returns a color 10% less saturated than $color */

1 A complete list of all the color functions of the Stylus preprocessor is presented on the Stylus Documentation project website.
And an example of using the “color” function in Stylus:

color = #0982C1 h1 background color border 3px solid darken (color , 50%) Arithmetic operations

Thanks to preprocessors, performing arithmetic operations inside CSS code is now simple and easy. This feature is often useful.

Note translator: it is worth mentioning the function from CSS3 named

calc()

, which also allows you to perform simple arithmetic operations within CSS code.

Create a 3D effect for text using a CSS property

1 text-shadow
is a great idea. The only problem is working with color, which is quite difficult and cumbersome.

Using mixins and color functions, we can create 3D text and change its color on the fly:

Sass @mixin text3d ($color) ( color: $color; text-shadow: 1px 1px 0px darken ($color, 5%), 2px 2px 0px darken ($color, 10%), 3px 3px 0px darken ($color, 15% ), 4px 4px 0px darken ( $ color , 20% ), 4px 4px 2px #000 ; ) h1 ( font-size : 32pt ; @include text3d(#0982c1); ) LESS .text3d (@color ) ( color : @ color ; text-shadow : 1px 1px 0px darken (@ color , 5% ), 2px 2px 0px darken (@ color , 10% ), 3px 3px 0px darken (@ color , 15% ), 4px 4px 0px darken (@ color , 20% ), 4px 4px 2px #000 ; ) span ( font-size : 32pt ; .text3d(#0982c1); ) Stylus text3d (color ) color : color text-shadow : 1px 1px 0px darken (color , 5%) , 2px 2px 0px darken (color, 10%), 3px 3px 0px darken (color, 15%), 4px 4px 0px darken (color, 20%), 4px 4px 2px #000 span font-size: 32pt text3d (#0982c1)

In the example for Stylus, I chose the option to write the property

1 text-shadow
in one line, since here I omitted the curly braces. Compiled CSS span ( font-size : 32pt ; color : #0982c1 ; text-shadow : 1px 1px 0px #097bb7 , 2px 2px 0px #0875ae , 3px 3px 0px #086fa4 , 4px 4px 0px #07689a , 4px 4px 2px #000 ; ) Columns

The use of variables and numeric values ​​for these variables came to my mind when I first began to become familiar with the capabilities of CSS preprocessors. Declaring the width for a layout inside a variable makes it the task of changing that width ( if necessary) simple and fast:

Sass $siteWidth: 1024px;

$gutterWidth: 20px;

$sidebarWidth: 300px;

body (margin: 0 auto; width: $siteWidth;).content(float:left;width:$siteWidth - ($sidebarWidth +$gutterWidth);).sidebar(float:left;margin-left:$gutterWidth;width: $sidebarWidth ; ) LESS @siteWidth : 1024px ;

@gutterWidth : 20px ; @sidebarWidth : 300px ;).

body (margin: 0 auto; width: @siteWidth;).content(float:left;width:@siteWidth - (@sidebarWidth +@gutterWidth);).sidebar(float:left;margin-left:@gutterWidth;width: @sidebarWidth ; ) Stylus siteWidth = 1024px ;

gutterWidth = 20px ;

Such different tasks, as a rule, are small and slightly reduce efficiency. Fortunately, these and several other inefficiencies have been recognized and challenged by preprocessors.

A preprocessor is a program that takes one data type and converts it to another data type. In the case of HTML and CSS, some of the most popular preprocessor languages ​​are Haml and Sass. Haml is converted to HTML and Sass is converted to CSS.

Since their inception, while solving some of the most common problems, Haml and Sass have found many additional ways to extend the capabilities of HTML and CSS. Not only by removing ineffective tasks, but also by creating methods that make website development easier and more logical. Preprocessors have also become popular due to the various frameworks that support them; one of the most popular is Compass.

Haml

CodeKit also supports other preprocessors that you may also find useful.

Doctype

The first part of writing a document in Haml is knowing what type of doctype to use. When working with HTML documents, the main document type will be HTML5. In Haml, document types are defined by three exclamation marks (!!!), followed by something specific if necessary.

The default doctype in Haml is HTML 1.0 Transitional. Therefore, to make it like HTML5, you need to pass the number five after the exclamation marks (!!! 5).

Ready HTML

Declaration of elements

One of the defining features of Haml is its syntax and how to declare and nest elements. HTML elements typically contain an opening and closing tag, but Haml elements only have one opening tag. Elements begin with a percent sign (%) and then indentation determines nesting. Indentation in Haml can be done with one or more spaces, but it is important that the indentation remains the same. Tabs and spaces cannot be combined and the same number of tabs or spaces must be the same throughout the document.

Eliminating the need for opening and closing tags and the required indentation structure creates a layout that is easy to follow. At any time, the markup can be quickly viewed and changed without difficulty.

%body %header %h1 Hello world!

%section %p Lorem ipsum dolor sit amet.

Compiled HTML

Hello World!

Lorem ipsum dolor sit amet.

Text in Haml can be placed on the same line as the declared element or indented below the element. Text cannot be both on the same line as the declared element and nested below it; there must be one or the other option. The above example can be rewritten as follows:

%body %header %h1 Hello world!

%section %p Lorem ipsum dolor sit amet.

Attributes

Attributes, like elements, are declared slightly differently in Haml. Attributes are declared immediately after the element, in curly or parentheses, depending on whether you want to use Ruby or HTML syntax. Ruby style attributes will use standard hash syntax inside(), while HTML style attributes will use standard HTML syntax inside().") !}

%section %p Lorem ipsum dolor sit amet.

%img(:src => "shay.jpg", :alt => "Shay Hou") %img(src: "shay.jpg", alt: "Shay Hou") %img(src="shay.jpg" alt="Shay Hou

Classes and IDs

If desired, classes and identifiers can be declared like other attributes, but they can also be treated slightly differently. Instead of listing the class and id attributes with their values ​​inside parentheses, the value can be specified directly after the element. Using either a dot for classes or a hash for identifier, a value can be added immediately after the element.

Additionally, attributes can be mixed by joining together in an appropriate format. The classes must be separated by dots, and other attributes can be added using one of the previously outlined formats.

%section %p Lorem ipsum dolor sit amet.

%section.feature %section.feature.special %section#hello %section#hello.feature(role="region")

Classes and identifiers in

In case a class or identifier is used in , then %div can be omitted and the value of the class or identifier can be included directly. Again, classes should be defined by a dot, and identifiers by a hash.

%section %p Lorem ipsum dolor sit amet.

Awesome.awesome.lesson #getting-started.lesson

Boolean attributes

Boolean attributes are treated the same as if they were in Ruby or HTML, depending on the syntax used.

%section %p Lorem ipsum dolor sit amet.

%input(:type => "checkbox", :checked => true) %input(type="checkbox" checked=true) %input(type="checkbox" checked)

Escaping text

In the example below, the first pattern = @author is executed by Ruby, getting the authors name from the application. The second pattern starts with a backslash escaping the text and is printed as is without execution.

Author = @author \= @author

%section %p Lorem ipsum dolor sit amet.

Shay Hou = @author

Text Escaping Alternatives

At times, escaping text is not enough and Ruby is needed to generate the desired output. One popular example for this is trying to include a period immediately after a link, but not as part of the link text. Placing a period on a new line is not acceptable because it will be treated as an empty class value, causing a compilation error. Adding a backslash before the period escapes the character, but puts a space between the last word and the period. Again, not producing the desired result.

In these cases, the Ruby helper comes in handy. The example below uses the helper to place a period immediately after the last word, but outside the link text.

%p Shay - = succeed "." do %a(:href => "#") well done

%section %p Lorem ipsum dolor sit amet.

Shay - Well done.

Comments

Like elements and attributes, comments are handled slightly differently in Haml. The code can be commented quite simply using a single forward slash (/). Single lines can be commented out by using a forward slash at the beginning of a line, and blocks of code can be commented out by being nested under a slash.

%div / Comment line Current line / %div Commented block

%section %p Lorem ipsum dolor sit amet.

Current line

Conditional comments

Conditional comments are also handled differently in Haml. To create a conditional comment, use square brackets () around the condition. These square brackets must be placed immediately after the slash.

/ %script(:src => "html5shiv.js")

%section %p Lorem ipsum dolor sit amet.

Quiet comments

Haml also provides the ability to create special silent comments. Silent comments differ from basic HTML comments in that, once compiled, any content within a silent comment is completely removed from that page and does not appear in the results. Silent comments begin with a hyphen, followed by a hash (-#). As with other comments, silent comments can be used to remove one or more lines using nesting.

%div -# Deleted line Current line

%section %p Lorem ipsum dolor sit amet.

Current line

Filters

Haml offers several filters that allow you to use different types of input within Haml. Filters start with a colon, followed by the name of the filter, for example :markdown, with all the content to filter the attachment below it.

Common filters

Below are some common filters, including the most popular: css and: javascript.

  • :cdata
  • :coffee
  • :escaped
  • :javascript
  • :less
  • :markdown
  • :maruku
  • :plain
  • :preserve
  • :ruby
  • :sass
  • :scss
  • :textile
Javascript filter

:javascript $("button").on("click", function(event) ( $("p").hide("slow"); ));

%section %p Lorem ipsum dolor sit amet.

$("button").on("click", function(event) ( $("p").hide("slow"); ));

CSS and Sass filters

:css .container ( margin: 0 auto; width: 960px; ) :sass .container margin: 0 auto width: 960px

%section %p Lorem ipsum dolor sit amet.

.container ( margin: 0 auto; width: 960px; )

Ruby interpolation

As mentioned earlier, Haml can evaluate Ruby, and sometimes there may be cases where Ruby must be evaluated within plain text. In this case, Ruby must be interpolated by wrapping the required code in Ruby.

Below is a Ruby example that is interpolated as part of the class name.

%div(:class => "student-#(@student.name)")

%section %p Lorem ipsum dolor sit amet.

SCSS and Sass

SCSS and Sass are preprocessing languages ​​that compile to CSS. They're a bit like Haml and make writing code easier while offering very few controls. Individually, SCSS and Sass share the same origins, but technically they have different syntaxes.

For the sake of brevity, Haml and Sass were the only preprocessors covered in this tutorial. They were also chosen because they are built using Ruby and fit directly into Ruby on Rails applications. They also received tremendous support from the community.

When it comes to choosing which preprocessor to use, it's important to consider what's best for your team and project. Projects built in Node.js can probably benefit more from Jade and Stylus. The most important aspect to consider, however, is what your team is used to using. Do your research for each project and choose the most informed solution.

Resources and links
  • Haml - HTML Abstraction Markup Language
  • Sass - Syntactically Awesome Stylesheets
  • Sass Playground on SassMeister

Modern CSS is powerful, and in combination with preprocessors, it is generally a fighting machine for designing content on pages. The article provides an extensive guide to Sass/SCSS with examples. After reading this, you'll learn how to use mixins, variables, and directives to give you even more control over your styles.

Note All Sass/SCSS code is compiled to CSS so that browsers can understand and display it correctly. Currently, browsers do not support working with Sass/SCSS or any other CSS preprocessor directly, and the standard CSS specification does not provide similar functionality.

Why use Sass/SCSS instead of CSS?
  • Nesting- SCSS allows you to nest CSS rules within each other. Nested rules are applied only for elements that match external selectors (and if we are talking about Sass, then everything is beautiful and intuitive there even without parentheses).
  • Variables- standard CSS also has the concept of variables, but in Sass you can work with them a little differently. For example, repeat them through the @for directive. Or generate properties dynamically. You can study more on the Russian-language project website.
  • Improved math operations- you can add, subtract, multiply and divide CSS values. Unlike standard CSS, Sass/SCSS allows you to do without calc() .
  • Trigonometry- SCSS allows you to write your own (sine and cosine) functions using only Sass/SCSS syntax, similar to how you can do it in other languages ​​like JavaScript.
  • Directives@for , @while and expression@if-else - You can write CSS code using familiar elements from other languages. But don't be fooled - in the end the output will be plain CSS.
  • Mixins (mixins)- you can create a set of CSS properties once and work with them repeatedly or mix them with other values. Mixins can be used to create separate themes of the same layout. Mixins can also contain entire CSS rules or anything else allowed in a Sass document. They can even accept arguments, allowing you to create a wide variety of styles with a small number of mixins.
  • Functions- You can create CSS definitions as functions for reuse.
  • Sass Preprocessor

    Sass is not dynamic. You won't be able to generate and/or animate CSS properties and values ​​in real time. But you can create them in a more efficient way and let standard properties (like CSS animation) borrow them from there.

    Syntax

    SCSS doesn't really add any new features to CSS other than new syntax that often reduces coding time.

    Prerequisites

    There are 5 CSS preprocessors: Sass, SCSS, Less, Stylus and PostCSS.

    This article mostly covers SCSS, which is similar to Sass. You can read more about these preprocessors on Stack Overflow (original) or on qaru (translation into Russian).

    SASS  -  (.sass) S yntactically A wesome S tyle S heets.

    SCSS  -  (.scss) Sass y C ascading S tyle S heets.

    The .sass and .scss extensions are similar, but still not the same. For command line fans, here is the conversion method:

    # Convert from Sass to SCSS $ sass-convert style.sass style.css # Convert from SCSS to Sass $ sass-convert style.scss style.sass

    Sass is the first specification for SCSS with a .sass file extension. Its development began back in 2006, but later an alternative syntax with the .scss extension was developed.

    Please note Other preprocessors have similar functionality to SCSS, but the syntax may differ. Also, everything that works in CSS will also work perfectly in Sass and SCSS.

    Variables

    Sass/SCSS allows you to work with variables. In CSS they are denoted by a double dash (--), and in preprocessors they are represented by a dollar sign ($).

    $number: 1; $color: #ff0000; $text: "tproger forever."; $text: "IT forever." !default; $nothing: null;

    You can assign a default value to variables that do not yet have a value by adding the !default tag at the end of the value. In this case, if the variable has already been assigned a value, it will not change; if the variable is empty, it will be assigned the new specified value.

    #container ( content: $text; )

    Variables in Sass can be assigned to any property.

    Nested Rules

    Standard nested CSS elements using white space:

    /* Nested rules */ #A ( color: red; ) #A #B ( color: green; ) #A #B #C p ( color: blue; )

    Same nested elements using SCSS:

    /* Nested rules */ #A ( color: red; #B ( color: green; #C p ( color: blue; ) ) )

    As you can see, the syntax looks cleaner and less repetitive.

    This is especially useful when managing overloaded layouts. This way, the alignment in which the nested properties are written in code closely matches the actual layout structure of the application.

    Behind the scenes, the preprocessor still compiles it into standard CSS code (shown above) so it can be rendered in the browser. We're just changing the way we write CSS.

    Ampersand #p ( color: black; a ( font-weight: bold; &:hover ( color: red; ) ) )

    With the & character you can explicitly specify where the parent selector should be inserted.

    The result of compiling Sass (from the previous example) to CSS is below.

    #p (color: black;) #p a (font-weight: bold;) #p a:hover (color: red;)

    As a result, the ampersand was compiled into the name of the parent element a (a:hover).

    Mixins (aka impurities)

    Mixins can also contain selectors, including those with properties. And selectors can contain references to the parent element through the ampersand (&), you remember about that, right?

    Example of working with multiple browsers

    Some things in CSS are quite tedious to write, especially in CSS3, where on top of that you often need to use a large number of vendor prefixes (-webkit- or -moz-).

    Mixins allow you to create groups of CSS declarations that you will use multiple times throughout your site. It is good practice to use mixins for vendor prefixes. Example:

    @mixin border-radius($radius) ( // Prefixes for: -webkit-border-radius: $radius; // Chrome and Safari -moz-border-radius: $radius; // Firefox -ms-border-radius: $radius; // Internet Explorer -o-border-radius: $radius; // Opera border-radius: $radius; // Standard CSS ) // Example of using the border-radius mixin after creating it.box ( @include border- radius(10px)

    Arithmetic operations

    Just like in real life, you can't work with numbers that have incompatible data types (like adding px and em).

    Addition and subtraction p ( font-size: 10px + 2em; // ERROR! font-size: 10px + 6px; // 16px font-size: 10px + 2; // 12px )

    Always pay attention to the type of data being added. That is, pixels to pixels, elephants to elephants. Subtraction works in the same way, but with a minus sign.

    Subtraction example:

    Multiplication

    Done exactly like in CSS, using calc(a * b) , but without calc and parentheses. In addition, you can also separate the multiplication sign with spaces from numbers (5*6 == 5 * 6).

    Exception You cannot multiply pixels among themselves. That is, 10px * 10px != 100px . 10px * 10 == 100px .

    P ( width: 10px * 10px; // ERROR! width: 10px * 10; // 100px width: 1px * 5 + 5px; // 10px width: 5 * (5px + 5px); // 50px width: 5px + ( 10px / 2) * 3; // 20px )

    Division

    With division, things are a little more complicated, but you can figure it out, because in standard CSS the slash is reserved for using a short form of notating properties. Example below.

    /* short form for writing properties */ font: italic bold .8em/1.2 Arial, sans-serif; /* standard form for writing properties */ font-style: italic; font-weight: bold; font-size: .8em; line-height: 1.2; font-family: Arial, sans-serif;

    There are three helpers that will hint at the possibility of division:

  • The value (or any part of it) is stored in a variable or returned by a function.
  • Values ​​are enclosed in parentheses.
  • The value is used as part of another arithmetic expression.
  • $var1: 20; $var2: 4; p ( top: 16px / 24px; // Displays unchanged in standard CSS top: (20px / 5px); // Divides (but only when using brackets) top: #($var1) / #($var2); / / Outputs as normal CSS code, no division is performed top: $var1 / $var2; // Division is performed top: random(4) / 5; // Division is performed (if used in conjunction with the function) top: 2px / 4px + 3px; // Division is performed if another arithmetic operation is added)

    Compilation result in CSS:

    P ( top: 16px / 24px; top: 4; top: 20 / 4; top: 5; top: 0.6; top: 3.5px; )

    Remainder

    Remainder calculates the remainder of a division operation. Below we will look at how to create a “zebra” for an HTML list.

    @mixin zebra() ( @for $i from 1 through 7 ( @if ($i % 2 == 1) ( .stripe-#($i) ( background-color: black; color: white; ) ) ) ) * ( @include zebra(); text-align: center; )

    The creation of the zebra mixin is shown in the code embed above. The @for and @if directives are described in the section below.

    To create a sample, you need to write several HTML elements.

    zebra zebra zebra zebra zebra zebra zebra

    Result in browser:

    Zebra successfully generated by zebra mixin

    Comparison Operators

    The @if directive takes a SassScript expression and uses its nested styles if the expression returns anything other than false or null .

    The following shows how @if and @else directives work when nested within a mixin.

    @mixin spacing($padding, $margin) ( @if ($padding > $margin) ( padding: $padding; ) @else ( padding: $margin; ) .container ( @include spacing(10px, 20px); )

    Comparison in action. The spacing mixin will select the padding size if it is larger than the margin .

    After compiling to CSS:

    Container ( padding: 20px; )

    Logical operators

    Description of logical operators

    Using Sass Boolean Operators to create a button that has a background that changes depending on its width.

    @mixin button-color ($height, $width) ( @if (($height< $width) and ($width >= 35px)) ( background-color: blue; ) @else ( background-color: green; ) .button ( @include button-color(20px, 30px) )

    Strings

    CSS defines 2 types of strings: with and without quotes. Sass recognizes both. As a result, you will end up with the same type of strings in CSS that you used in Sass.

    In some cases, you can add strings to valid CSS values ​​without quotes, but only if the added string is a terminating element.

    P ( font: 50px Ari + "al"; // Compiles to 50px Arial )

    The example below demonstrates what not to do.

    P ( font: "50px" + Arial; // ERROR! )

    You can add strings of different types as long as there are no spaces in them. The example below will not compile.

    P:after ( content: "Bring back Linus " + Torvalds!; // ERROR! )

    P:after ( content: "Bring back Linus" + "Torvalds!"; // pay attention to "Torvalds!" )

    Example of adding multiple strings:

    P:after ( content: "The destiny of " + "humanity" + "-" + "iteration."; )

    Adding strings and numbers:

    P:after ( content: "Recursion " + 2013 + "the destiny of the celestials"; )

    Please note: The content property only works with the:before and:after pseudo-selectors. It is recommended not to use content in a CSS document, but to use it directly between tags in HTML.

    Thread Control Operators

    SCSS has functions (fucntion()) and directives (@directive). A little higher, we already looked at an example of a function when we studied passing arguments inside mixins.

    Functions are usually enclosed in parentheses immediately following their name. And the directive begins with the @ symbol.

    Like JavaScript, SCSS allows you to work with a standard set of flow control operators.

    if()

    if() is a function (and sometimes the basis of artificial intelligence).

    Its use looks quite primitive: the operator will return one of the two values ​​indicated in the condition.

    /* Using the if() function */ if (true, 1px, 2px) => 1px; if (false, 1px, 2px) => 2px;

    @if

    @if is a directive used for conditional branching.

    /* Using the @if directive */ p ( @if 1 + 1 == 2 ( border: 1px solid; ) @if 7< 5 { border: 2px dotted; } @if null { border: 3px double; } }

    Compilation result:

    P ( border: 1px solid; )

    Below is a combo fork with the addition of the @else directive.

    /* Create a $type variable */ $type: river; /* Color the containers blue if the value for the $type variable is river */ div ( @if $type == river ( color: blue; ) ) /* Conditional colors for the text in the tag

    */ p ( @if $type == tree ( color: green; ) @else if $type == river ( color: blue; ) @else if $type == dirt ( color: brown; ) )

    Checking for the presence of a parent element

    The ampersand selects the parent element if one exists. Otherwise it will return null . Therefore it can be used in conjunction with the @if directive.

    In the following examples, we'll look at creating conditional CSS styles depending on the presence of a parent element.

    /* Check to see if there is a parent element */ @mixin does-parent-exist ( @if & ( /* Apply a blue color to the parent element if it exists */ &:hover ( color: blue; ) ) @else ( /* Parent element missing, apply blue color to links */ a ( color: blue; ) ) )

    @for directive

    The @for directive prints a set of styles a specified number of times. For each iteration, a counter variable is used to change the output.

    The @for directive is iterated 5 times.

    @for $i from 1 through 5 ( .definition-#($i) ( width: 10px * $i; ) )

    Compilation result in CSS:

    Definition-1 ( width: 10px; ) .definition-2 ( width: 20px; ) .definition-3 ( width: 30px; ) .definition-4 ( width: 40px; ) .definition-5 ( width: 50px; )

    @each directive

    The @each directive sets $var to each of the list or dictionary values ​​and outputs the styles it contains using the corresponding $var value.

    @each $animal in platypus, lion, sheep, dove ( .#($animal)-icon ( background-image: url("/images/#($animal).png") ) )

    Compilation result in CSS:

    Platypus-icon ( background-image: url("/images/platypus.png"); ) .lion-icon ( background-image: url("/images/lion.png"); ) .sheep-icon ( background- image: url("/images/sheep.png"); .dove-icon ( background-image: url("/images/dove.png"); )

    @while directive

    The @while directive takes a SassScript expression and loops through the styles it contains while the expression evaluates to true . It can be used to create more complex loops than @for is suitable for, although it is rarely needed. For example:

    $index: 5; @while $index > 0 ( .element-#($index) ( width: 10px * $index; ) $index: $index - 1; )

    Compilation result:

    Element-5 ( width: 50px; ) .element-4 ( width: 40px; ) .element-3 ( width: 30px; ) .element-2 ( width: 20px; ) .element-1 ( width: 10px; )

    Functions in Sass/SCSS

    Using Sass/SCSS you can use functions in the same way as in other languages.

    Let's create a function three-hundred-px() that returns 300px.

    @function three-hundred-px() ( @return 300px; ) .name ( width: three-hundred-px(); border: 1px solid gray; display: block; position: absolute; )

    After applying the class.name, the width of the element will be 300 pixels.

    Hello.

    Functions in Sass can return any valid CSS value and can be assigned to any property. They can even be calculated based on the passed argument.

    @function double($width) ( @return $width * 2; )

    Trigonometry

    The trigonometric functions sin() and cos() are often found as built-in classes in many languages, such as JavaScript for example.

    Their work is worth studying if you need to reduce the time spent developing user interface animations, such as creating a trobber. By the way, we already talked about this in one of the articles. But in this case it will be code, not a GIF image inserted into an HTML document.

    Below we will look at a couple of examples for creating interesting animation effects using the sin() function, in which the amount of code is kept to a minimum. Then you can scale this knowledge to create interactive user interface elements (movement in a circle, wavy animation).

    The benefit of using trigonometry in combination with CSS is that there are no additional HTTP requests as is the case with gif images.

    You can write trigonometric functions in Sass. Read more about this.

    Writing your own functions

    In trigonometry, many operations are based on functions. Each function builds on the other. For example, the rad() function requires the use of PI() . The cos() and sin() functions require the use of rad() .

    @function PI() ( @return 3.14159265359; )

    Writing functions in Sass/SCSS is very similar to writing functions in other languages.

    Using the pow() function:

    @function pow ($number, $exp) ( $value: 1; @if $exp > 0 ( @for $i from 1 through $exp ( $value: $value * $number; ) ) @else if $exp< 0 { @for $i from 1 through -$exp { $value: $value / $number; } } @return $value; }

    Using the rad() function:

    @function rad ($angle) ( $unit: unit ($angle); $unitless: $angle / ($angle *0 + 1); //If the angle value is in degrees ("deg"), you need convert it to radians. @if $unit == deg ( $unitless: $unitless / 180 * PI(); ) @return $unitless )

    To calculate the tangent using the tan() function, you need to use the sin() and cos() functions..

    Absolutely all experienced layout designers use preprocessors. There are no exceptions. If you want to succeed in this activity, do not forget about these programs. At first glance, they can cause quiet horror in a beginner - this is too similar to programming! In fact, you can understand all the capabilities of CSS preprocessors in about a day, and if you try, then in a couple of hours. They will make your life much easier in the future.

    How CSS preprocessors came to be

    To better understand the features of this technology, let’s briefly dive into the history of the development of visual presentation of web pages.

    When mass use of the Internet first began, no style sheets existed. The execution of documents depended solely on browsers. Each of them had their own styles that were used to handle certain tags. Accordingly, the pages looked different depending on which browser you opened them in. The result is chaos, confusion, and problems for developers.

    In 1994, Norwegian scientist Haakon Lie developed a style sheet that could be used to style the appearance of a page separate from the HTML document. The idea attracted the attention of representatives of the W3C consortium, who immediately began to refine it. A few years later, the first version of the CSS specification was released. Then it was constantly improved and refined... But the concept remained the same: each style is given certain properties.

    Using CSS tables has always caused some problems. For example, layout designers often had difficulties with sorting and grouping properties, and not everything is so simple with inheritance.

    And then came the two thousandths. Professional front-end developers increasingly began to engage in markup, for whom flexible and dynamic work with styles was important. The CSS that existed at that time required prefixing and tracking support for new browser features. Then JavaScript and Ruby experts got down to business, creating preprocessors - add-ons for CSS that add new features to it.

    CSS for Beginners: Features of Preprocessors

    They perform several functions:

    • unify browser prefixes and hacks;
    • simplify the syntax;
    • make it possible to work with nested selectors without errors;
    • improve styling logic.

    In short: the preprocessor adds programming logic to the CSS capabilities. Now styling is performed not by the usual enumeration of styles, but by using several simple techniques and approaches: variables, functions, mixins, loops, conditions. In addition, it became possible to use mathematics.

    Seeing the popularity of such add-ons, the W3C began gradually adding features from them into the CSS code. For example, this is how the calc() function appeared in the specification, which is supported by many browsers. It is expected that soon it will be possible to set variables and create mixins. However, this will happen in the distant future, and preprocessors are already here and already working perfectly.

    Popular CSS preprocessors. Sass

    Developed in 2007. Initially it was a component of Haml, an HTML template engine. The new capabilities for managing CSS elements appealed to Ruby on Rails developers, who began to distribute it everywhere. Sass introduced a huge number of features that are now included in any preprocessor: variables, nesting of selectors, mixins (at that time, however, you could not add arguments to them).

    Declaring Variables in Sass

    Variables are declared using the $ sign. You can store properties and their sets in them, for example: “$borderSolid: 1px solid red;”. In this example, we declared a variable called borderSolid and stored the value 1px solid red in it. Now, if in CSS we need to create a red border 1px wide, we simply specify this variable after the property name. Once declared, variables cannot be changed. Several built-in functions are available. For example, let's declare a $redColor variable with the value #FF5050. Now in the CSS code, in the properties of some element, we use it to set the font color: p ( color: $redColor; ). Want to experiment with color? Use the darken or lighten functions. This is done like this: p ( color: darken($redColor, 20%); ). This will make redColor 20% lighter.

    Nesting

    Previously, it was necessary to use long and awkward constructs to indicate nesting. Let's imagine that we have a div containing p, and it, in turn, contains a span. For div we need to set the font color to red, for p - yellow, for span - pink. In regular CSS this would be done like this:

    With the help of a CSS preprocessor, everything is made simpler and more compact:

    Elements are literally “nested” one into another.

    Preprocessor Directives

    You can import files using the @import directive. For example, we have a file fonts.sass, which declares styles for fonts. We include it in the main style.sass file: @import ‘fonts’. Ready! Instead of one large style file, we have several that can be used to quickly and easily access the properties we need.

    Hagfishes

    One of the most interesting ideas. Makes it possible to set a whole set of properties in one line. They work as follows:

    @mixin largeFont (

    font-family: 'Times New Roman';

    font-size: 64px;

    line-height: 80px;

    font-weight: bold;

    To apply a mixin to an element on the page, use the @include directive. For example, we want to apply it to the h1 header. The result is the following construction: h1 ( @include: largeFont; )

    All properties from the mixin will be assigned to the h1 element.

    Preprocessor Less

    Sass syntax is reminiscent of programming. If you're looking for an option that's more suitable for beginner CSS learners, check out Less. It was created in 2009. The main feature is native support, so it will be easier for layout designers unfamiliar with programming to master it.

    Variables are declared using the @ symbol. For example: @fontSize: 14px;. Nesting works on the same principles as in Sass. Mixins are declared as follows: .largeFont() ( font-family: 'Times New Roman'; font-size: 64px; line-height: 80px; font-weight: bold; ). To connect, you don't need to use preprocessor directives - just add a freshly created mixin to the properties of the selected element. For example: h1 ( .largeFont; ).

    Stylus

    Another preprocessor. Created in 2011 by the same author who gave the world Jade, Express and other useful products.

    Variables can be declared in two ways - explicitly or implicitly. For example: font = 'Times New Roman'; - this is an implicit option. But $font = ‘Times New Roman’ is explicit. Mixins are declared and included implicitly. The syntax is: redColor() color red. Now we can add it to the element, for example: h1 redColor();.

    At first glance, Stylus may seem confusing. Where are the “native” parentheses and semicolons? But once you dive into it, everything becomes much clearer. However, keep in mind that long-term development with this preprocessor may unlearn you from using classic CSS syntax. This sometimes causes problems when you need to work with “pure” styles.

    Which preprocessor should you choose?

    It really... doesn't matter. All options provide approximately the same capabilities, just the syntax is different for each. We recommend doing the following:

    • if you are a programmer and want to work with styles as code, use Sass;
    • if you are a layout designer and want to work with styles as with regular layout, pay attention to Less;
    • if you like minimalism, use Stylus.

    For all options, a huge number of interesting libraries are available that can further simplify development. Sass users are advised to check out Compass, a powerful tool with a lot of built-in capabilities. For example, after installing it, you will never have to worry about vendor prefixes. Makes working with meshes easier. There are utilities for working with colors and sprites. A number of already announced mixins are available. Dedicate a couple of days to this product - thereby you will save a lot of effort and time in the future.