Media Queries Mayhem:

Sass, I'm Looking at You!

By: Ricardo Zea - Web Designer

July 5th, 2016

DublinCSS Meetup

  • Originally from Colombia, South America.

     
  • Beautiful wife and son.

     
  • Doing Web Design for a very long time =]

Short story…

  • “There are no dumb questions. I just think it's dumb not to ask.”

What are Media Queries?

Media Queries Mayhem: Sass, I'm looking at you!

Is a CSS3 module allowing content rendering to adapt to [...] screen resolution[s] (e.g. smartphone screen vs. computer screen).

How does a Media Query look?

Media Queries Mayhem: Sass, I'm looking at you!

@media (min-width: 40em) {
  .selector {
    width: 100%;
  }
}

How do you use Media Queries?

Media Queries Mayhem: Sass, I'm looking at you!

@media (min-width: 40em) {
  .selector {
    width: 100%;
  }
}
.selector {
  width: 50%;
}

2 ways of creating

Media Queries:

Media Queries Mayhem: Sass, I'm looking at you!

The "vanilla" CSS way

The Sass way(s)

Media Queries Mayhem: Sass, I'm looking at you!

header {
  width: 50%;
}

.
.
.

/*=== Media Queries ===*/

/*640*/
@media (min-width: 40em) {
  header {
    width: 75%;
  }
}

/*800*/
@media (min-width: 50em) {
  header {
    width: 100%;
    padding-bottom: 10px;
    border-bottom: #999 1px dotted;
  }
}

The "vanilla" CSS way:

Media Queries Mayhem: Sass, I'm looking at you!

// Define some screen sizes for media queries
$phone:        320px;
$phone-wide:   500px;
$tablet:       600px;
$large-screen: 992px;

@mixin at-least($device-width) {
  @media screen and (min-width: $device-width) {
    @content 
  }
}

@mixin until($device-width) {
  @media screen and (max-width: $device-width - 1) {
    @content 
  }
}

The Sass way(s):

The "Screen Size Based" Style #1

Media Queries Mayhem: Sass, I'm looking at you!

// Define some screen sizes for media queries
$phone:        320px;
$phone-wide:   500px;
$tablet:       600px;
$large-screen: 992px;

The Sass way(s):

Let's focus on the screen sizes list for a minute...

The "Screen Size Based" Style #1

Media Queries Mayhem: Sass, I'm looking at you!

// Define some screen sizes for media queries
$phone:                320px;
$phone-pseudo-wide:    400px;
$phone-wide:           500px;
$tablet:               600px;
$large-screen:         992px;
The "Screen Size Based" Style #1

The Sass way(s):

Media Queries Mayhem: Sass, I'm looking at you!

// Define some screen sizes for media queries
$phone:                320px;
$phone-pseudo-wide:    400px;
$phone-wide:           500px;
$tablet:               600px;
$tablet-pseudo-wide:   640px;
$large-screen:         992px;
The "Screen Size Based" Style #1

The Sass way(s):

Media Queries Mayhem: Sass, I'm looking at you!

// Define some screen sizes for media queries
$phone:                320px;
$phone-pseudo-wide:    400px;
$phone-wide:           500px;
$tablet:               600px;
$tablet-pseudo-wide:   640px;
$tablet-semi-wide:     700px;
$large-screen:         992px;
The "Screen Size Based" Style #1

The Sass way(s):

Media Queries Mayhem: Sass, I'm looking at you!

// Define some screen sizes for media queries
$phone:                320px;
$phone-pseudo-wide:    400px;
$phone-wide:           500px;
$tablet:               600px;
$tablet-pseudo-wide:   640px;
$tablet-semi-wide:     700px;
$tablet-like-ipad:     768px;
$some-wider-tablet:    800px;
$good-luck-width:      860px;
$better-luck-width:    900px;
$good-'ol-960gs-width: 960px;
$i-prefer-980gs-width: 980px;
$large-screen:         992px;
$no-more-17-screens:   1024px;
$media-queries-mayhem: 1140px;

Things are starting to look ugly, eh?

The "Screen Size Based" Style #1

The Sass way(s):

Media Queries Mayhem: Sass, I'm looking at you!

Eeewww!

Media Queries Mayhem: Sass, I'm looking at you!

//Usage

.selector {
  @include at-least($phone-wide) {
    width: 50%;
  }
}
//Usage

.selector {
  @include at-least($tablet) {
    width: 50%;
  }
}
//Usage

.selector {
  @include at-least($media-queries-mayhem) {
    width: 50%;
  }
}
The "Screen Size Based" Style #1

The Sass way(s):

Result:

Absolute Sass Mayhem.

Media Queries Mayhem: Sass, I'm looking at you!

  • Too verbose if not careful when naming breakpoints
  • Prone to excess in breakpoints
  • Abstracts make it hard to memorize names : widths

Cons:

  • Clever solution
  • Individual mixins (min-width and max-width)
  • Independent mixins from screen size list
  • Easy to scale
  • Easily adaptable to content-based breakpoints

Pros:

The "Screen Size Based" Style #1

The Sass way(s):

Media Queries Mayhem: Sass, I'm looking at you!

The "Named Media Queries" Style:
@mixin breakpoint($point) {
  @if $point == papa-bear {
    @media (max-width: 1600px) { @content; }
  }
  @else if $point == mama-bear {
    @media (max-width: 1250px) { @content; }
  }
  @else if $point == baby-bear {
    @media (max-width: 650px)  { @content; }
  }
}

The Sass way(s):

Media Queries Mayhem: Sass, I'm looking at you!

@mixin breakpoint($point) {
  @if $point == papa-bear {
    @media (max-width: 1600px) { @content; }
  }
  @else if $point == papa-bear-chair {
    @media (max-width: 1400px) { @content; }
  }
  @else if $point == mama-bear {
    @media (max-width: 1250px) { @content; }
  }
  @else if $point == baby-bear {
    @media (max-width: 650px)  { @content; }
  }
}
The "Named Media Queries" Style:

The Sass way(s):

Media Queries Mayhem: Sass, I'm looking at you!

@mixin breakpoint($point) {
  @if $point == papa-bear {
    @media (max-width: 1600px) { @content; }
  }
  @else if $point == papa-bear-chair {
    @media (max-width: 1400px) { @content; }
  }
  @else if $point == mama-bear {
    @media (max-width: 1250px) { @content; }
  }
  @else if $point == mama-bear-chair {
    @media (max-width: 1180px) { @content; }
  }
  @else if $point == baby-bear {
    @media (max-width: 650px)  { @content; }
  }
}
The "Named Media Queries" Style:

The Sass way(s):

Media Queries Mayhem: Sass, I'm looking at you!

@mixin breakpoint($point) {
  @if $point == papa-bear {
    @media (max-width: 1600px) { @content; }
  }
  @else if $point == papa-bear-chair {
    @media (max-width: 1400px) { @content; }
  }
  @else if $point == mama-bear {
    @media (max-width: 1250px) { @content; }
  }
  @else if $point == mama-bear-chair {
    @media (max-width: 1180px) { @content; }
  }
  @else if $point == baby-bear {
    @media (max-width: 650px)  { @content; }
  }
  @else if $point == baby-bear-chair {
    @media (max-width: 500px) { @content; }
  }
}
The "Named Media Queries" Style:

The Sass way(s):

Media Queries Mayhem: Sass, I'm looking at you!

@mixin breakpoint($point) {
  @if $point == papa-bear {
    @media (max-width: 1600px) { @content; }
  }
  @else if $point == papa-bear-chair {
    @media (max-width: 1400px) { @content; }
  }
  @else if $point == mama-bear {
    @media (max-width: 1250px) { @content; }
  }
  @else if $point == mama-bear-chair {
    @media (max-width: 1180px) { @content; }
  }
  @else if $point == baby-bear {
    @media (max-width: 650px)  { @content; }
  }
  @else if $point == baby-bear-chair {
    @media (max-width: 500px) { @content; }
  }
  @else if $point == goldilocks {
    @media (max-width: 420px) { @content; }
  }
}
The "Named Media Queries" Style:

The Sass way(s):

Media Queries Mayhem: Sass, I'm looking at you!

@mixin breakpoint($point) {
  @if $point == papa-bear {
    @media (max-width: 1600px) { @content; }
  }
  @else if $point == papa-bear-chair {
    @media (max-width: 1400px) { @content; }
  }
  @else if $point == mama-bear {
    @media (max-width: 1250px) { @content; }
  }
  @else if $point == mama-bear-chair {
    @media (max-width: 1180px) { @content; }
  }
  @else if $point == baby-bear {
    @media (max-width: 650px)  { @content; }
  }
  @else if $point == baby-bear-chair {
    @media (max-width: 500px) { @content; }
  }
  @else if $point == goldilocks {
    @media (max-width: 420px) { @content; }
  }
  @else if $point == media-queries-mayhem {
    @media (max-width: 320px) { @content; }
  }
}
The "Named Media Queries" Style:

The Sass way(s):

Media Queries Mayhem: Sass, I'm looking at you!

@mixin breakpoint($point) {
  @if $point == papa-bear {
    @media (max-width: 1600px) { @content; }
  }
  @else if $point == papa-bear-chair {
    @media (max-width: 1400px) { @content; }
  }
  @else if $point == mama-bear {
    @media (max-width: 1250px) { @content; }
  }
  @else if $point == mama-bear-chair {
    @media (max-width: 1180px) { @content; }
  }
  @else if $point == baby-bear {
    @media (max-width: 650px)  { @content; }
  }
  @else if $point == baby-bear-chair {
    @media (max-width: 500px) { @content; }
  }
  @else if $point == goldilocks {
    @media (max-width: 420px) { @content; }
  }
  @else if $point == media-queries-mayhem {
    @media (max-width: 320px) { @content; }
  }
}
The "Named Media Queries" Style:

The Sass way(s):

Media Queries Mayhem: Sass, I'm looking at you!

papa-bear 
papa-bear-chair 
mama-bear 
mama-bear-chair 
baby-bear 
baby-bear-chair 
goldilocks 
media-queries-mayhem

Starbucks

short
tall
grande
venti

GoT

eddard
catelyn
robb
sansa
arya
bran
rickon

LOTR

gollum
bilbo
gimly
aragorn
gandalf
balrog

Heavy Metal

fucking-small
small
medium
large
fucking-large

The "Named Media Queries" Style:

The Sass way(s):

Media Queries Mayhem: Sass, I'm looking at you!

//Usage

.selector {
  @include breakpoint(baby-bear) {
    width: 50%;
  }
}
The "Named Media Queries" Style:

The Sass way(s):

Media Queries Mayhem: Sass, I'm looking at you!

Media Queries Mayhem: Sass, I'm looking at you!

//Usage

.selector {
  @include breakpoint(baby-bear) {
    width: 50%;
  }
}
//Usage

.selector {
  @include breakpoint(mama-bear-chair) {
    width: 50%;
  }
}
The "Named Media Queries" Style:

The Sass way(s):

Media Queries Mayhem: Sass, I'm looking at you!

Media Queries Mayhem: Sass, I'm looking at you!

//Usage

.selector {
  @include breakpoint(baby-bear) {
    width: 50%;
  }
}
//Usage

.selector {
  @include breakpoint(mama-bear-chair) {
    width: 50%;
  }
}
//Usage

.selector {
  @include breakpoint(goldilocks) {
    width: 50%;
  }
}
The "Named Media Queries" Style:

The Sass way(s):

No effin' clue amigo!

Media Queries Mayhem: Sass, I'm looking at you!

Regardless of the funny names,
the "Named Media Queries" technique
is a clever solution too.

 

Let's build upon it:

Media Queries Mayhem: Sass, I'm looking at you!

//Chris' style

@mixin breakpoint($point) {
  @if $point == papa-bear {
    @media (max-width: 1600px) { @content; }
  }
  @else if $point == mama-bear {
    @media (max-width: 1250px) { @content; }
  }
  @else if $point == baby-bear {
    @media (max-width: 650px)  { @content; }
  }
}
//Ricardo's adaption for "Desktop-first" method

@mixin maxw($point) {
  @if $point == 1140 {
    @media (max-width: 1140px) { @content; }
  }
  @else if $point == 1024 {
    @media (max-width: 1024px) { @content; }
  }
  @else if $point == 980 {
    @media (max-width: 980px)  { @content; }
  }
}

Desktop-first

Media Queries Mayhem: Sass, I'm looking at you!

//Ricardo's adaptation for "Desktop-first" method

@mixin maxw($point) {
  @if $point == 1140 {
    @media (max-width: 1140px) { @content; }
  }
  @else if $point == 1024 {
    @media (max-width: 1024px) { @content; }
  }
  @else if $point == 980 {
    @media (max-width: 980px)  { @content; }
  }
}
//Ricardo's adaptation for "Mobile-first" method

@mixin minw($point) {
  @if $point == 980 {
    @media (min-width: 980px) { @content; }
  }
  @else if $point == 1024 {
    @media (min-width: 1024px) { @content; }
  }
  @else if $point == 1140 {
    @media (min-width: 1140px)  { @content; }
  }
}

Mobile-first

Individual Mixins:

Hmm!

Media Queries Mayhem: Sass, I'm looking at you!

Media Queries Mayhem: Sass, I'm looking at you!

//Usage - Ricardo's version

.selector {
  @include minw(980) {
    width: 50%;
  }
}
The "Named Media Queries" Style:

The Sass way(s):

Media Queries Mayhem: Sass, I'm looking at you!

Media Queries Mayhem: Sass, I'm looking at you!

//Usage - Ricardo's version

.selector {
  @include minw(980) {
    width: 50%;
  }
}
//Usage - Ricardo's version

.selector {
  @include minw(1024) {
    width: 75%;
  }
}
The "Named Media Queries" Style:

The Sass way(s):

Media Queries Mayhem: Sass, I'm looking at you!

Media Queries Mayhem: Sass, I'm looking at you!

//Usage - Ricardo's version

.selector {
  @include minw(980) {
    width: 50%;
  }
}
//Usage - Ricardo's version

.selector {
  @include minw(1024) {
    width: 75%;
  }
}
//Usage - Ricardo's version

.selector {
  @include minw(1140) {
    width: 100%;
  }
}
The "Named Media Queries" Style:

The Sass way(s):

Media Queries Mayhem: Sass, I'm looking at you!

  • Too verbose if not careful when naming breakpoints
  • Prone to excess in breakpoints
  • Abstracts makes it hard to memorize names : widths
  • Prone to too many lines in the mixin
  • Not DRY

Cons:

  • Clever solution
  • Individual mixins (Dekstop-first and Mobile-first)
  • All breakpoints visible in a single media block
  • Easy to scale
  • Easily adaptable to content-based breakpoints

Pros:

The "Named Media Queries" Style:

The Sass way(s):

I admit it :)

Media Queries Mayhem: Sass, I'm looking at you!

I've used the 'Named Media Queries' method:

Media Queries Mayhem: Sass, I'm looking at you!

//Desktop-first
@mixin maxw($point) {
	@if $point == 1140 {
		@media (max-width: 76.125em) { @content; }
	}
	@else if $point == 1000 {
		@media (max-width: 62.5em) { @content; }
	}
	@else if $point == 960 {
		@media (max-width: 60em) { @content; }
	}
	@else if $point == 900 {
		@media (max-width: 56.25em) { @content; }
	}
	@else if $point == 800 {
		@media (max-width: 50em) { @content; }
	}
	@else if $point == 768 {
		@media (max-width: 48em) { @content; }
	}
	@else if $point == 700 {
		@media (max-width: 43.75em) { @content; }
	}
	@else if $point == 640 {
		@media (max-width: 40em) { @content; }
	}
	@else if $point == 600{
		@media (max-width: 37.5em) { @content; }
	}
	@else if $point == 580 {
		@media (max-width: 36.25em) { @content; }
	}
	@else if $point == 520 {
		@media (max-width: 32.5em) { @content; }
	}
	@else if $point == 480 {
		@media (max-width: 30em) { @content; }
	}
	@else if $point == 400 {
		@media (max-width: 25em) { @content; }
	}
	@else if $point == 320 {
		@media (max-width: 20em) { @content; }
	}
}

//Mobile-first
@mixin minw($point) {
	@if $point == 321 {
		@media (min-width: 20.06em) { @content; }
	}
	@else if $point == 401 {
		@media (min-width: 25.06em) { @content; }
	}
	@else if $point == 481 {
		@media (min-width: 30.06em) { @content; }
	}
	@else if $point == 521 {
		@media (min-width: 32.56em) { @content; }
	}
	@else if $point == 581 {
		@media (min-width: 36.31em) { @content; }
	}
	@else if $point == 601 {
		@media (min-width: 37.56em) { @content; }
	}
	@else if $point == 641 {
		@media (min-width: 40.06em) { @content; }
	}
	@else if $point == 701 {
		@media (min-width: 43.81em) { @content; }
	}
	@else if $point == 769 {
		@media (min-width: 48.06em) { @content; }
	}
	@else if $point == 801 {
		@media (min-width: 50.06em) { @content; }
	}
	@else if $point == 901 {
		@media (min-width: 56.31em) { @content; }
	}
	@else if $point == 961 {
		@media (min-width: 60.06em) { @content; }
	}
	@else if $point == 1001 {
		@media (min-width: 62.56em) { @content; }
	}
	@else if $point == 1141 {
		@media (min-width: 71.31em) { @content; }
	}
}

Not DRY and ugly, isn't it?

Media Queries Mayhem: Sass, I'm looking at you!

Eeewww dude!

Result:

Absolute Sass Mayhem.

Media Queries Mayhem: Sass, I'm looking at you!

Media Queries Mayhem: Sass, I'm looking at you!

$breakpoints: (phone: 480px, tablet: 768px, desktop: 1024px) !default;
$media-expressions: (screen: "screen", 
                    print: "print", 
                    retina2x: ("(-webkit-min-device-pixel-ratio: 2)", "(min-resolution: 192dpi)"), 
                    retina3x: ("(-webkit-min-device-pixel-ratio: 3)", "(min-resolution: 350dpi)")
                    ) !default;

@mixin media($conditions...) {
  $i: 1;
  
  @each $condition in $conditions {
    $conditions: set-nth($conditions, $i, parse-expression(nth($conditions, $i)));
    $i: $i + 1;
  }
  
  $branches: get-query-branches($conditions);
  $query: "";
  
  @each $branch in $branches {
    @if ($query != "") {
      $query: $query + ", ";
    }
    
    $query: $query + $branch;
  }
  
  @media #{$query} { @content; }
}

@function get-query-branches($expressions) {
  $result: "";
  $has-groups: false;
  
  // Getting initial snapshot and looking for groups
  @each $expression in $expressions {
    @if ($result != "") {
      $result: $result + " and ";
    }
    
    @if (type-of($expression) == "string") {
      $result: $result + $expression;
    } @else if (type-of($expression) == "list") {
      $result: $result + nth($expression, 1);
      $has-groups: true;
    }
  }  
  
  // If we have groups, we have to create all possible combinations
  @if $has-groups {
    @each $expression in $expressions {
      @if (type-of($expression) == "list") {
        $first: nth($expression, 1);
        
        @each $member in $expression {
          @if ($member != $first) {
            @each $partial in $result {
              $result: join($result, str-replace-first($first, $member, $partial));
            }
          }
        }
      }
    }    
  }
  
  @return $result;
}

@function parse-expression($expression) {
  $operator: "";
  $value: "";
  $element: "";
  $result: "";
  $is-width: true;  
  
  // Separating the operator from the rest of the expression
  @if (str-slice($expression, 2, 2) == "=") {
    $operator: str-slice($expression, 1, 2);
    $value: str-slice($expression, 3);
  } @else {
    $operator: str-slice($expression, 1, 1);
    $value: str-slice($expression, 2);
  }
  
  // Checking what type of expression we're dealing with
  @if map-has-key($breakpoints, $value) {
    $result: map-get($breakpoints, $value);
  } @else if map-has-key($media-expressions, $expression) {
    $result: map-get($media-expressions, $expression);
    $is-width: false;
  } @else {
    $result: to-number($value);
  }
  
  @if ($is-width) {
    @if ($operator == ">") {
      $element: "(min-width: #{$result + 1})";
    } @else if ($operator == "<") {
      $element: "(max-width: #{$result - 1})";
    } @else if ($operator == ">=") {
      $element: "(min-width: #{$result})";
    } @else if ($operator == "<=") {
      $element: "(max-width: #{$result})";
    }
  } @else {
    $element: $result;
  }
  
  @return $element;
}

@function str-replace-first($search, $replace, $subject) {
  $search-start: str-index($subject, $search);
  
  @if not $search-start {
    @return $subject;
  }
  
  $result: str-slice($subject, 0, $search-start - 1);
  $result: $result + $replace;
  $result: $result + str-slice($subject, $search-start + str-length($search));
  
  @return $result;
}

@function _length($number, $unit) {
  $strings: 'px' 'cm' 'mm' '%' 'ch' 'pica' 'in' 'em' 'rem' 'pt' 'pc' 'ex' 'vw' 'vh' 'vmin' 'vmax';
  $units:   1px  1cm  1mm  1%  1ch  1pica  1in  1em  1rem  1pt  1pc  1ex  1vw  1vh  1vmin  1vmax;
  $index: index($strings, $unit);
  
  @if not $index {
    @warn "Unknown unit `#{$unit}`.";
    @return false;
  }
  
  @return $number * nth($units, $index);
}

@function to-number($string) {
  // Matrices
  $strings: '0' '1' '2' '3' '4' '5' '6' '7' '8' '9';
  $numbers:  0   1   2   3   4   5   6   7   8   9;
  
  // Result
  $result: 0;
  $divider: 0;
  $minus: false;

  // Looping through all characters
  @for $i from 1 through str-length($string) {
    $character: str-slice($string, $i, $i);
    $index: index($strings, $character);
    
  
    @if $character == '-' {
      $minus: true;
    }
    
    @else if $character == '.' {
      $divider: 1;
    }
    
    @else {
      @if not $index {
        $result: if($minus, $result * -1, $result);
        @return _length($result, str-slice($string, $i));
      }

      $number: nth($numbers, $index);
      
      @if $divider == 0 {
        $result: $result * 10;
      }
      
      @else {
        // Move the decimal dot to the left
        $divider: $divider * 10;
        $number: $number / $divider;
      }
      
      $result: $result + $number;
    }
  }
  
  @return if($minus, $result * -1, $result);
}

/**
*
* Testing
*
**/

div {
  @include media("<=phone") {
    background-color: #def;
    
    &:before {
      content: "<=phone";
    }
  }

  @include media(">phone") {
    background-color: #abc;
    
    &:before {
      content: ">phone";
    }    
  }

  @include media(">=815px", "<desktop") {
    background-color: #fed;
    
    &:before {
      content: ">=815px, <desktop";
    }    
  }

  @include media(">=desktop") {
    background-color: #fab;
    
    &:before {
      content: ">=desktop";
    }
  }
  
  @include media("retina2x") {
    &:after {
      content: "Retina" !important;
    }    
  }
}
The "Screen Size Based" Style #2

The Sass way(s):

Absolute Sass Mayhem.

Media Queries Mayhem: Sass, I'm looking at you!

  • Usage a bit confusing (>=phone, etc.)
  • Too advanced for beginners
  • Prone to excess in breakpoints
  • Abstracts makes it hard to memorize names : widths
  • Excessive amount of lines in the mixin
  • Overkill mixin to simply handle media queries

Cons:

  • Clever solution
  • Robust mixin
  • Single mixin that handles everything
  • Easy to scale
  • Easily adaptable to content-based breakpoints

Pros:

The Screen Size Based Style #2

The Sass way(s):

Sass, dude...
This mayhem! Bleh.

Media Queries Mayhem: Sass, I'm looking at you!

THINK.

Media Queries Mayhem: Sass, I'm looking at you!

Whatever method we use,
all we want at the end is something similar to this:

@media (min-width: 640px) {
  .selector {
    width: 100%;
  }
}

Media Queries Mayhem: Sass, I'm looking at you!

Simple.

Put things in perspective and ask yourself:

Media Queries Mayhem: Sass, I'm looking at you!

  • Is Sass and its enormous power complicating things too much?
  • Why do these solutions have so many Cons?
  • Does handling CSS media queries need to be THIS complicated?
  • Shouldn't building a better web be easier?
  • Isn't creating such complex and abstract features blinding us from the end result: memorable experiences and happy users?

Media Queries Mayhem: Sass, I'm looking at you!

Ironically Sass can answer all

those questions with:

The

"HASTA LUEGO"

Mixin

Because you're saying "So Long!" to those other mixins we saw before :)

@mixin goingLarge($width) {
    @media (min-width: $width){ @content; }
}

Media Queries Mayhem: Sass, I'm looking at you!

The "Hasta Luego" Style:

A mere 3 line mixin:

The Sass way(s):

This is how the HASTA LUEGO mixin works:

Media Queries Mayhem: Sass, I'm looking at you!

.selector {
  //…Mobile stuff
  @include goingLarge(600px) { //Content-based breakpoint
    //Desktop stuff
  }
}

Mixin:

@mixin goingLarge($width) {
    @media (min-width: $width){ @content; }
}

Example:

//Mobile-first Mixin
@mixin goingLarge($width) {
    @media (min-width: $width){ @content; }
}

//Example:
header {
  width: 100%;
  @include goingLarge(487px) { //Content-based breakpoint
    width: 50%;
  }
}

//Compiles to:
header {
  width: 100%;  
}

@media (min-width: 487px){
  header {
    width: 50%;  
  }
}

Media Queries Mayhem: Sass, I'm looking at you!

Mobile-first Mixin:

Hmm!

Media Queries Mayhem: Sass, I'm looking at you!

  • Baffling simple and clever solution
  • Completely DRY
  • Individual mixins (Desktop-first and Mobile-first)
  • It accomplishes exactly the same as the other methods with A LOT less code.
  • No need to keep track of widths
  • No need to memorize abstract names : widths
  • It directs you to create breakpoints based on content rather than on specific/device widths.
  • Easy to use
  • Easy for beginners to understand

Pros:

The "Hasta Luego" Style

Media Queries Mayhem: Sass, I'm looking at you!

The Sass way:

Cons:

Nothhhhhhing!

Media Queries Mayhem: Sass, I'm looking at you!

The Sass way:

The "Hasta Luego" Style

Example:

//Desktop-first Mixin
@mixin goingSmall($width) {
    @media (max-width: $width){ @content; }
}

//Example:
header {
  width: 50%;
  @include goingSmall(725px) { //Content-based breakpoint
    width: 100%;
  }
}

//Compiles to:
header {
  width: 50%;  
}

@media (max-width: 725px){
  header {
    width: 100%;  
  }
}

Media Queries Mayhem: Sass, I'm looking at you!

Dekstop-first Mixin:

Dood! That's sweeet!

Media Queries Mayhem: Sass, I'm looking at you!

Takeaways:

Media Queries Mayhem: Sass, I'm looking at you!

  • Put things in perspective before committing to a solution.
  • Never stop questioning solutions you adopt.
  • Assign Pros and Cons to your methods.
  • The power of Sass can be overwhelming sometimes, don't let it intimidate you.
  • It's not how proficient you are with a web technology, is how you use it to make memorable experiences and users happy.

“Life’s most persistent and urgent question is:
What are you doing for others?”

— Dr. Martin Luther King Jr.

Gracias!

Media Queries Mayhem:

Sass, I'm Looking at You!

Ramón, 1994 - 2004

By: Ricardo Zea - Web Designer

July 5th, 2016

DublinCSS Meetup

Desktop-first

Media Queries Mayhem: Sass, I'm looking at you!

//Ricardo's adaptation for "Desktop-first" method

@mixin maxw($point) {
  @if $point == 1140 {
    @media (max-width: 71.25em) { @content; }
  }
  @else if $point == 1024 {
    @media (max-width: 64em) { @content; }
  }
  @else if $point == 980 {
    @media (max-width: 61.25em)  { @content; }
  }
}
//Ricardo's adaptation for "Mobile-first" method

@mixin minw($point) {
  @if $point == 980 {
    @media (min-width: 61.25em) { @content; }
  }
  @else if $point == 1024 {
    @media (min-width: 64em) { @content; }
  }
  @else if $point == 1140 {
    @media (min-width: 71.25em)  { @content; }
  }
}

Mobile-first

Use em's rather than px:

Formula: width(px) / font base(px) = em value
Example: 1024px / 16px = 64em

Media Queries Mayhem: Sass, I'm Looking at You!

By Ricardo Zea

Media Queries Mayhem: Sass, I'm Looking at You!

I've seen amazingly clever Sass mixins created to handle CSS media queries, but I think that some of these solutions are overkill. In this presentation I show you how a mere 3 line Sass mixin can accomplish the same, keeping us focused on what matters most at the end of our day: happy users. -- Presentation for the Dublin CSS meetup (Ireland) - http://www.meetup.com/DublinCSS/

  • 1,486