<parent>Magento/luma</parent>When using media queries inside _extend.less:
// normal
.logo {
border-bottom: 4px solid #cccccc; // should be overwritten with media queries styles
}
& when (@media-common = true) {
.logo {
border: 1px solid #cccccc; // should be overwritten with media queries styles
.lib-css(background, @link__color);
}
}
// mobile media query
.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) {
.logo {
border: 1px solid #ff00ff;
}
}
// tablet media query
.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
.logo {
border: 1px solid #ff0000;
}
}
Inside styles-m.less and styles-l.less you need to put //@magento_import 'source/_extend.less'; before @import 'source/lib/_responsive.less';
//
// Extend for minor customisation
// ---------------------------------------------
//@magento_import 'source/_extend.less';
//
// Media queries collector
// ---------------------------------------------
@import 'source/lib/_responsive.less';
Another fix to extend magento2 less styles with available mixins and variables, with the right specificity of the media queries:
You have to copy the blank theme's source/_sources.less inside custom/web/css/source/_sources.less, and add an import to your custom _custom.less here.
// /**
// * Copyright 漏 2013-2017 Magento, Inc. All rights reserved.
// * See COPYING.txt for license details.
// */
@import '_variables.less';
@import (reference) '_extends.less';
@import '_typography.less';
@import '_layout.less';
@import '_tables.less';
@import '_messages.less';
@import '_navigation.less';
@import '_tooltips.less';
@import '_loaders.less';
@import '_forms.less';
@import '_icons.less';
@import '_buttons.less';
@import '_sections.less';
@import '_pages.less'; // Theme pager
@import '_actions-toolbar.less';
@import '_breadcrumbs.less';
@import '_popups.less';
@import '_price.less';
// custom
@import '../_custom.less';
Inside _custom.less you can access all variables and mixins.
// normal
.logo {
border-bottom: 4px solid #cccccc; // should be overwritten with media queries styles
}
& when (@media-common = true) {
.logo {
border: 1px solid #cccccc; // should be overwritten with media queries styles
.lib-css(background, @link__color);
}
}
// mobile media query
.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) {
.logo {
border: 1px solid #ff00ff;
}
}
// tablet media query
.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
.logo {
border: 1px solid #ff0000;
}
}
In the above code the styles specificity is respected because the '// normal' code appears above the media queries inside styles-m.css.
Described behavior is not a bug but expected behavior. _extend.less should be able to override all other styles so it is placed at the bottom of the styles-m.less and styles-l.less.
It's a bad expected behaviour because it's not for sure if the user want to override also the media queries code with a code "// normal" or "@media-common = true".
With the solution above it should override the media queries code if they use also media queries inside _extend.less, which is another perspective on which is a expected behaviour.
You should respect css specificity, but it's broken using your media queries mixins. Those media queries mixins also can't be used inside nested css selectors, and make the less code much more scattered and complicated, only to save some kb on mobile separating the styles-l.css.
I think responsive media queries should be revisited, they are the problem, they should work inside nested selectors and they should respect css specificity. With only one styles.css compiled.
With something like this:
// min-width
// USAGE: @media @min-sm {}
@query-min-xs: 480px; // Extra small query
@query-min-sm: 768px; // Small query
@query-min-md: 992px; // Medium query
@query-min-lg: 1200px; // Large query
@query-min-xl: 1450px; // Extra Large query
@min-xs: ~"(min-width: @{query-min-xs})";
@min-sm: ~"(min-width: @{query-min-sm})";
@min-md: ~"(min-width: @{query-min-md})";
@min-lg: ~"(min-width: @{query-min-lg})";
@min-xl: ~"(min-width: @{query-min-xl})";
// max-width
// USAGE: @media @max-sm {}
@query-max-xs: 479px; // Extra small query
@query-max-sm: 767px; // Small query
@query-max-md: 991px; // Medium query
@query-max-lg: 1199px; // Large query
@query-max-xl: 1449px; // Extra Large query
@max-xs: ~"(max-width: @{query-max-xs})";
@max-sm: ~"(max-width: @{query-max-sm})";
@max-md: ~"(max-width: @{query-max-md})";
@max-lg: ~"(max-width: @{query-max-lg})";
@max-xl: ~"(max-width: @{query-max-xl})";
I agree with @minimit , the responsive mixin generates wrong order of media queries in "styles-ml.css" file for 'max @screen__xxs', 'max @screen__xs', 'max @screen__s', and 'max @screen__m' cases.
I have tested this .less code.
.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__xxs) {
.logo-text { background-color: blue; }
}
.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__xs) {
.logo-text { background-color: green; }
}
.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) {
.logo-text { background-color: darkred; }
}
.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) {
.logo-text { background-color: darkblue; }
}
.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
.logo-text { background-color: purple; }
}
.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__l) {
.logo-text { background-color: cyan; }
}
.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__xl) {
.logo-text { background-color: lightpink; }
}
Because the generated media query for 'max @screen__m' is placed later than the other media queries, it is overriding rules for 'xxs', 'xs', and 's'.
The result of this code is: the .logo-text background is ALWAYS darkblue for screen size 767px (@screen__m - 1) and under.
I am tempted to change the order of codes on
lib/web/css/source/lib/_responsive.less
to look like this:
//
// Style groups for 'mobile' devices
// ---------------------------------------------
& when (@media-target = 'mobile'), (@media-target = 'all') {
@media only screen and (max-width: @screen__m) {
.media-width('max', (@screen__m + 1));
}
@media only screen and (max-width: (@screen__m - 1)) {
.media-width('max', @screen__m);
}
@media only screen and (max-width: (@screen__s - 1)) {
.media-width('max', @screen__s);
}
@media only screen and (max-width: (@screen__xs - 1)) {
.media-width('max', @screen__xs);
}
@media only screen and (max-width: (@screen__xxs - 1)) {
.media-width('max', @screen__xxs);
}
@media all and (min-width: @screen__s) {
.media-width('min', @screen__s);
}
}
But, I will not change it because the impact will be too big for me to debug. The file is a part of the foundation of the whole .less system of M2.
I hope the team will find a solution to this issue.
Until then, I will workaround by using the (dreadful) !important and adding more classes to increase specificity.
What @minimit wrote is true. I've reproduced this on Magento 2.2.0 as well.
It's annoing you have to override (with !important) your own styles to get them applied on higher screen resolution.
@vkublytskyi we need to rethink this expected behaviour to avoid users having to use the ugly !important in their styles or find any other workarounds.
I'll give you another example I have tried and got into same issue.
I'm not trying to override any existing styles from theme or any other module. Complete new styles for custom stuff. I'm adding my styles in the _theme.less file.
The styles order is the same as @minimit described to reproduce.
& when (@media-common = true) {
.my-very-new-class {
border: 1px solid #cccccc; // should be overwritten with media queries styles
}
}
// mobile media query
.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) {
.my-very-new-class {
border: 1px solid #ff00ff;
}
}
// tablet media query
.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
.my-very-new-class {
border: 1px solid #ff0000;
}
}
As a result I have to use the !important, otherwise I'll have the gray color everywhere.
Why should I do so ? I shouldn't.
So even keeping in mind backward compatibility we definitely should do something on this matter, @vkublytskyi.
Let's make the work with magento 2 a breeze not a steeplechase.
What happened with this? Still seems to be the case in Magento 2.2.3 but the issue has been closed with no explanation ?
Hi @minimit the fix for this this issue, has already available in 2.2-develop branch.
@engcom-backlog-nazar hi. Can you give a link to the fix please?
I agree with this issue, as it has caused headache many times.
I think it can be fixed while still allowing _extend.less to be the last file included to override other styles, if we simply use a mixin for common styles instead of a variable. This way, the mixin can be called explicitly in the correct place in _responsive.less, to ensure that all common styles are output before all media queries:
& when(@media-common = true) to .media-common()@media-common definitions in _responsive.less (line 14) & styles-l.less (line 33).media-common(); in _responsive.less, inside mobile/all section (line 29)(I believe that the only breaking change or backwards incompatibility this would cause is the need to update custom files according to step 1, which should be quite easy and could be listed in breaking changes for the release.)
Most helpful comment
I agree with this issue, as it has caused headache many times.
I think it can be fixed while still allowing _extend.less to be the last file included to override other styles, if we simply use a mixin for common styles instead of a variable. This way, the mixin can be called explicitly in the correct place in _responsive.less, to ensure that all common styles are output before all media queries:
& when(@media-common = true)to.media-common()@media-commondefinitions in _responsive.less (line 14) & styles-l.less (line 33).media-common();in _responsive.less, inside mobile/all section (line 29)(I believe that the only breaking change or backwards incompatibility this would cause is the need to update custom files according to step 1, which should be quite easy and could be listed in breaking changes for the release.)