Media query ranges

Kudos to Kevin Powell's latest youtube video Stop using min-width in your media queries i just learned that css media query ranges are already baseline widely available.

Quick recap on what it looks like:

/* viewports larger than 64em = 1024px */
@media (width > 64em) {}

/* viewports larger than and including 64em = 1024px */
@media (width >= 64em) {}

/* viewports smaller than 64em = 1024px */
@media (width < 64em) {}

/* viewports larger than and including 35em = 560px and smaller than (and excluding) 64em = 1024px */
@media (35em <= width < 64em) {}

That means in my workplace i can now really start using them. Since we still have Sass in use in a lot of projects and a mixin for the media queries, i wonder how these mixins would now look like.

Here's the up-until-now mixin. The downside: We need separate variables for each defined breakpoint, e.g. for the 1024px breakpoints it's 1024px for the min-width and 1023px for the max-width.

@mixin respondMin($width) {
   @media (min-width: $width) {
     @content;
    }
}
// with equivalents for respondMax($width) and respondMinMax($minWidth, $maxWidth)

// and this is how they're included
.selector {
  @include respondMax($breakpoint-max-lg) {}
  @include respondMin($breakpoint-min-lg) {}
}

Now with ranged syntax, what would that look like? It uses the same variable.

// say, $width = 64em = 1024px
@mixin respondMinRange($width) {
   @media (width >= $width) {
     @content;
    }
}

@mixin respondMaxRange($width) {
   @media (width < $width) {
     @content;
    }
}

@mixin respondMinMaxRange($minWidth, $maxWidth) {
   @media ($minWidth <= width < $maxWidth) {
     @content;
    }
}

One could even go ahead and reduce the number of mixins, though i'm not sure i like this from a "readable code" perspective. Then again, could just be a matter of getting used to.

// define mixin
@mixin respondRange($width, $operator: '>=') {
   @media (width #{$operator} $width) {
     @content;
    }
}

// use mixin
.selector {
  @include respondRange($breakpoint-md) {} // @media (width >= 64em)
  @include respondRange($breakpoint-md, '<') {} // @media (width < 64em)
}

Looking at these mixins, i'm now thinking about the name. Media queries can react to so much more than the viewport inline size. For our typical workplace website, i wouldn't abstract the mixin itself any further.

But the naming can certainly be better. Maybe @include respondInlineSize($breakpoint-md)? Or @include breakpoint($inline-md)?

More logical syntax

Another woaah moment: i did have the and and or operators in my active css knowledge, but not the not operator. See "Media query fundamentals" on MDN for more.

Usually, i do the mobile-first approach. Start with styles and at adequate sizes adapt to larger viewports. If they're needed at all with all the shiny grid auto-fills and clamps and whatnot. (Yes, i still get very excited if i can write an entire responsive layout in 5 lines of css or so.) Nonetheless, from time to time i do find myself adding exceptions for very small mobiles.

So far, i've used max-width declarations to mark these. Since min-width declarations are the default approach, a max-width stands out. With ranged media queries that "smaller than" operator could easily be overlooked. The not operator might well become my go-to marker for these styles when writing native css.

/* exception below 22.5em = 360px viewports */
@media (max-width: 22.44em) {}
@media (width < 22.5em) {}
@media not (width > 22.5em) {}

The em reminder

For accessibility reasons it is recommended to use em values instead of pixel.

If a user changes the base font size in their browser settings, media queries will adapt better with em values, since those are relative to whatever is set in the browser. For the same reason, one should never use pixel values on font-size declarations.

Resources