I have to run grunt exec
before grunt watch
will read my changes correctly. As of how my system is set up, the common styles get complied down to the styles-m.css
file that get generated to the
<site-root>/pub/static/frontend/<vender-namespace>/<theme-name>/en_US/css/styles-m.css
And this follows the magento claim for a mobile first design, any styles in the .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {}
media query will not load in this file, reducing the weight of the total css files.
This page talks about it some more: Magento 2 Docs
And some examples: Magento 2 UI Library
You are correct that when you place any styles in:
//
// Desktop
//--------------------------------------
.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {}
They will only be included in the styles-l.css
file and not in the styles-m.css
. But all styles will be compiled to the styles-l.css
file and only styles not wrapped in that line of code will show up in the mobile styles sheet. The idea being that if you have styles that don't exist on a mobile device, there is no reason to have the extra code weight in that file.
To make things easy for my work flow, i have three media queries in every .less file:
//
// Common
//--------------------------------------
& when (@media-common = true) {}
This is for styles that are used in both mobile and desktop views
//
// Desktop
//--------------------------------------
.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {}
This is for styles that will only be included in the styles-l.css
file.
//
// Mobile
// _____________________________________________
.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) {}
And this is for all mobile styles.
All my code is wrapped in one of these three, and this way i have a clear separation between that different breakpoints and sheet.
Best Answer
@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
andstyles-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 thestyles-m.less
file? Yes, because M2 is supposed to be mobile first and therefore thestyles-m.less
file is the only file (save some email Less files and I think a few others) that actually has@media-common
set totrue
(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 thestyles-l.less
file is called.styles-l.less
sets@media-common
tofalse
as thestyles-m.less
file should have already loaded up these 'common' styles...and if you look invendor/magento/theme-frontend-blank/Magento_Theme/layout/default_head_blocks.xml
you'll see thatstyles-m.css
(which gets generated fromstyles-m.less
if it isn't already generated Dev Docs: .css request to .less search - More Here) gets loaded beforestyles-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 instyles-l.less
, so you're going to get code duplication in bothstyles-m.less
andstyles-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 bothstyles-m.less
andstyles-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 bothstyles-m.less
andstyles-l.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.
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 appropriatehomepage.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
mystyles-m.less
andstyles-l.less
won't look for thehomepage.less
file and there's no code duplication.