šŸ“œ ā¬†ļø ā¬‡ļø

Organization of adaptive layout in BEM with SCSS

One of the main difficulties encountered by many front-end developers using the BEM methodology in CSS is the way to organize adaptive layout. As is well known, blocks and elements must be independent of each other, as well as the context in which they are located, which means that they are derived from the device. In this case, in different screen resolutions, the block may actually have a different display. It will be about how to organize the adaptability of such representations, while retaining the ability to use each of them, regardless of any external factors and from each other.

A common practice in solving this problem is to write the block code, as well as modifiers that are used in conjunction with it, but only for certain types of devices and their permissions. For example, the .product block and its modifiers: .product_mobile, .product_tablet, .product_desktop. Modifiers contain a change in the representations for a particular class of devices and permissions, adding modifiers to the block, we can manage its adaptability. More often than not, developers neglect this practice, setting all these states in the block itself, receiving at the output an adaptive block for all devices. With this strategy, there are no problems until there is a need on the mobile device (* _mobile) to display the presentation for the tablet (* _tablet) or to use on all devices only one type of presentation on one page and the other on different. How to organize such an interaction, while maintaining the independence and portability of representations, we consider next.

Task


There are 2 pages, a catalog and a main one.
There are 3 views of the block of goods: A, B, C
And three screen resolutions: Mobile, Tablet, PC.
It is necessary to display the main page of the site: A - mobile version. B - tablet. C - PC.
On the catalog page: C - Mobile, A - Tablet, B - PC.
It is also necessary to preserve the possibility of switching the block representation when adding an additional modifier to it.

At this stage, it becomes obvious that we need to create 6 modifiers, and organize them in such a way that they do not overlap each other in different situations. We also need to preserve the possibility of a hard assignment of the type of block to modifiers, without losing its adaptability. It becomes obvious that we will have to duplicate the code in cases (ā€œCā€ presentation for PC, ā€œCā€ presentation for mobile devices). To avoid duplication, in this case, SCSS mixins are well suited, which ultimately require only 3 (one for each block representation, A, B, C), adaptability and the ability to switch the state are achieved through the special organization of mixins and their connection.

Mixin organization


You can use two ways to organize mixin: impose each presentation as independent or impose one basic representation and expand it. Working example:
')

Simplified example
//    1.    ,  . @mixin type1-A() { width: 100px; height: 100px; background-color: red; } @mixin type1-B() { //   width: 100px; height: 100px; background-color: blue; } //    2.    2 ,    ,      @mixin type2-A() { width: 100px; height: 100px; background-color: red; } @mixin type2-B() { // 2  background-color: blue; } //-    .      (c.  type1-b type2-b ) .t1-a { @include type1-A(); } .t1-b { @include type1-B(); } .t2-a { @include type2-A(); } .t2-b { @include type1-A(); @include type2-B(); } //      ,   2    .   . .A { @include mix(); @include mix_A(); } .B { @include mix(); @include mix_B(); } 


The main advantage of the second method is in a smaller amount of code and the avoidance of duplicates; it is preferable when the presentation does not change significantly. The first method leads to significant duplication, but allows you to transfer a separate type of presentation between different projects, without having to transfer them all, while the presentation can change dramatically, without losing the readability of the code and understanding of its work, because All properties will be in the same mixin. Both of these methods are equally well suited for organizing code for adaptive, the only question is in decomposition and tasks.

Rewrite mixins in a slightly different format. Which makes it easy to control the final representations.

Mixin Organization Code
 //$b -  , $m -    @mixin present_type_1($b, $m:"") { #{$m}#{$b} { //   .block-name //...code... } #{$m} #{$b}__item { //  .block-name__item //...code... &_modificator_value { //  .block-name__item_modificator_value //...code... } } } 


This way of organizing a mixin allows you to connect it in many different ways, making the management of perceptions more understandable. Suppose we have 3 mixins present_type_1, present_type_2, present_type_3, consider the possible options for their connection:

Connecting mixin
 //      .some-block,     1 @include present_type_1(".some-block"); //      .some-block   .some-block_modificated,     2 @include present_type_2(".some-block", ".some-block_modificated"); //   @include present_type_3(".some-block", ".some-block_type_3"); 


An example more close to real life, tile goods:


We organize the interaction of mixins for different screen resolutions:

Adaptive mixin connection
 // 1,  ,    @media all and (min-width:901px) { @include present_type_1(".some-block"); } // 2,    @media all and (min-width:601px) and (max-width:900px) { @include present_type_2(".some-block"); } // 3,    @media all and (max-width:600px) { @include present_type_3(".some-block"); } //   -      2.      @include present_type_2(".some-block", ".some-block_force-main-present"); // ,       3,        ,   . @media all and (min-width:901px) { @include present_type_3(".some-another-block"); } @media all and (min-width:601px) and (max-width:900px) { @include present_type_2(".some-another-block"); } @media all and (max-width:600px) { @include present_type_1(".some-another-block"); } //  .     3,    ,   2,   . @include present_type_3(".some-block"); @media all and (min-width:601px) and (max-width:900px) { @include present_type_2(".some-block", ".some-block_tablet"); } 


Tile with adaptive:



This is the method for solving the previously described problem. With proper organization of mixins and ways to connect them, you can achieve a flexible display of the block in different screen resolutions and different contexts. At the same time, mixins are independent in themselves, so they can be reused separately from each other, on different projects.

Full example with the solution of the problem described in the beginning of the article:



Bonus


We depart from the BEM methodology. There are times when it is more convenient to modify the descendants, depending on the selector of their parent. For example, change the view of all products in the tile products, changing the class on the parent. Let us consider the modifiers product_parent_vertical product_parent_horizontal as an example.

Layout
 <div class="product-layout"> <div class="product"></div> <div class="product"></div> <div class="product"></div> <div class="product"></div> <div class="product"></div> </div> <div class="product-layout product_parent_vertical"> <div class="product"></div>    </div> <div class="product-layout product_parent_horizontal"> <div class="product"></div>    </div> 


Consider an example of the organization of such behavior:

The implementation of the interaction
 @mixin vertical($b, $m:""){/*...*/} @mixin horizontal($b, $m:""){/*...*/} //    @include vertical(".product"); // ,        ,      @include vertical(".product",".product_parent_vertical "); // ,    ,      . @include horizontal(".product",".product_parent_horizontal "); 


Such an approach is rather a weak solution than a good practice, even if this behavior is set more explicitly, for example, by adding a third parameter to the mixin, it is nevertheless worth mentioning.

Tile with bonus part code:



Conclusion


This way of organizing mixin is well suited for adaptive layout or modifier organization, while allowing you to easily transfer views between individual projects independently of each other, providing extensive opportunities for combining them.

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


All Articles