Skip to main content
Added update with illustration of a cause of the problem.
Source Link
ryanF
  • 2.3k
  • 1
  • 20
  • 31

The way that I've gotten around this is to use a Less reference import Less Docs: reference import option[Less Docs: reference import option][1], which will not pull in the code within said Less file, it will just make the files available within the scope of the file requesting the import.

Now, with all of that said here's the kicker, you don't really need to do this. Why? Well, aren't the css styles within the CSS Guards[CSS Guards][2], in this case @media-common = true only meant to be called with the styles-m.less file? Yes, because M2 is supposed to be mobile first and therefore the styles-m.less file is the only file (save some email Less files and I think a few others) that actually has @media-common set to true (and there are only handful of files that even set this variable, period).

So anything that is within a CSS Guard which has the condition of @media-common = true is meant to be ran always, except for when the styles-l.less file is called. styles-l.less sets @media-common to false as the styles-m.less file should have already loaded up these 'common' styles...and if you look in vendor/magento/theme-frontend-blank/Magento_Theme/layout/default_head_blocks.xml you'll see that styles-m.css (which gets generated from styles-m.less if it isn't already generated [Dev Docs: Dev Docs: .css request to .less search.css request to -.less search][3] More Here- [More][4] [Here][5]) gets loaded before styles-l.css.

If you or anyone else comes up with a better solution, I'm all ears.

UPDATE So disregard what I mentioned above regarding code duplication. In my case I was both adding an explicit inclusion of my custom css in a page and I also added my custom less file to my theme's _extend.less.

I was modifying app/design/frontend/<Vendor>/<theme>/Magento_Cms/layout/cms_index_index.xml to include the following:

    <head>
        <!-- ADD PAGE-SPECIFIC STYLES SHEETS HERE -->
        <css src="css/pages/homepage.css" />
    </head>

and I also had an entry in app/design/frontend/<Vendor>/<theme>/web/css/source/_extend.less of:

@import "../pages/homepage.less";

What I've found is that it's either or, not both. So in this case when M2 was trying to process a request for http://vappey.dev/static/frontend/<Vendor>/<theme>/<locale>/css/pages/homepage.css it would load up the appropriate homepage.less file and this file wouldn't have @media-common within it's scope, so the error was telling. In order to get around that, add import references as I've mentioned above and they won't be any code duplication. Furthermore, but removing the entry from _extend.less my styles-m.less and styles-l.less won't look for the homepage.less file and there's no code duplication.

The way that I've gotten around this is to use a Less reference import Less Docs: reference import option, which will not pull in the code within said Less file, it will just make the files available within the scope of the file requesting the import.

Now, with all of that said here's the kicker, you don't really need to do this. Why? Well, aren't the css styles within the CSS Guards, in this case @media-common = true only meant to be called with the styles-m.less file? Yes, because M2 is supposed to be mobile first and therefore the styles-m.less file is the only file (save some email Less files and I think a few others) that actually has @media-common set to true (and there are only handful of files that even set this variable, period).

So anything that is within a CSS Guard which has the condition of @media-common = true is meant to be ran always, except for when the styles-l.less file is called. styles-l.less sets @media-common to false as the styles-m.less file should have already loaded up these 'common' styles...and if you look in vendor/magento/theme-frontend-blank/Magento_Theme/layout/default_head_blocks.xml you'll see that styles-m.css (which gets generated from styles-m.less if it isn't already generated Dev Docs: .css request to .less search - More Here) gets loaded before styles-l.css.

If you or anyone else comes up with a better solution, I'm all ears.

The way that I've gotten around this is to use a Less reference import [Less Docs: reference import option][1], which will not pull in the code within said Less file, it will just make the files available within the scope of the file requesting the import.

Now, with all of that said here's the kicker, you don't really need to do this. Why? Well, aren't the css styles within the [CSS Guards][2], in this case @media-common = true only meant to be called with the styles-m.less file? Yes, because M2 is supposed to be mobile first and therefore the styles-m.less file is the only file (save some email Less files and I think a few others) that actually has @media-common set to true (and there are only handful of files that even set this variable, period).

So anything that is within a CSS Guard which has the condition of @media-common = true is meant to be ran always, except for when the styles-l.less file is called. styles-l.less sets @media-common to false as the styles-m.less file should have already loaded up these 'common' styles...and if you look in vendor/magento/theme-frontend-blank/Magento_Theme/layout/default_head_blocks.xml you'll see that styles-m.css (which gets generated from styles-m.less if it isn't already generated [Dev Docs: .css request to .less search][3] - [More][4] [Here][5]) gets loaded before styles-l.css.

If you or anyone else comes up with a better solution, I'm all ears.

UPDATE So disregard what I mentioned above regarding code duplication. In my case I was both adding an explicit inclusion of my custom css in a page and I also added my custom less file to my theme's _extend.less.

I was modifying app/design/frontend/<Vendor>/<theme>/Magento_Cms/layout/cms_index_index.xml to include the following:

    <head>
        <!-- ADD PAGE-SPECIFIC STYLES SHEETS HERE -->
        <css src="css/pages/homepage.css" />
    </head>

and I also had an entry in app/design/frontend/<Vendor>/<theme>/web/css/source/_extend.less of:

@import "../pages/homepage.less";

What I've found is that it's either or, not both. So in this case when M2 was trying to process a request for http://vappey.dev/static/frontend/<Vendor>/<theme>/<locale>/css/pages/homepage.css it would load up the appropriate homepage.less file and this file wouldn't have @media-common within it's scope, so the error was telling. In order to get around that, add import references as I've mentioned above and they won't be any code duplication. Furthermore, but removing the entry from _extend.less my styles-m.less and styles-l.less won't look for the homepage.less file and there's no code duplication.

Source Link
ryanF
  • 2.3k
  • 1
  • 20
  • 31

@fefe The @media-common variable is initially set in either:

  • vendor/magento/theme-frontend-blank/web/css/styles-m.less

  • vendor/magento/theme-frontend-blank/web/css/styles-l.less

This is if you're using either the blank or luma theme as a parent. If so, then this applies to you. If not, then whatever your parent theme is, should have a declaration and initialization of this variable...or if the parent theme you're using calls another for it's parent, the same applies.

Take a look at the styles-m.less and styles-l.less files to see the order in which less files are imported. You can also add some form of logging at \Less_Parser::parseFile().

The way that I've gotten around this is to use a Less reference import Less Docs: reference import option, which will not pull in the code within said Less file, it will just make the files available within the scope of the file requesting the import.

An example of what I've imported at the top of a custom Less file:

@import (reference) "../source/lib/variables/_responsive.less"; @import (reference) "../source/lib/_responsive.less";

*Note the path I'm using here in relative to my custom theme's custom Less file path in relation to the eventual var/view_preprocessed/css/frontend/<Vendor>/<theme>/<locale>/css/ path.

My custom theme directory hierarchy looks like this: app/design/frontend/<Vendor>/<theme>/web/css/custom/custom.less.

The files that I want to import are here:

  • var/view_preprocessed/css/frontend/<Vendor>/<theme>/<locale>/css/source/lib/_responsive.less

  • var/view_preprocessed/css/frontend/<Vendor>/<theme>/<locale>/css/source/lib/variables/_responsive.less

My custom file, which will be doing the import, will eventually live here:

  • var/view_preprocessed/css/frontend/<Vendor>/<theme>/<locale>/css/custom/custom.less

Now, with all of that said here's the kicker, you don't really need to do this. Why? Well, aren't the css styles within the CSS Guards, in this case @media-common = true only meant to be called with the styles-m.less file? Yes, because M2 is supposed to be mobile first and therefore the styles-m.less file is the only file (save some email Less files and I think a few others) that actually has @media-common set to true (and there are only handful of files that even set this variable, period).

So anything that is within a CSS Guard which has the condition of @media-common = true is meant to be ran always, except for when the styles-l.less file is called. styles-l.less sets @media-common to false as the styles-m.less file should have already loaded up these 'common' styles...and if you look in vendor/magento/theme-frontend-blank/Magento_Theme/layout/default_head_blocks.xml you'll see that styles-m.css (which gets generated from styles-m.less if it isn't already generated Dev Docs: .css request to .less search - More Here) gets loaded before styles-l.css.

This means that you could literally get around that error by defining @media-common: true; at the top of your custom Less file and based on what I've described above and what I'm understanding of the code so far, that should take care of the error.

Here's the problem: Whether you're including the source/lib/_responsive.less & source/lib/variables/_responsive.less files or defining your own @media-common: true; at the top of your custom file, this will overwrite the @media-common: false; assignment in styles-l.less, so you're going to get code duplication in both styles-m.less and styles-l.less. I don't see any way around that at the moment. The root issue of this is that our custom Less files aren't being loaded after both styles-m.less and styles-l.less or that the @media-common variable's value isn't being brought into the scope of our custom Less files. This shouldn't be the case, if we're importing our custom less via the _extend.less file, which the docs (suggest), as you have the following at the end of both styles-m.less and styles-l.less:

//@magento_import 'source/_extend.less';

I hope this has given you both insight and an immediate solution to your problem.

If you or anyone else comes up with a better solution, I'm all ears.