Anton Boritskiy
Anton Boritskiy

Reputation: 1569

Nested CSS3 media queries in SCSS/Sass

I'm working on a responsive web-site which is based on Bootstrap. I use SCSS/Sass and Compass to optimize the CSS workflow. And in my Sass code I have the following:

$sm-screens-and-wider: "screen and (min-width: 768px)";
$lg-screens: "screen and (min-width: 1200px)";

@media #{$sm-screens-and-wider} {
    .search-copyright-tab .copyright {
      font-size: 19px;
      @media #{$lg-screens} {
        font-size: 21px;
      }
    }
}

this results into the following CSS:

@media screen and (min-width: 768px) {
  .search-copyright-tab .copyright {
    font-size: 19px;
  }
}
    
@media screen and (min-width: 768px) and (min-width: 1310px) {
  .search-copyright-tab .copyright {
    font-size: 21px;
  }
}

Note the repeating min-width in the second media-query. That is valid CSS code and works quite fine in modern browsers. But respond.js fails parsing it, since it's regex grabs the first value and IE8 renders content in wrong way.

I have googled a lot and haven't find any mentions of issues like that. I found even why it fails with responds.js:

minw : thisq.match( /\(\s*min\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" ),

this regex only considers first found min-width in media-query statement (thisq). So currently I have several possible solutions (arranged by severity):

  1. Use max-width media-queries for such case, though braking mobile-first concept;
  2. Change my SCSS/Sass file structure and make it less readable by separating the same class styles;
  3. Fork and modify respond.js library;
  4. Post-process the output of Sass and rewrite the broken entries.

To be honest I'm not happy with any of these solutions, and I have a feeling that Sass should process such cases himself and it is my weird Sass use-case, which forces it behaves like that (except using Sass with Bootstrap, which is Less powered). Can anybody point out the easier/better solution here?

Upvotes: 3

Views: 4214

Answers (1)

Daniel Imms
Daniel Imms

Reputation: 50149

It makes sense to merge identical items (screen) but not the min-widths as they are different. I've found SASS actually has very little understanding of what CSS rules are valid by design, in order to future-proof itself.

I wouldn't be comfortable using a merge query that has multiple queries like that not only because of the issue you're having but because it's precious wasted bytes that still have to go over the wire.

I would use @include to define the @media queries as it's a little nicer than the string method you're using and do it like this, which I feel is just as readable as your solution without the problems:

// The mixins can be defined in some shared file
@mixin media-gte-sm {
  @media screen and (min-width: 768px) {
    @content;
  }
}
@mixin media-gte-lg {
  @media screen and (min-width: 1200px) {
    @content;
  }
}

.search-copyright-tab .copyright {
  @include media-gte-sm {
    font-size: 19px;
  }
  @include media-gte-lg {
    font-size: 21px;
  }
}

Upvotes: 2

Related Questions