Responsive Web Design with Sass+Compass

Slides available at

http://snugug.github.io/RWD-with-Sass-Compass/

Who Am I?

First, an experiment

Hold up your hand if you own a smartphone

Lower it if you have the exact same phone (make, model, carrier, and OS version) as your neighbors

Put your hands back up

Lower it if you only use your phone while you're distracted, on the go, and want a dumbed-down or lite experience

Responsive Web Design isn’t about current devices and known unknowns, it’s about future devices and unknown unknowns.

What's a team to do?

We start with our content first

It’s not about mobile first (or just small screen first) – it's about content first. But it happens that thinking about what works for mobile does work for other things as well.

Jeffery Zeldman

We design using mobile as a focusing lens


But don't take that the wrong way…

[T]here is no mobile web. There are plenty of mobile devices. And equally there is no desktop web. It is just the web. [O]ne web.

Jeremy Keith

We use web standards, progressive enhancement, and modern best practices

All while staying device agnostic, avoiding common user experience pitfalls, and staying future friendly.

This is not the web
This is the web
This will be the web

Oh, and throw away “Pixel Perfect”

Of Course Responsive Web Design is Hard.

It's Design.

Mason Wendell

The Web is an Inherently Unstable Medium

Ethan Marcotte

What Do You Need for RWD?

As outlined in Ethan Marcotte's Phrase-Coining A List Apart article, Responsive Web Design needs the three following things:

  • Media Queries
  • Fluid Grids
  • Flexible Media

Using Compass Extensions

gem 'extension', '~>X.Y.Z'
require '{extension}'
@import '{extension}';

Media Queries

Start with the small screen first, then expand until it looks like shit.

TIME FOR A BREAKPOINT!

Stephen Hay

Breakpoint

gem 'breakpoint', '~>2.4.0'
require 'breakpoint'
@import 'breakpoint';

Basic Media Queries - Sass

// Your basic media queries, min-width and min/max width, are super easy!
$small: 543px;
$medium: 794px;
$fence-sm: $small $medium;

#foo {
  content: 'No Media Queries';

  @include breakpoint($small) {
    content: 'Small Media Query';
  }

  @include breakpoint($fence-sm) {
    content: 'Fenced Media Query';
  }
}

Basic Media Queries - CSS

 /* Nested Breakpoint calls become separate media queries */
#foo {
  content: 'No Media Queries';
}

@media (min-width: 543px) {
	#foo {
		content: 'Small Media Query';
	}
}

@media (min-width: 543px) and (max-width: 794px) {
	#foo {
		content: 'Fenced Media Query';
	}
}

Basic Media Queries - CSS

 /* Setting $breakpoint-to-ems: true will write Media Queries in Ems! */
@media (min-width: 33.9375em) {
	#foo {
		content: 'Small Media Query';
	}
}

@media (min-width: 33.9375em) and (max-width: 49.625em) {
	#foo {
		content: 'Fenced Media Query';
	}
}

Advanced Media Queries - Sass

// Advanced "and" media queries and "or" media queries made simple
$print-land: print monochrome (orientation landscape);

$fenced-landscape: screen 321px 543px, handheld (orientation portrait);

#foo {
  @include breakpoint($print-land) {
    content: 'Monochrome Print in Landscape';
  }

  @include breakpoint($fence-landscape) {
    content: 'Screen media type between 300px and 500px or Handheld media type in Portrait';
  }
}

Advanced Media Queries - CSS

 /* Advanced "and" media queries and "or" media queries made simple */
@media print and (monochrome) and (orientation: landscape) {
	#foo {
		content: 'Monochrome Print in Landscape';
	}
}

@media screen and (min-width: 321px) and (max-width: 543px), handheld and (orientation: portrait) {
	#foo {
		content: 'Screen media type between 300px and 500px or Handheld media type in Portrait';
	}
}

Resolution Media Queries - Sass

// Resolution media queries are a pain. Breakpoint makes them easy. We use the standard DPPX units.
$hidpi: min-resolution 1.5dppx;
$cross-reso: max-resolution 143dpi;

#foo {
  @include breakpoint($hidpi) {
    content: 'Device Pixel Ratio of at least 1.5';
  }

  @include breakpoint($cross-reso) {
  	content: 'Cross Browser Resolution Query'
  }
}

Resolution Media Queries - CSS

 /* Breakpoint will transform the DPPX unit into cross-browser compatible resolution queries and DPI units into cross-browser DPR queries! */
@media (min-resolution: 1.5dppx), (-webkit-min-device-pixel-ratio: 1.5), (min--moz-device-pixel-ratio: 1.5), (min-resolution: 144dpi) {
  #foo {
    content: 'Device Pixel Ratio of at least 1.5';
  }
}

@media (max-resolution: 143dpi), (-webkit-max-device-pixel-ratio: 1.48958), (max--moz-device-pixel-ratio: 1.48958) {
  #foo {
    content: "Cross Browser Resolution Query";
  }
}

Media Query Fallbacks - Sass

// _mqs.scss
$touch: pointer fine, 'no-query' '.no-touch';
$no-queries: 678px, 'no-query' '.no-mqs';

#foo {
  @include breakpoint($touch) {
    content: 'Fine Pointer';
  }
  @include breakpoint($no-queries) {
  	content: 'No Media Queries';
	}
}

Media Query Fallbacks - Sass

// style.scss
$breakpoint-no-queries:         false;
$breakpoint-no-query-fallbacks: false;

@import "mqs";
// touch.scss
$breakpoint-no-queries:         true;
$breakpoint-no-query-fallbacks: '.no-touch';

@import "mqs";

Media Query Fallbacks - CSS

/* style.css */
/* Only the Media Query gets printed out here! */
@media (pointer: fine) {
  #foo {
  	content: 'Fine Pointer';
	}
}
No Touching!

Media Query Fallbacks - CSS

/* style.css */
/* Only the Media Query gets printed out here! */
@media (pointer: fine) {
  #foo {
  	content: 'Fine Pointer';
	}
}
/* touch.css */
/* Only the Meida Queries with a .touch no-fallback get printed! */
.no-touch #foo {
	content: 'Fine Pointer';
}

Fluid Grids

Box Model

Let's Cheat at CSS

// We can import all of Compass safely because it doesn't write any CSS.
@import 'compass';

// We switch our box model to Border Box.
// From [Paul Irish](http://paulirish.com/2012/box-sizing-border-box-ftw/)
*, *:before, *:after {
  @include box-sizing('border-box');
}

Singularity

gem 'singularitygs', '~>1.2.0.rc.3'
require 'singularitygs'
@import 'singularitygs';

Building With Grids

Grids provide order to your design and structure to your information.

The best grids are specific to your content and your design, as they are an extension of both.

Twitter Bootstrap

Zurb Foundation

YUI Pure

All The Grids Are All The Same!

Boring Grids

Symmetric Grids - Twitter Bootstrap

@include add-grid(12);
@include add-gutter(1/3);
Twitter Bootstrap Grid

Symmetric Grids - Zurb Foundation

@include add-grid(12);
@include add-gutter(0.9375em);
@include add-gutter-style(split);
Zurb Foundation Grid

Symmetric Grids - YUI Pure

@include add-grid(12);
@include add-gutter(0);
YUI Pure Grid

Interesting Grids

Asymmetric Grid - Custom

@include add-grid(1 4 1);
@include add-gutter(1/6);
@include add-gutter-style(split)
Custom Asymmetric Grid

Asymmetric Grid - Compound

// Compound function comes from [Singularity Extras](https://github.com/Team-Sass/Singularity-extras)
@include add-grid(compound(3, 4));
@include add-gutter(1);
Compound Asymmetric Grid

Asymmetric Grid - Ratio Based

// Ratio function comes from [Singularity Extras](https://github.com/Team-Sass/Singularity-extras)
@include add-grid(ratio(golden-ratio(), 4));
@include add-gutter(golden-ratio() * 1em);
@include add-gutter-style(split);
Ratio Asymmetric Grid

Asymmetric Grid - Spiral Based

// Ratio spiral function comes from [Singularity Extras](https://github.com/Team-Sass/Singularity-extras)
@include add-grid(ratio-spiral(5));
@include add-gutter(1);
Ratio Spiral Asymmetric Grid

Asymmetric Grid - Mixed Fixed and Fluid Grids

// Calc output style comes from [Singularity Extras](https://github.com/Team-Sass/Singularity-extras)
@include add-grid(320px 1 2);
@include add-gutter(1em);
@include sgs-change('output', 'calc');

Semantic Grids

Singularity is what we like to call a semantic grid system, meaning that instead of grid classes being generated that you then apply to your HTML, the grid is stored entirely within your CSS and applied directly to the element you want to use it on.

Spanning The Grid - HTML

<body>
  <div class="main">Main Section</div>
  <div class="first">First Section</div>
  <div class="second">Second Section</div>
</body>

Spanning The Grid - Sass

// Simply pass the number of columns you'd like to span and what column you'd like to start from.

@include add-grid(2 8 2);
@include add-gutter(1/3);

.first {
  @include grid-span(1, 1);
}

.main {
  @include grid-span(1, 2);
}

.second {
  @include grid-span(1, 3);
}

Spanning The Grid - Display

Grid Span display

Responsive Grid Context - Sass

// add-grid allows you to automatically change your global Grid Context at various breakpoints

@include add-grid(12);
@include add-grid(2 8 2 at 700px);
@include add-gutter(1/3);

.first {
  @include grid-span(3, 4);

  @include breakpoint(700px) {
    @include grid-span(1, 1);
  }
}

.main {
  @include grid-span(6, 7);

  @include breakpoint(700px) {
    @include grid-span(1, 2);
  }
}

.second {
  @include grid-span(3, 1);

  @include breakpoint(700px) {
    @include grid-span(1, 3);
  }
}

Responsive Grid Context - Display

Nested Grids - HTML

<body>
  <div class="main">
    <div class="one">One</div>
    <div class="two">Two</div>
    <div class="three">
      <div class="a">Three A</div>
      <div class="b">Three B</div>
      <div class="c">Three C</div>
    </div>
    <div class="four">Four</div>
  </div>
  <div class="first">First Section</div>
  <div class="second">Second Section</div>
</body>

Nested Grids (Outer Grid) - Sass

@include add-grid(2 8 2);
@include add-gutter(1/3);

.first {
  @include grid-span(1, 1);
}

.main {
  @include grid-span(1, 2);
}

.second {
  @include grid-span(1, 3);
}

Nested Grid (Outer Grid) - Display

Nested Grids, Outer Grid

Nested Grids (First Nesting) - Sass

@include layout(8) {
	.one {
	  @include grid-span(1, 1);
	}

	.two {
	  @include grid-span(1, 8);
	}

	.three {
	  @include grid-span(6, 2);
	}

	.four {
	  @include grid-span(2, 4);
	  clear: both;
	 }
}

Nested Grid (First Nesting) - Display

Nested Grids, First Nesting

Nested Grids (Second Nesting) - Sass

@include layout(6) {
	.a {
	  @include grid-span(2, 3);
	}

	.b {
	  @include grid-span(2, 5);
	}

	.c {
	  @include grid-span(2, 1);
	}
}

Nested Grid (Second Nesting) - Display

Nested Grids, Second Nesting

Fluid Media

Toolkit

gem 'toolkit', '~>2.0.0.alpha.7'
require 'toolkit'
@import 'toolkit';

Basic Fluid Media

// Making images and HTML5 video fluid is pretty easy.

img, video {
	max-width: 100%;
	height: auto;
}

Intrinsic Ratios - Sass

// Using [Intrinisc Ratios](http://alistapart.com/article/creating-intrinsic-ratios-for-video), you can even make embedded videos fluid!

.fluid-16-9 {
  @include intrinsic-ratio;
}
.fluid-4-3 {
	@include intrinsic-ratio(4/3);
}
<body>
  <div class="fluid-16-9">
    <iframe width="560" height="315" src="http://www.youtube.com/embed/hHloF85dQZg?rel=0" frameborder="0" allowfullscreen></iframe>
  </div>
</body>

Intrinsic Ratios - CSS

/* Intrinsic Ratio code is built for a small code footprint, so shared code is extended. */
.fluid-16-9, .fluid-4-3 {
  position: relative;
  height: 0;
}

.fluid-16-9 > *, .fluid-4-3 > * {
  display: block;
  position: absolute;
  width: 100% !important;
  height: 100% !important;
  top: 0;
  margin: 0;
  padding: 0;
}

.fluid-16-9 {
  padding-top: 56.25%;
  width: 100%;
}

.fluid-4-3 {
  padding-top: 75%;
  width: 100%;
}

Putting It All Together

Did I Mention?

Everything you just saw? Yah, it's backend independent. You can use it anywhere, with anything, for any project. Sass Rocks

Thank You

Slides available at

http://snugug.github.io/RWD-with-Sass-Compass/