Less And UI Framework¶
Concepts¶
Separate Stylesheets¶
Magento 2 LESS compilation works differently to most platforms in that it generates two CSS output files instead of one.
<link rel="stylesheet" type="text/css" media="all" href="http://example.com/static/version1573393649/frontend/Magento/luma/en_US/css/styles-m.css" />
<link rel="stylesheet" type="text/css" media="screen and (min-width: 768px)" href="http://example.com/static/version1573393649/frontend/Magento/luma/en_US/css/styles-l.css" />
Note the media attribute on the link element for styles-l
.
This means that all devices will load styles-m
(mobile) and only devices that have a minimum horizontal resolution of 768 pixels will load styles-l
.
It is important to be aware of this as it is important that this optimisation is taken advantage of as much possible. Magento by default works in a mobile first approach when creating stylesheets and this should be adopted when working with Magento 2.
Practices¶
It is strongly advised that styling changes (in modules and themes) conform to the standard Magento 2 style rules.
Whilst not explicitly stated in the guidelines, it is clear that Magento 2 use the BEM
methodology when writing stylesheets.
Here is an example of BEM being used in Magento 2.
There are different flavours of BEM (block element modifier) in the wild.
More information Bem documentation Preprocessors and BEM
Tooling¶
Magento 2 uses Grunt by default when working in a development environment, it allows for much faster iterations when making changes To use Grunt, you must have Node and NPM installed in your development environment and all project dependencies installed.
Before this you'll need to install bzip2
sudo bash
yum install bzip2
Before Grunt will work, you will need to install and configure it for your theme
Commands¶
Grunt has a number of commands available to use, unfortunately at the time of writing Magento have not listed all the available commands and sufficient documentation.
All commands listed are prefixed with grunt <command-name>
.
Where available, the official Magento 2 description is used, different usage variants are comma separated.
To see a full list of available Grunt commands, use grunt -h
.
Command | Usage | Description | Notes |
---|---|---|---|
clean |
clean |
Removes the theme related static files in the pub/static and var directories. | This will remove all files related to the themes and is not useful on it's own |
exec |
exec ,exec:<theme_name> |
Republishes symlinks to the source files to the pub/static/frontend/ directory. Use grunt exec: |
This will create the symlinks required for less compilation to work, if you have created a new LESS file you will need to re-run this or it will not be compiled. Extra files such as fonts and images will not be published. |
less |
less ,less:<theme_name> |
Compiles CSS files using the symlinks published in the pub/static/frontend/ directory. Use grunt less: |
Performs a single LESS compilation |
watch |
watch ,watch:<theme_name> |
Tracks the changes in the source files, recompiles .css files, and reloads the page in the browser. | When first run, it does not compile CSS until a change is detected. Browsers will not update automatically if you use a container for development such as LXC or Docker |
refresh |
refresh ,refresh:<theme_name> |
Is a combination of clean and exec , this will ensure your symlinks are present for LESS compilation. |
It is important to note that when you republish your theme symlinks that you will be missing fonts, images and other assets required for your theme.
To get around this, static-content
deploy can be used with some extra flags to ensure the content is available.
The following is a simple bash script that can be used instead of exec
and refresh
when developing your theme.
grunt refresh:mytheme;
php bin/magento setup:static-content:deploy --no-less --no-css -j 4 en_GB en_US -a frontend;
php bin/magento setup:static-content:deploy -a adminhtml en_GB en_US
Importing Partial LESS files¶
You must use the full file name when using LESS imports - or Grunt will not work when watching
// Won't work - symlinks will be broken in development with grunt refresh/watch
@import "partials/abc";
// Works - full file name in place
@import "partials/abc.less";
This snippet will run the refresh command for mytheme
and then re-deploy static content for non CSS/LESS changes.
All fonts, images or other assets should then remain and be visible when developing the theme.
Browser Sync¶
Browser sync allows you to work with Magento 2 styling more efficiently by removing the need for a page refresh.
Install dependencies¶
sudo bash
npm install -g browser-sync
Run Browsersync¶
Here is a one liner you can use to get Browsersync working, replace the proxy with your hostname for your Magento 2 development instance along with the theme and locale accordingly
(cd pub/static/frontend/<ThemeVendor>/<ThemeName>/<Locale>/css; browser-sync start --proxy 'www.magento2.local' --files="*.css" --https)
The --https
flag is optional, it is recommend to develop with HTTPS if possible.
You will still need to use a separate terminal to start your LESS watcher (refresh script).
Once browsersync is running, you should see some output like the following:
[Browsersync] Proxying: http://www.magento2.local
[Browsersync] Access URLs:
-----------------------------------------
Local: https://localhost:3000
External: https://192.168.122.106:3000
-----------------------------------------
UI: http://localhost:3001
UI External: http://localhost:3001
-----------------------------------------
If you are running Browsersync inside a container like LXC, you will need to use the External
IP address and port to
access it.
Note
You will also need to add your hostname to the containers hosts file
Use this with your browser and CSS changes will come through automatically.
Common Rules¶
As mentioned before, Magento 2 splits all rules between a large and mobile stylesheet (styles-m and styles-l). The large stylesheet is only loaded by the Browser if the device being used meets the minimum horizontal resolution.
When writing rules, it is important to try and distinguish which rules can be applied to both mobile and large devices. This is important because we can optimise the LESS compilation to only include the styles necessary for mobile devices and leave the remaining rules in the large spreadsheet. This reduces the download size of the mobile spreadsheet to only include the required styles and as a result - improves download time of the stylesheet and rendering time.
When rules can be applied to both types of devices, you need to wrap the rules with media-common
.
& when (@media-common = true)
{
// Rules that are shared (common) between mobile and desktop
// ...
}
This forces the rules inside the statement to only be placed in styles-m
which will be loaded by both desktop and mobile.
Media Query Breakpoints¶
Breakpoints (media queries) are used in CSS to declare styling rules that are specific to different devices or contexts. For example to target mobile, tablet and desktop devices independently.
Magento 2 expands upon this by placing the contents of media queries into either the styles-m
or styles-l
stylesheets
depending on their conditions.
For examples, rules declared to only apply to screen widges in excess of 768px
will be places in styles-l
and not styles-m
.
This is done by the use of Mixin Guards.
To use Magento's breakpoint system you need to use the .media-width
mixin.
//
// Medium Desktop
// _____________________________________________
.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
// Rules specific to devices larger than 768px horizontally will apply from here
}
The @extremum
parameter is either min
or max
strings followed by the desired targeted breakpoint @break
.
When specifying the breakpoint, it is important to only use the predefined breakpoints. The breakpoints are defined in lib/web/css/source/lib/variables/_responsive.less
Note that this is a core file and should not be edited and it is also strongly discouraged to override the breakpoints unless absolutely necessary.
Any changes to the LESS files within lib
are liable to be overwritten when Magento is updated to a newer version.