CSS Media queries in Magento 2

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!

Related Inchoo Services

You made it all the way down here so you must have enjoyed this post! You may also like:

Moving the validation error message, this time globally Danijel Vrgoc
, | 0

Moving the validation error message, this time globally

Behind the scenes with one Magento PWA Studio contributor Aron Stanic
Aron Stanic, | 3

Behind the scenes with one Magento PWA Studio contributor

Customising product info tabs in Magento 2 (part 2) Igor Tikvic
, | 2

Customising product info tabs in Magento 2 (part 2)

12 comments

  1. There’s a typo in your helper:

    .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {} <== missing brace
  2. *
    // 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

  3. 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.

  4. Please note that less won’t compile properly unless you rename the variables.less file to _variables.less.

  5. 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 :/

  6. 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.

  7. 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.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <blockquote cite=""> <code> <del datetime=""> <em> <s> <strike> <strong>. You may use following syntax for source code: <pre><code>$current = "Inchoo";</code></pre>.

Tell us about your project

Drop us a line. We'd love to know more about your project.