📜 ⬆️ ⬇️

LESS underutilized, but no less excellent.

This post is inspired by the comment of the respected habraser SerafimArts that LESS does not know much. I would like to dispel these seditious statements and at the same time show how wonderful LESS can be if it is properly prepared.

Note: some examples of “life” in this article are provided for those people who for some reason (including religious) do not use Autoprefixer.

Note 2: for everything that is written below, the latest version of LESS is used, because there is no reason at all not to use it.
')


Mergers


They are associations, they are merdzhi ( Merge ). Used if you need to add something through a space or comma. Transjunctions, transforms, multiple backgrounds, shadows (sorry for the Russian word: box-shadow sounds somehow unkind) are rejoicing. Best of all, examples will tell me.


We unite through the space right in the mixin
.transform (@value) { transform+_:@value; } .transformed { .transform(rotateX(10deg)); .transform(scale(1.2,1.1)) } 

Compiles to
 .transformed { transform: rotateX(10deg) scale(1.2, 1.1); } 


And now separated by commas
 .transition (@property: all,@duration: 0s,@delay: 0s,@ease: ease-in-out){ transition+: @arguments; } .transitioned { .transition(width,1s); .transition(opacity,0.5s,0.2s,linear); } 

Will turn into
 .transitioned { transition: width 1s 0s ease-in-out, opacity 0.5s 0.2s linear; } 


Exactly what is needed. No difficulty with using: just call the desired mixin as many times as you need. This is something even more convenient than a method with an indefinite number of parameters: a hard order of arguments will not allow you to get lost. Happiness, and only.

Conditions


Instead of the usual ifs in LESS, there are so-called guards ( guards ). Their essence is to cause different ads of one mixin depending on different conditions (there is something in them from generics). The life example is given in the same comments that inspired me: I would like to have transients for transforms with prefixes. So be it (note the when keyword after the mixin declaration):

 //    .transition (@property: all,@duration: 0s,@delay: 0s,@ease: ease-in-out) when (@property=transform) { -webkit-transition+: -webkit-transform @duration @delay @ease; -moz-transition+: -moz-transform @duration @delay @ease; -o-transition+: -o-transform @duration @delay @ease; transition+: -ms-transform @duration @delay @ease, transform @duration @delay @ease; //, -ms-transition    } //  . .transition (@property: all,@duration: 0s,@delay: 0s,@ease: ease-in-out) when not (@property=transform) { -webkit-transition+: @arguments; -moz-transition+: @arguments; -o-transition+: @arguments; transition+: @arguments; } .transitioned { .transition(width,1s); .transition(transform,0.5s,0.2s,linear); } 


At the output we get (formatting on my columns, the rest was done by the preprocessor)
 .transitioned { -webkit-transition: width 1s 0s ease-in-out, -webkit-transform 0.5s 0.2s linear; -moz-transition: width 1s 0s ease-in-out, -moz-transform 0.5s 0.2s linear; -o-transition: width 1s 0s ease-in-out, -o-transform 0.5s 0.2s linear; transition: width 1s 0s ease-in-out, -ms-transform 0.5s 0.2s linear, transform 0.5s 0.2s linear; } 


Isn't that great? Gardas support relations =,>, <,> =, <=, logical operators and, or, not, and some more functions for checking the type of variable (iscolor, isnumber, etc.), which allows you to vary the choice of myxin in significant the limits. A small but important nuance: LESS will take and execute all mixins with the same name that will pass through the guard. It is necessary not to forget and add all the necessary conditions for the "other" cases. And I think it is good. And why this is good, will be seen below.

Cycles


The statement that there are no cycles in LESS is absolutely true. But there is a recursion! Actually, developers propose to use it . As a vital example, create a sprite class generator for the image (do not miss the code, there are a lot of comments)

 //     .  ,   ,      .spriter (@x: 0,@y: 0) { background: #cccccc url("my-sprite-img.png") @x*20px @y*30px; } //    .generate_sprite(@x,@y) { .sprite-@{x}-@{y}{ .spriter(@x,@y); } } //    -        . // ,      ,    -. //LESS    ,   . .generate_sprite(@x,@y) when (@y=0) and (@x>0) { .generate_sprite(@x - 1,@spritey); } .generate_sprite(@x,@y) when (@y>0){ .generate_sprite(@x,@y - 1); } //,            @spritex: 1; @spritey: 2; //  .generate_sprite(@spritex,@spritey); 


At the output we get six classes for icons
 .sprite-1-2 { background: #cccccc url("my-sprite-img.png") 20px 60px; } .sprite-1-1 { background: #cccccc url("my-sprite-img.png") 20px 30px; } .sprite-1-0 { background: #cccccc url("my-sprite-img.png") 20px 0px; } .sprite-0-2 { background: #cccccc url("my-sprite-img.png") 0px 60px; } .sprite-0-1 { background: #cccccc url("my-sprite-img.png") 0px 30px; } .sprite-0-0 { background: #cccccc url("my-sprite-img.png") 0px 0px; } 


It was here that we used what all the appropriate mixins would be called. Because of this, we did not have to duplicate the call of the class generator in the control structures. Great.
You will probably say that this is a perversion. I think you will be right. Yet the absence of cycles in the language somewhat increases the difficulty in constructing such constructions. Fortunately, they are needed less often.

Entering the code as a parameter


As parameters, you can transfer full pieces of less-code that will behave quite logically. Examples are our everything: it is easier to show than to explain
 .placeholder(@content) { &::-webkit-input-placeholder{ @content(); } &:-moz-placeholder { @content(); } //,    } .withplaceholder{ .placeholder({ //,        color:blue; font-style: italic; }) } 


With a slight movement of the hand turns into
 .withplaceholder::-webkit-input-placeholder { color: blue; font-style: italic; } .withplaceholder:-moz-placeholder { color: blue; font-style: italic; } 


Moreover, you can insert a call to other mixins into the embedded code and everything will work:
 .topleft(@position){ top:@position; left:@position/2; } .keyframes(@name,@rules) { //     ? @keyframes @name { @rules(); }; } .keyframes(down,{ 0% { .topleft(0); }; 100% { .topleft(80); }; }); 


And at the exit
 @keyframes down { 0% { top: 0; left: 0; } 100% { top: 80; left: 40; } } 

We created the whole pack of keyframes (more precisely, they would have created if, for brevity and readability, I did not miss vendor prefixes) with a single team - ideally.

And one last thing in this section: do not like to write long media query? I understand you: every time the same thing. Let's cut it. Here is the code
 @width_mobile: 320px; @width_tablet: 640px; .media_mobile(@rules) { @media screen and (max-width: @width_tablet) and (min-width: @width_mobile) { @rules(); }; }; .class_parent{ width:300px; .media_mobile({ width:200px; .class_child{ width:100px; } }); } 


Will become so
 .class_parent { width: 300px; } @media screen and (max-width: 640px) and (min-width: 320px) { .class_parent { width: 200px; } .class_parent .class_child { width: 100px; } } 

Not to write a long steam locomotive every time media query - is this not a dream of an adaptive typesetter?

What can be said in the end. LESS is very actively developing. Some of these features did not exist literally until version 1.7, which came out literally six months ago. For me personally, this caused some inconvenience: I often have to work with different types of animations on the frontend. However, now I’m almost ready to kiss the developers for this nice and kind preprocessor, which is easy to learn (there were no problems in translating even the most inexperienced developers into it), powerful enough for all (or almost all) life situations, and importantly, it has a convenient readable syntax.

I hope this post will raise LESS a bit in the eyes of the habrasoobshchestva. Thank you all for your attention.

PS If someone can tell me how to make the highlight LESS on the Habré, I will be very grateful.

Source: https://habr.com/ru/post/233653/


All Articles