CSS Media queries in Magento 2

It’s highly unlikely that there are some frontend developers involved in a responsive website development who are not familiar with the concept of CSS Media queries. In this post, I’ll be looking at Magento 2 way of implementing this functionality in its default theme development workflow.
How do Magento 2 media queries work?
In the heart of Magento 2 media queries mechanism, defined in Magento UI library, is a .media-width() mixin.
.media-width(<@extremum>, <@break>);
@extremum: max|min – sets whether to use min-width or max-width in media query condition
@break: value – sets the value of breakpoint to compare with in media query condition
We can see the practical use of it in the following example:
// In .less file
.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) {
your styles
}
// After compilation, in .css file
@media only screen and (max-width: 640px) {
your styles
}
This mixin, which is used for grouping style rules in certain media queries, can be used whenever you need it, in any .less file in your theme. In the end, it will be invoked only once – in lib/web/css/source/lib/_responsive.less file.
If you check the end product of .less files compilation, styles.css file, you’ll see there each media query with all its rules only once, so there are no a multiple calls for the same query.
Default settings
By default, media queries are outputting styles in two different files:
1. styles-m.less – which generates basic and mobile-specific styles
2. styles-l.less – generates desktop-specific styles (for 768px width screen and higher)
This means that, when the website is opened on a mobile device, it will load only styles compiled from the styles-m.less file. Extra styles from the second file (styles-l.less) are compiling and loading only if the screen width is 768px or higher.
For this style groups separation, special variables @media-target and @media-common are used:
// For targetting device for styles output
@media-target: all|desktop|mobile
// In practice
& when (@media-target = 'mobile'), (@media-target = 'all') {
@media only screen and (max-width: (@screen__xs - 1)) {
.media-width('max', @screen__xs);
}
}
// For deciding whether to output common styles.
@media-common: true|false
// Adding common styles
& when (@media-common = true) {
your styles
}
Out of the box, Magento UI library has a set of predefined variables for breakpoints. We can use them in any case we need them and they can be changed or extended them with a new ones:
- 320px
- 480px
- 640px
- 768px (breakpoint for switching between mobile and desktop views)
- 1024px
- 1440px
Custom breakpoints
Quite often, we’ll find ourselves in a situation where we’ll need to add an additional breakpoint (apart from default ones) in which we can apply a different styling. There are three things which need to be done in order to add a custom breakpoint in our theme.
1. Define a variable for the new breakpoint.
First, we’ll have to create a /web/css/source/variables.less file
. If we would use a standalone theme, this file would be new and empty. But, since we’re following the best practice (inheriting from Magento Blank theme), we’ll have to copy this file from our parent theme.
Here we can define our custom breakpoint:
@custom__breakpoint: 1280px;
2. Implement our new breakpoint
To do so, we’ll override _responsive.less file from Magento UI library by copying it to our theme in /web/css/source/lib/
. Now, in our theme’s _responsive.less file we have to edit .media-width() mixin by adding the appropriate rule for the new custom breakpoint.
& when (@media-target = 'desktop'), (@media-target = 'all') {
@media all and (min-width: @custom__breakpoint) {
.media-width('min', @custom__breakpoint);
}
}
3. Implement the screen changes for the new breakpoint.
If everything is set properly, we should be able call our new .media-width() mixin whenever we need it in our theme .less files.
.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @custom__breakpoint) {
// Stlying applied at @custom__breakpoint breakpoint
}
A small helper
In the end, to wrap things up, I’ll give you some quick jump-start piece of code; media queries which you can quickly apply, depending on which screen size you’d like to target.
// Common
// (for styles used in both mobile and desktop views)
& when (@media-common = true) {}
// Mobile
// (for all mobile styles.)
.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) {}
// Tablet
.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
// Desktop
.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__l) {}
Thank you for reading!
12 comments
Mobile menu breakpoint in Magento 2
There’s a typo in your helper:
How is the @media-target even defined?
*
// For deciding whether to output common styles.
@media-common: true|false
*
Please, you cannot change this variable…Never change the variable. Only read in condition.
Magento add this variable automatically when compiling style-l.css and style-m.css
In the heart of Magento 2 media queries mechanism, defined in Magento UI library, is a .media-width() mixin.
The link you have linked has an extra forward slash that breaks it.
It should had been
https://devdocs.magento.com/guides/v2.0/frontend-dev-guide/css-topics/theme-ui-lib.html
Aside this, thank you for the helpful article!
After compilation all styles paced in & when (@media-common = true) {} appears below the
.media-width() styles, which mean it has highest priority.
Is it default magento behavior? or smth broken in my custom theme? can’t find the answer on the magento developer guide.
Please note that less won’t compile properly unless you rename the variables.less file to _variables.less.
Thank You Goran.
Very useful. Still I have some problems with this. I was trying to change header.panel class, but it was only possible from Magento-theme/web/source/_extended.less instead from web/source/_extended.less
Now I’m fighting with .logo :/
Thank you for writing this guide.
Could you please elaborate more on how to incorporate this into modifying existing style showing samples of good practices.
I already extended Luma theme and edited my theme. But I would like to edit some styles for mobile. Should I just go ahead and write my code in _extend.less or topmenu_extend.less (the two files I used to modify luma theme)?
Appreciated.
Hi,
I am new to Magento 2.
I am developing one theme for Magento 2, but some how I am not able to make it responsive design.
I follow above instruction for responsive.
Can you please help me.
It so useful for beginners (like me) who want to understand how can we build a responsive theme in Magento 2. Thanks a lot.
very useful
thanks for sharing that