How to Get a SASS Nested Nested Media Query to Work with the Use of the Media Query or Operator

How to get a SASS nested nested media query to work with the use of the media query or operator

This appears to be a hyper-specific case that appears is part misbehavior in Sass and part ambiguous expectations.

Sass handles nesting combined with comma delimited media queries without problems... until you start specifying a display type on both the inner and outer query:

/* without `screen` */
.foo {
@media (min-width: 20em) {
color: yellow;

@media all and (max-width: 40em), (orientation: portrait) {
color: green;
}
}
}

/* without `only` */
.bar {
@media screen and (min-width: 20em) {
color: yellow;

@media all and (max-width: 40em), (orientation: portrait) {
color: green;
}
}
}

/* with `only screen` */
.buzz {
@media only screen and (min-width: 20em) {
color: red;

@media all and (max-width: 40em) {
color: blue;
}
}
}

Output:

/* without `screen` */
@media (min-width: 20em) {
.foo {
color: yellow;
}
}
@media all and (min-width: 20em) and (max-width: 40em), (min-width: 20em) and (orientation: portrait) {
.foo {
color: green;
}
}

/* without `only` */
@media screen and (min-width: 20em) {
.bar {
color: yellow;
}
}
@media screen and (min-width: 20em) and (orientation: portrait) {
.bar {
color: green;
}
}

/* with `only screen` */
@media only screen and (min-width: 20em) {
.buzz {
color: red;
}
}

In both cases where both the inner and outer query contains a display type (all, screen), the compiled results do not correctly match what was written. This appears to be a case of Sass trying to write something that resembles a valid media query (since it knows that screen and all is not valid).

So only specify the display type once.

.element {
@media (min-width: 825px) and (max-width: 999px) {
font-size: 10.4vw;

@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
font-size: 9.6vw;
}
}
}

Compiles to:

@media (min-width: 825px) and (max-width: 999px) {
.element {
font-size: 10.4vw;
}
}
@media all and (min-width: 825px) and (max-width: 999px) and (-ms-high-contrast: none), (min-width: 825px) and (max-width: 999px) and (-ms-high-contrast: active) {
.element {
font-size: 9.6vw;
}
}

Nesting Media Queries

No. You need to use the and operator and write that as two queries. You can, however, do this in SCSS, which will compile to CSS, but it will combine them by unfolding them and using the and operator.

This is a common problem, and once I first wrote LESS or SCSS, I didn't ever want to go back to writing this long-hand.

Long-handed CSS:

@media (-webkit-min-device-pixel-ratio: 2) and (max-width: 768px) and (min-width: 320px),
(min-resolution: 192dpi) and (max-width: 768px) and (min-width: 320px) {
body {
border: 1px solid red;
}
}
@media (-webkit-min-device-pixel-ratio: 2) and (max-width: 320px),
(min-resolution: 192dpi) and (max-width: 320px) {
body {
border: 1px solid blue;
}
}

Nesting queries may work, but support varies across browsers.

How to target two media queries using SASS interpolation?

This won't give you CSS error but is slightly different from what you need:

@media #{$mobile}, #{$tablet} {
/* my styles for mobile and tablet displays */
}

From MDN docs:

Comma-separated lists behave like the logical operator or when used in
media queries. When using a comma-separated list of media queries, if
any of the media queries returns true, the styles or style sheets get
applied. Each media query in a comma-separated list is treated as an
individual query, and any operator applied to one media query does not
affect the others. This means the comma-separated media queries can
target different media features, types, and states.

The thing is that concat that you are making with string interpolation isn't
compiled to valid CSS. Read more about media query logic here.

Media Query scss breakpoints best practice

I think this is a great question and I often feel like the divide is caused by old school coders who are used to life before SASS and refuse to move into the new age of SASS and nested CSS.

Method 1

Pros

You can put every media query for a break point into a single place so
it's easier to find an diagnose when you want to make multiple changes
to a page template.

Cons

It's messy and you end up with multiple class declarations all over
the place, so when it comes to editing one element or adding a new
element into the HTML you end up having to edit CSS across multiple
areas which is harder to track.

It involves a hell of a lot of scrolling up and down to find the media
query in question and then edit that single class element.

Method 2

Pros

Everything is kept together in one place, it's easy to see to find a
class and edit all of the breakpoints that are used in it.

It's also possible to quickly add new breakpoints to apply quick fixes

It's also easier to read and understand at a quick glance.

Cons

Old school developers may not like it!!

Sometimes it's not good. If you have a fixed template and you know
it's not going to change. Putting the entire CSS for the whole page or
area makes it a lot easier to work with. You can edit multiple classes
for a single breakpoint all in one place.

Conclusion

It depends on the situation. I don't think that it's a my way or the highway type of scenario, its a mixture of both.

When building components you often want to keep the CSS in one block like in Method 1. But when you're diagnosing a whole site that's been put together and are inserting single breakpoints for specific elements, it starts to make more sense using Method 2.

I've found that the more sites we create the more I've become adept at figuring out what method is best for that situation and the rules above tend to guide me in the right direction.

Media queries in Sass

$small: 300px;
$medium: 900px;

.smth {
//some CSS
@media screen and (max-width: $small) {
//do Smth
}
@media screen and (min-width: $medium) {
//do Smth
}
}

Something like this?

Nesting @media rules in element

I think that it depends on the amount of the code you are going to write. It works without any problem, but hundreds of different media queries nested in each class could be hard to maintain. In my opinion a good practice, especially for big projects, would be to use separate files for each media query threshold, in order to keep your CSS organized as much as possible.
For example:

style.less

.class1 {
width: 100%;
}

.class2 {
color: #000;
}

@media screen and (min-width: 740px) {
@import "min740.less";
}

min740.less

.class1 {
width: 50%;
}

.class2 {
color: #faa;
}

If you are going to write separate components, like buttons or typographies, you can keep all the related media queries in the same file, in order to have a completely separate CSS module (your 2nd example basically).

In terms of speed and performances, obviously is always recommended to use compiled LESS in production, but considering your examples, the single media query selector would be more efficient, since in the "example1 way" the media query selector will be replicated multiple times:

.class1 {
width: 100%;
}
@media screen and (min-width: 740px) {
.class1 {
width: 50%;
}
}
.class2 {
width: 100%;
}
@media screen and (min-width: 740px) {
.class2 {
width: 50%;
}
}

Using media queries, following standards with SASS and BEM?

I prefer the 2nd variant for the following reason: when you have many media queries, indeed, the 1st variant requires less copy/paste.

But though, the code becomes much less readable if you have many elements or modifiers in the block, i.e. selectors. It's common to face a situation when it's needed to change style for several elements/modifiers at exact screen. And when that case appears - as for me - it's easier to navigate between media queries, find the needed media and change code there - so you work at one place in the file, whereas in the 1st variant you would need to jump between selectors. In my opinion when it comes to work with media queries - it's faster to navigate between them, then to navigate between selectors.

imagine the following code with media query inside every selector :

.section_name_educational {
display: flex;
flex-direction: row;
padding: 0px;

.fp-tableCell {
display: flex;
flex-direction: row;
}

.section {

&__inner {
display: flex;
flex-direction: row-reverse;
height: 100vh;
height: calc(100vh - 80px);
box-sizing: border-box;
width: 50%;
padding-left: 40px;
margin-top: auto;
padding-bottom: 40px;
}

&__header {
position: relative;
width: 100%;
top: 62px;
left: 40px;
}

&__text-holder {
width: 100%;
}

&__title {
font-size: 48px;
}

&__subtitle {
width: 150%;
margin: 20px 0px;
}

&__description {
color: #669900;
font-size: 18px;
}

&__primary {
height: 100%;
display: flex;
box-sizing: border-box;
flex-direction: column;
justify-content: space-between;
width: 100%;
}

&__additional {
display: none;
}

&__kettles {
display: flex;
}

&__kettle {
height: auto;
margin-right: 20px;

&_order {
&_1 {
width: 183px;
min-width: 183px;
max-width: 183px;
}

&_2 {
width: 108px;
min-width: 108px;
max-width: 108px;
}

&_3 {
width: 127px;
min-width: 127px;
max-width: 127px;
}
}
}

&__background-holder {
overflow: hidden;
max-height: 100vh;
}

&__background {
position: relative;
width: auto;
height: 100vh;
}
}
}

@media all and (max-height: 600px) {
.section_name_educational {
.section {
&__kettle {
&_order {
&_2 {
width: 68px;
max-width: 68px;
min-width: 68px;
height: 120px;
margin-left: 30px;
}

&_3 {
width: 78px;
max-width: 78px;
min-width: 78px;
height: 120px;
}
}
}
}
}
}

@media all and (max-height: 760px) {
.section_name_educational {
.section {
&__header {
top: 40px;
}

&__subtitle {
width: 100% !important;
}

&__additional {
display: none !important;
}
}
}
}

@media (--large) {
.section_name_educational {
.section {
&__subtitle {
width: 120%;
}
}
}
}

@media (--xlarge) {
.section_name_educational {
padding-top: 120px;

.section {

&__inner {
height: calc(100vh - 60px);
margin-top: 0;
}

&__header {
transition-delay: 1s;
opacity: 0;
right: -100px;
bottom: -40px;
transform: translateY(20px);
}

&__subtitle {
width: 120%;
}

&__primary {
width: calc(100% - 160px);
}

&__additional {
display: flex;
flex-direction: column;
justify-content: space-between;
}

&__bubbles {
display: block;
position: relative;
top: 40px;
width: 160px;
min-width: 160px;
max-width: 160px;
height: auto;
transform: translateY(20px);
opacity: 0;
transition-delay: 1s;
}

&__kettle {
opacity: 0;
transform: translateY(20px);
transition-delay: 1s;
}
}

&.active {
.section {
&__header {
transition: opacity 1s ease-out 0.8s,
transform 0.8s ease-out 0.8s;
opacity: 1;
transform: translateY(0px);
}

&__kettle {
opacity: 1;
transform: translateY(0px);
transition: opacity 0.6s ease-out,
transform 0.6s ease-out;
&_order {
&_1 {
transition-delay: 1.6s;
display: block;
}

&_2 {
transition-delay: 1.9s;
}

&_3 {
transition-delay: 2.1s;
}
}
}

&__bubbles {
transition: opacity 0.8s ease-out 2.5s,
transform 0.8s ease-out 2.3s;
transform: translateY(0px);
opacity: 1;
}
}
}
}
}

@media all and (min-width: 1400px) {
.section_name_educational {
.section {
&__header {
left: 60px;
}

&__subtitle {
width: 110%;
}
}
}
}

@media (--xxlarge) {
.section_name_educational {
.section {

&__primary {
width: calc(100% - 148px);
}

&__subtitle {
width: 80%;
margin: 40px 0px;
}

&__description-inner {
width: 60%;
}

&__bubbles {
width: 148px;
min-width: 148px;
max-width: 148px;
top: 40px;
}
}
}
}

@media (--monster) {
.section_name_educational {
.section {
&__primary {
width: calc(100% - 227px);
}

&__header {
left: 200px;
top: 150px;
}

&__title {
font-size: 58px;
}

&__subtitle {
font-size: 24px;
width: 80%;
}

&__description {
font-size: 24px;
}

&__bubbles {
width: 227px;
min-width: 227px;
max-width: 227px;
left: 0px;
}
}
}
}

As for me - it would be difficult to read it if I had done it with the 1st variant.



Related Topics



Leave a reply



Submit