Smaller loops used to create column classes on Twitter. How do they work?

Bootstrap uses some LESS mixins to generate class columns (and several other classes);

.make-grid-columns() { // Common styles for all sizes of grid columns, widths 1-12 .col(@index) when (@index = 1) { // initial @item: ~" .col-xs-@ {index}, .col-sm-@ {index}, .col-md-@ {index}, .col-lg-@ {index}"; .col((@index + 1), @item); } .col(@index, @list) when (@index =< @grid-columns) { // general; "=<" isn't a typo @item: ~" .col-xs-@ {index}, .col-sm-@ {index}, .col-md-@ {index}, .col-lg-@ {index}"; .col((@index + 1), ~"@{list}, @{item}"); } .col(@index, @list) when (@index > @grid-columns) { // terminal @{list} { position: relative; // Prevent columns from collapsing when empty min-height: 1px; // Inner gutter via padding padding-left: (@grid-gutter-width / 2); padding-right: (@grid-gutter-width / 2); } } .col(1); // kickstart it } 

I see that the LESS mixin guard is used to create loops, and I can understand the code examples that are given in the LESS documentation ;

 .loop(@counter) when (@counter > 0) { .loop((@counter - 1)); // next iteration width: (10px * @counter); // code for each iteration } div { .loop(5); // launch the loop } 

But I can’t understand exactly how the more complex nested security expressions used at boot work. Can someone comment on the above bootstrap code in a bit more detail to give me an indication of what is going on?

0
source share
1 answer

The purpose of the .make-grid-columns() mix is ​​to create a long list of selectors that have the same properties. This list may not be hard code in the code due to the number of columns ( @grid-columns ) may vary.

You have already illustrated the basics of the cycle in Less in the question yourself.

To understand mixins, you need to understand that Less allows you to use the same mixin name many times. All "matching" mixins will be compiled into CSS code. When when () mixer fuses allow you to set the condition for compliance. When the guard does not match the mixer, it does not compile. In addition to mixins guards, you can also use pattern matching, than you can match by value as follows:

 .mixin1(a,@width){} .mixin1(b,@width){} 

Call .mixin(a,20px); matches only the first mixin. Partern matching based on arity (number of arguments) will also work. Please note that .col(@index) when (@index = 1) does not need protection ( see also ). calling .col(@index) has only one argument, therefore .col(1); matches only this mixin based on arity matching. Mixing .col(@index) calls .col(@index, @list) mixin (s). Mixing .col(@index) when (@index = 1) will only be called for the first iteration. The reason for having two mixins instead of one is that Less does not support if / else. The selector list cannot begin or end with a comma, so the first or last element in the selector list must be different from the others.

Alternatively, you can use mixin with an additional argument:

 .mixin(@iterator; @item:~""; @seperator:~"") when (@iterator < 5){ @list: ~"@{item} @{seperator} @{iterator}"; .mixin((@iterator + 1); @list; ","); } .mixin(@iterator; @list; @seperator) when (@iterator = 5){ .selector{ @{list}: value; } } .mixin(1); 

@seperator will be empty ( ~"" ) for the first call and a comma ( "," ) for all other calls. Note that a mixin with default parameters also corresponds to calls that do not have setpoints for default values: So, .call(1); matches mixin .call(@a; @b:4; @c:5){} .

As mentioned in the comments ~"@{list}, @{item}" generates a list of selectors via string concatenation.

The last iteration .col(@index, @list) when (@index =< @grid-columns) calls col((@grid-columns + 1)....) mixin with @ index=@grid-columns and therefore matches the last mixin .col(@index, @list) when (@index > @grid-columns) in the structure.

@{list} { } use selector interpolation to set the list of selectors and its properties.

Of course, you should also read the excellent seven-max blog post about this structure to create a list of selectors.

Finally, you should be aware that Bootstrap needs such a long list of selectors because it avoids (partial) attribute selectors. Instead of a list of selectors, you can also use the following CSS / Less code:

 [class^="col-"], [class*=" col-"] { position: relative; // Prevent columns from collapsing when empty min-height: 1px; // Inner gutter via padding padding-left: (@grid-gutter-width / 2); padding-right: (@grid-gutter-width / 2); } 

The reason to avoid choosing attribute selectors is that some browsers compute them slowly. As you can see at http://benfrain.com/css-performance-revisited-selectors-bloat-expensive-styles/ , you can disable this argument. Personally, I believe that unused code is a more important performance issue than using attribute selectors in most Bootstrap projects.

+1
source

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


All Articles