Magento 2 – Fix .media-width() LESS Mixin Issue

lessmagento2mixins

I'm trying to use Magento2's .media-width() mixin. I followed the instructions from the devdocs and added the mixin in my theme like this:

.logo img {
  width: 125px;
  height: 29px;
  .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
    width: 250px;
    height: 58px;
  }
}

Only the CSS outside of the .media-width() is being generated. Nothing within it is being generated. Am I missing something.

UPDATE

Following the advice of @circlesix I did not nest the media query, but still I'm having some trouble.

.logo img {
  width: 125px;
  height: 29px;
}
.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
  .logo img {
    width: 177px;
    height: 41px;
  }
}

My desktop rule in the media query is being overruled by the first rule for .logo img as it is defined later in styles-l.css.
enter image description here

Interestingly I don't see the rule I defined within the media-width() mixin defined anywhere within styles-m.css. So perhaps I need to use the media-width() for both desktop & mobile views and only define common properties outside of it?

Best Answer

Ok, so I discovered a little more about this but as @circlesix pointed out it's not possible to use these LESS mixins nested like this.

Furthermore if you look at the <head> section of Magento you'll notice that the styles-l.css is loaded after the mobile styles, i.e. styles-m.css.

<link  rel="stylesheet" type="text/css"  media="all" href="http://example.com/pub/static/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/pub/static/frontend/Magento/luma/en_US/css/styles-l.css" />

So styles-l.css is only loaded on screens 768px and over in width, saving mobile devices from having to load it.

If you write a LESS rule like normal without any of the mixins it will be put into both of these files and anything you add to with the media-width() mixin will be added before it, and therefore overwritten.

You can use the @media-common = true separation variable to output it only to styles-m.css before any of the media query rules are added. This way it will be applied to both desktop and mobile devices, as both load styles-m.css.

media-width() mixins under 768px are only put in styles-m.css, vice-a-versa any media-width() mixins 768px over in width is only put in styles-l.css.

So, I think the best practice is to put all your common styles within & when (@media-common = true) {} and use the media-width() mixin for any css rules which are specific to a particular width.

For instance, below is what I went with in the end...

//
//  Common
//  _____________________________________________
& when (@media-common = true) {
  .logo img {
    width: 125px;
    height: 29px;
  }
}

//
//  Mobile
//  _____________________________________________
//.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) {}

//
//  Desktop
//  _____________________________________________
.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
  .logo img {
    width: 177px;
    height: 41px;
  }
}

It's the same approach used by Magento in:

  • app/design/frontend/Magento/blank/web/css/source/_navigation.less
  • vendor/magento/theme-frontend-blank/web/css/source/_navigation.less
Related Topic