📜 ⬆️ ⬇️

Our experience of moving to adaptive UI-kit



Hello! My name is Dmitry Belyaev, I work as a frontend-developer in the Mail.Ru Group media projects department. Together with our team we develop and support 13 vertical projects of various subjects. Until recently, each of them was quite different from the rest both in terms of design and in terms of technologies used. As they are now developing in similar directions, managers increasingly began to come to us with the question: “We recently rolled out feature N on one of the projects, can we launch an analogue for our project next week / tomorrow / yesterday?”, After which we began to dig in the features of the layout of the next project, stumble upon new pitfalls, not counting the fact that we have repeatedly solved the same tasks. Such situations began to make everyone think about unification, which would not only increase project awareness, but also reduce the time for solving work tasks.

At the same time, mobile versions of projects for touch-devices began to be developed, and it was decided to try out a new approach to development specifically for them. The structure of the pages of the mobile version of a site is usually much simpler than similar pages of desktop versions and, accordingly, in case of an error when choosing a method for solving a particular task, we would spend less time on repairing. The interface design department prepared for us a UI-kit that contained a huge number of prototypes and layouts for individual blocks and layout of typical pages like listings of news, articles, comments. Additionally, unique interface elements were drawn, which are needed only for some specific projects, for example, a recipe block on the Lady or a calculator on the Courses. They have developed their own library of blocks, based on the BEM methodology, using the BEM-tools we have developed in conjunction with the Fest template and Stylus.

The approach with the use of such a library of blocks proved to be excellent. It allowed us to avoid the need for multiple duplication of the same code and greatly reduced labor costs. He was also pleased with the designers, since they no longer had to track the compliance of the design of each block on each project, it was enough to check the block on any of the projects, because now they used a single implementation of common blocks stored in a single repository.
')
After the successful launch of new mobile versions, we decided to use this approach in the upcoming redesigns of desktop versions of projects. Thanks to the uniform style and abstract implementation of the blocks after the first launches, we could already begin to impose most of the pages based on the design prototypes, without the need for detailed drawing on the layouts of each design element. This meant a decrease in the amount of resources spent by designers. In addition to such exciting prospects for the implementation of this approach, unforeseen difficulties awaited us. And today I want to tell you about how we overcame them.

1. Blocks that can do too much


Since the practice of using the UI-kit and related technical solutions began with mobile versions, the pages of which in most cases consist of simple elements, it often turned out that the design of these elements is in many ways similar. It seemed quite logical to implement them in the form of one common unit, which would have a standard output and a set of modifiers for different cases. Initially, everything worked just fine, but with the launch of new projects, the number of options for using the unit has steadily increased, and the logic of the work of existing options has become increasingly difficult. It took more and more time to support such a unit. For example, it would seem that a simple task - highlighting the links of news that the user has already viewed, resulted in the addition of a new modifier and prescribing it to all news entities of this block.



Under such circumstances, it was natural to decide to divide all these cases into separate blocks, even if they differ semantically from each other with a similar design. Otherwise, one of the main features of the approach could be lost - simple support for whale design with the ability to easily apply and maintain it on all projects. So we had separate blocks responsible for the output of news, comments, consultations, information about institutions, and so on.

2. Fonts


In search of beautiful font solutions for desktop versions of projects, 4 Roboto fonts were originally selected and a font grid was drawn that contained standard font use options when creating layouts. In fact, we rather quickly faced the problem of the human factor, when, by chance, new dimensions appeared in the models in already standardized blocks. This led us to the need to create a separate config for describing font parameters. Initially, all options for their use were divided in the config into semantic groups: headers, typesetting text, small signatures. Each of the sizes corresponded to any key name, but the number of outlines in the grid was constantly changing. Maintaining it in this form became problematic, and we decided to store information about fonts in a common hash, divided into groups by type.

$font['sets'] = defaults({ light: { _default: { font-weight: $font.weight.light }, '9': { font-size: 9px, line-height: 12px, _media: { font-size: 11px, line-height: 16px } }, '13': { font-size: 13px, line-height: 16px, _media: { font-size: 15px, line-height: 20px } }, '15': { font-size: 15px, line-height: 20px, _media: { font-size: 17px, line-height: 24px } }, ... 

To work with this config, a small mixin was written in the stylus, through which all font sizes on projects began to be written. At the same time, for any element it can be called up in an adaptive version, by passing an additional parameter, depending on which size will increase for large screen resolutions.

 set(hash, media = false) if (media) if ('_media' in hash && type(hash._media) is 'object') for $size in 'medium' 'large' +forScreen($size) for $attr-name, $attr-value in hash._media {$attr-name}: ($attr-value) for $attr-name, $attr-value in hash if ($attr-name != '_media') {$attr-name}: ($attr-value) .block__element set: $font.sets.light['15'] true 

Later, this solution helped us a lot when, during the redesign of the first desktop project using the UI-kit, there were problems with displaying fonts on Windows. Their rendering was far behind the Mac OS version, and since we used a rather thin Roboto Light, we could not afford to leave them that way. It was decided to use an additional css-file, in which the font styles would be substituted for their counterparts fatter. In addition, almost immediately came the remark from the designers that some styles still look good, and in the current version they should be left the same.

Thanks to the configuration, it was enough for us to create an additional file, the stylus, in which we went through the configuration and replaced all the styles with the necessary design conditions. After compilation, we received 2 separate css-files: one for Windows users and the second for all other operating systems.

3. Coloring projects


Since the projects began to use many identical blocks, we had to provide users with some additional factor to distinguish our projects from each other. We achieved this goal by using accent colors in the design. For this, a separate stylus-config was created with a description of the color palette, and the corresponding values ​​were recorded on each individual project. To begin with, 2 accent colors and several colors for the page backgrounds were put into it. Over time, it was overgrown with standard color options, separated by semantics and shades.

If any of these colors were used in the block, it was not directly written into the styles, but into a separate block config. This made it possible not to get extra lines of code after the assembly when changing the color of the block on your project.

 $stepBlock = { default: { border: #d8d8d8, bg: #fff, color: #000, colorText: #000 }, states: { active: { bg: $color.primary.project, border: $color.secondary.project, color: #fff }, done: { border: $color.secondary.project, bg: #fff, color: #000 } } } 

In addition to applying accent colors to backgrounds, borders and text, almost immediately there were cases when it was necessary to repaint the icons or change their hue depending on the brightness of the accent color (for example, if the icon is on top of it). Moreover, sometimes it was necessary to animate the change in their color and change their size.

Initially, all the icons on the projects were assembled into sets of sprites from separate Grunt Tasks png-files, but after the appearance of such cases, we decided to make some of them fonts. We asked the designers to draw them in svg and put the resulting files into the repository as a separate block. Each of the projects was able to pick up the necessary icons and assemble a font with icons using Grunt, which will be automatically connected to the page.

4. Flat design


At the beginning of the redesign of desktop versions for the Health Mail.Ru project, a design that was different in style from the rest of the line was drawn, but since for the most part the block structure and their visual component was similar to standard solutions, it was decided to develop this project using the same methodology. Health models for the most part complied with the canons of a flat design and, accordingly, many of the blocks looked lighter, there were no shadows and gradients in them, which means it was possible to lighten the layout with styles. However, some of them could be used in more complex blocks, for example, buttons were components of paging, comments, polls, and so on.



To facilitate the layout, we carried out some of the elements of the blocks into separate files that can be rewritten on the project, getting rid of unnecessary wrappers. Also, there was no wish to drag extra styles to the project, so all default styles were moved to the _default modifier, which you can disable and start using your own variant. For example, the following dependency implementation of a button block in a whale and on a single project:

 ({ mustDeps: [ { block: 'icon' }, { block: 'link' }, { mod: 'default' } ], shouldDeps: [ { elems: ['inner', 'text', 'loader', 'count'] }, { mods: ['large', 'font', 'color', 'loading', 'full', 'simple'] } ] }); ({ noDeps: [ { mods: ['default', 'search'] }, { elems: ['inner', 'text', 'count'] } ] }) 

5. Adaptive mesh


In addition to adaptive fonts from the above item, it was supposed to adapt the content for different screen resolutions. We decided not to make standard tires, but to limit ourselves to three screen resolutions, on which the width of the wrapper will vary, and also changes in the display of blocks will be possible. To implement the adaptive grid, a regular config was created, in which the sizes of the columns were set, standard padding for the blocks responsible for the grid, media breaks. Since in some places it was necessary to sufficiently change the appearance of the page, each of the breakpoint was assigned its own key, which we began to use when writing block modifiers and mixins connected by layout adaptability.

 $layout['sizes'] = { small: { media: { max: 1279px }, cols: 1..47, wrapper: 940px }, medium: { media: { min: 1280px, max: 1339px }, cols: 1..59, wrapper: 1180px }, large: { media: { min: 1340px }, cols: 1..65, wrapper: 1300px } } mqForScreen($size, $sizes=$layout) $mq = screen for k in keys($sizes.sizes[$size].media) $mq = s('%s and (%s-width: %s)', $mq, s(k), $sizes.sizes[$size].media[k]) return $mq forScreen($size, $sizes=$layout) $mq = mqForScreen($size, $sizes) @media $mq {block} if $size == $layout.default .no-mq & {block} 

For all columns, we added modifiers that specify their sizes at each resolution. For example, it is possible to pass small_10 medium_20 large_percent-50 modifiers to any column, and it, accordingly, will occupy 10 cells wide at a small screen resolution, 20 at an average and will stretch half the parent unit at a large one. At the same time, all possible sizes are initially registered in the same config and are deployed in css using mixins. In a similar way, adaptability is added to the remaining blocks, if necessary, as well as to some helper classes like .hidden, hiding the blocks at the required permissions.

6. Conclusion


Over the past two years, since we started working on whale design, we have achieved good results by launching mobile versions for almost all of our projects and updating some of them to a new corporate style. The same approach is already being used in full on the desktop versions of projects: 6 projects have been redesigned, and we continue to work actively in this direction. The technique itself has more than once helped to implement quite complex components and significantly reduce the labor costs of their implementation in all projects.

We will be glad if you share your experience in developing projects built on the UI-kit in the comments, tell us about the problems you have encountered.

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


All Articles