chavab_1 chavab_1 - 1 month ago 18
CSS Question

SASS Media Query Mixin

I'm trying to get my breakpoints setup following this tutorial. They are working correctly when I target just one property. When I try to create a query that targets two (width and height) it only displays the latter. I've researched the Sass functions that I'm using and it should be rendering correctly so I'm not sure what the problem is. I'm using sass-rails on Ruby on Rails version 4.2.2.

Thanx

$breakpoints: (
'small' : ( max-width: 20em ),
'mobile' : ( min-width: 36.25em ),
'tablet' : ( min-width: 48em ),
'desktop' : ( min-width: 60em ),
'wide' : ( min-width: 75em ),
'height' : ( min-width: 75em ) and (min-height: 62.5em)
);

@mixin media($name) {
@if map-has-key($breakpoints, $name) {
@media #{inspect(map-get($breakpoints, $name))} {
@content;
}
}

@else {
@warn "Unfortunately, no value could be retrieved from `#{$breakpoint}`. "
+ "Please make sure it is defined in `$breakpoints` map.";
}
}


This is what is rendered:

@media (min-height: 62.5em) {

}

Answer

Normally when storing media queries in variables or as values in a key value pair, they should be stored as strings. Check out these sites Media Queries by David Walsh and Responsive Web Design in Sass by Mason Wendell

Replace this line of code
'height' : ( min-width: 75em ) and (min-height: 62.5em)
with
'height' : "( min-width: 75em ) and (min-height: 62.5em)"

Now that the values passed to the mixin can either be a string or list, the mixin needs to recognise these changes

@mixin media($name) {
  @if map-has-key($breakpoints, $name) {
    $value: map-get($breakpoints, $name);
    $query: if(type-of($value) == "string", $value, inspect($value));
    @media #{$query} {
      @content;
    }
  }
  @else {
    @warn "Unfortunately, no value could be retrieved from `#{$breakpoint}`. "
        + "Please make sure it is defined in `$breakpoints` map.";
  }
}

$breakpoints: (
  'small'  : ( max-width:  20em ),
  'wide'    : "( min-width: 75em ) and (min-height: 62.5em) and (max-height: 100em)",
  'height'    : "( min-width: 75em ) and (min-height: 62.5em)"  
);

div.gta {
  @include media(wide) { ... }
}

div#mgs {
  @include media(height) { ... }
}

This compiles to the following CSS

@media (min-width: 75em) and (min-height: 62.5em) and (max-height: 100em) {
  div.gta { ... }
}

@media (min-width: 75em) and (min-height: 62.5em) {
  div#mgs { ... }
}

This will allow the mixin to be used on any number of media queries