Introduction

This article describes how to boost a routine process of composing CSS files when you are developing a frontend of an online store. First of all, let's check out how can the official documentation of Magento 2 help with this task (Reference 1). Here you can find several typical strategies on customization of the basic themes – luma and blank:

  • Extending of the existing CSS rules
  • Overriding of CSS

In the first case, you should create a file called '_extend.less' for each inherited theme and then declare additional CSS rules in this file.

Extending CSS

In the second case, you should copy and paste a file called '_theme.less' from the parent theme to your custom theme in order to override the CSS rules:

Extending CSS

However, it's not recommended to use such an approach: overriding a CSS requires you to copy and paste the files from an original theme to your custom theme, which may lead to insufficient CSS rules after upgrading Magento 2 in future.

So, let's consider the first case in more detail. A file called '_extend.less' is imported from 'styles-m.less' to 'styles-l.less' using the '@magento_import' instruction. Even if you add only a few lines of the less code in '_extend.less', the saving process will clearly show that the styles are processed slowly from the very beginning.

Measurements

And if you try to create a new global less file, link it only to the current theme and then add CSS code into this file, then GRUNT, the system configuration in Magento 2, will recompile 'styles-l.less' and 'styles-m.less' in the same way, since their source code remained almost the same. Therefore it's quite important to reduce time spent for the less compilation.

Frontend development speed can be optimized through integration of an alternative assembly subsystem for JS files in Magento 2 based on gulp-frontools (Reference 2) along with minor changes in the structure of less files in your theme (i.e. keep the CSS rules which extend blank or luma outside 'styles-l.less' and 'styles-m.less').

Brief overview of frontools

Integrating frontools in your project will enable you with the following key benefits:

  • Integrated browsersync
  • Support of postcss plugins
  • Faster less compilation

Browsersync is a better alternative of the livereload plugin due to the following reasons:

  • Browsersync can be linked to any HTML page as an external JS file in order to reload styles of a web page in any browser, while livereload can only work by installing plugins in end user's browsers.
  • Browsersync offers a special tool for remote debugging ('weinre'), which includes reviewing a DOM tree of a web page for any connected device, debugging a JS code, analyzing the current downloading status of web page resources in a network, etc.
  • And finally, browsersync offers a multitude of supporting functions, such as synchronization of mouse-based or keyboard-based events among devices, synchronization of submit events across forms, etc.

As for postcss plugins, always keep in mind that when styles are compiled using server-side tools (bin/magento setup:static-content:deploy), all the code that you write may be ignored, since nodejs will not be used in any way. In this case, before starting assembly of static content in Magento 2, you will need to put your compiled CSS file in the same directory where the source less files are stored (this can be easily automated by adjusting the logic of gulp tasks), thus instructing Magento to skip the less compilation step and simply copy and paste CSS from

app/design/frontend/vendor/themename/web/css/
to the following directory::
pub/static/frontend/vendor/themename>/locale/web/css/

You find detailed instructions on how to install and set up a theme in Reference 2.

Modification of a theme

Once frontools are sucessfully configured, you can start reorganization of the CSS components in the project. As mentioned in the beginning of this article, we would like to extract CSS rules which extend blank or luma into separate files (i.e. keep them outside 'styles-l.less' and 'styles-m.less'). Below you can find a sample file structure for such a theme:

theme structure

 

Magento is commonly known as a modular and flexible CMS. Therefore implementation of any module in which CSS, JS or HTML is used should be kept only within the module itself. As for CSS, this idea is partly reflected in the theme structure. Most CSS code for the blank and luma themes is written in modules:

app/design/frontend/vendor/themename/vendor_modulename/web/css/source/_module.less

This is why, for better code readibility and file organization, minor changes in CSS should be stored in modules, as shown above for the 'Magento_Customer' module – all style extensions for this module are kept in

Magento_Customer/web/css/source/_module_extend.less.

Files with the 'module_extend.less' mask are not imported to 'styles-l.less' and 'styles-m.less'. Instead, they are linked in files called 'desktop.less' and 'mobile.less' that will contain all exact changes in the blank or luma themes. Below you can find a listing of 'mobile.less' and 'desktop.less' with comments

// mobile.less
//
//  Include library Magento UI with variables
//  ---------------------------------------------

@import 'source/lib/_lib.less'; 
@import 'source/_variables.less';

//
//  Extensions of modules and their widgets – recursive search across all modules in the theme
//  ---------------------------------------------

//@magento_import 'source/_module_extend.less'; 
//@magento_import 'source/_widgets_extend.less'; 

//
//  Mixins for media queries
//  ---------------------------------------------

@import 'source/lib/_responsive.less';

@media-target: 'mobile'; // Specifies the target device type for this file

//
//  Overriding global variables
//  ---------------------------------------------

@import 'source/_theme.less';
@import 'source/_theme_extend.less';

As you can see from the listing, we've excluded from 'mobile.less' all the code which was already present in 'styles-m.less', inserted additional '@magento_import' instructions for module/widget extensions and also linked a file called '_theme_extend.less' for overriding global variables. The official documentation instructs to override variables by copying and pasting a large file called '_theme.less' from the parent theme. The same can be done with a file of styles intended for desktop devices:

// desktop.less
//
//  Include library Magento UI with variables
//  ---------------------------------------------

@import 'source/lib/_lib.less'; // Global lib
@import 'source/_variables.less';

//
//   Extensions of modules and their widgets – recursive search across all modules in the theme
//  ---------------------------------------------

//@magento_import 'source/_module_extend.less';
//@magento_import 'source/_widgets_extend.less';

//
//  Mixins for media queries
//  ---------------------------------------------

@import 'source/lib/_responsive.less';

@media-target: 'desktop'; // Specifies the target device type for this file
@media-common: false; // Do not write to styles-m.less

//
//  Overriding global variables in the theme
//  ---------------------------------------------

@import 'source/_theme.less';
@import 'source/_theme_extend.less';

Don't forget to import 'source/_theme_extend.less' in the end of 'styles-l.less' and 'styles-m.less' files, so that changes in global variables might influence the less mixins which define the basic visual appearance of your online store.

Summary

Thus, the namespace of the compiled CSS for our custom theme is now separated from the parent theme's namespace by linking to the new files. After compiling CSS by means of 'frontools', you will notice a dramatic increase in speed:

Spead measure with fronttools

The screenshot above shows the time spent for CSS compilation performed using gulp-duration. As you can see, the saving process for each less file takes only 0.5 seconds instead of 6.8 seconds, after which browsersync immediately updates the web page styles without refreshing the page itself.

 

References

  1. Magento theme customization
  2. SnowdogApps/magento2-frontools project on Github