Susy and Media Queries (guide for Muppets)

3,314 views
Skip to first unread message

Suleiman Leadbitter

unread,
Jun 10, 2012, 6:52:07 PM6/10/12
to compas...@googlegroups.com
I'll keep this brief, I have been trying to get my head around using Susy and media queries to change a sites style for tablet and phone but for some reason I have a numb brain regarding this.

Seriously, in s..l...o...w terms, could someone explain how I add in the code to start the media queries and also to change the amount of columns.

Sorry to sound stoopid :P

Neal Sheeran

unread,
Jun 11, 2012, 1:00:08 AM6/11/12
to compas...@googlegroups.com
There is a pretty good demo on the Susy site for creating media queries: http://susy.oddbird.net/demos/magic/

It is a "mobile first" demo - meaning that the baseline styles start with a narrow viewport and then columns are added for wider displays. I followed this demo almost to the letter with a site that starts with 4 columns and then goes up to 8 and 12. My setup is something like this:

// My Variables:
$total-columns  : 4;
$column-width   : 4em;
$gutter-width   : 1.5em;
$grid-padding   : $gutter-width;

$break-1        : 8;
$break-2        : 12;

Those "break" variables are just where I want the media queries to occur. If the display is wide enough to display 8 columns, then do so. Wide enough for 12, then do that. This next line pretty much sets up my three media queries - I followed the tutorial above:

#wrap {
  @include container ($total-columns, $break-1, $break-2);
}

This SASS/Susy line will create the following CSS:

#wrap {
  *zoom: 1;
  max-width: 20.5em;
  _width: 20.5em;
  margin-left: auto;
  margin-right: auto;
  padding-left: 1.5em;
  padding-right: 1.5em; }
  #wrap:after {
    content: "";
    display: table;
    clear: both; }

/*-- Insert styles for my "default/narrow" layout here -- */

  @media (min-width: 45.5em) {
    #wrap {
      max-width: 42.5em;
      _width: 42.5em; } }

  @media (min-width: 67.5em) {
    #wrap {
      max-width: 64.5em;
      _width: 64.5em; } }

My three media queries are right there. The default 4  column, and one each for 8 (min-width: 45.5 ems) and 12 ((min-width: 67.5em). Then I defined the styles for the 8 and 12 column versions like so:

@include at-breakpoint($break-1)  {

/* -- All the styles for 8 columns go here ($break-1 = 8...see my variables above) --*/

}

@include at-breakpoint($break-2)  {

/* -- All the styles for 12 columns go here ($break-2 = 12...see my variables above) --*/

}

And that is all I did. Again, this method assumes you are starting from a mobile layout first and then building up. My originial plan was to start at a large desktop size and then scale down with queries, but since this tutorial (and a lot of web designers I follow) preach a "mobile first" philosophy, that's what I did. I actually found it easier this way, since a narrow display is going to drive a simple layout, and then get more complex as the display allows for more room.

There are different ways to define your actual media queries (per the Susy reference documentation), but this worked perfectly for me, as I'm no expert either.

If you haven't read Ethan Marcotte's original book, Responsive Web Design, I highly recommend it.

v/r,
Neal


Suleiman Leadbitter

unread,
Jun 11, 2012, 9:15:02 AM6/11/12
to compas...@googlegroups.com
Seriously and massive thank you Neal.

One quick question though. Where you have wrote @media (min-width: 45.5em) and @media (min-width: 67.5em) I have previously been working with pixels, so say 320px and 480px etc. How did you know the size in em's also does it change depending on your base-font-size?

Neal Sheeran

unread,
Jun 11, 2012, 11:24:26 AM6/11/12
to compas...@googlegroups.com
I did not write that, Susy + SASS figured it out. To answer your second question first: Yes, ems depend on font-size. The browser default should be 16px. Hence 1 em = 16px. Looking at my example variables above, the first media query looks for the earliest width I can use 8 columns, which results in: @media (min-width: 45.5em) Susy calculated it this way:

8 columns * 4ems per columns  = 32.0 ems
7 gutters * 1.5ems per gutter = 10.5 ems
Total width of the container  = 42.5 ems (same as the max-width)

Since my grid padding is the same as my gutter width (which is 1.5 em), there is 1.5ems of padding on each side of the container. So 2 * 1.5 = 3.0 ems. Add those three to 42.5 and you get the media query looking for a minimum width of 45.5 ems. When the viewport gets that big, then all of the styles contained within the query are then applied. If I wanted to know what the pixel equivalent of that, just multiply the ems by the pixel size: 45.5ems * 16 = 728px

I wasn't completely clear in my example. By writing this:

#wrap {
  @include container ($total-columns, $break-1, $break-2);
}

Susy then does all the math and builds the CSS required for the initial container and all the media queries for it -- the long block of CSS above. Then I put my width-specific styles in the following block:

@include at-breakpoint($break-1)  {

/* -- All the styles for 8 columns go here ($break-1 = 8...see my variables above) --*/

}

And then Susy will do the rest. I recommend using the tutorial on the Susy site with a very basic page, using your desired pixel values and then go look at the resulting CSS that it spits out. It helped me. I use a separate partial .scss file called "layout.scss" that does nothing but set the initial container with three breakpoints (I added one since my last message), the basic layout that applies to the default narrow layout defined by my initial variables, and then the layout changes that apply within the three media queries. No typography, no colors or any of that. Those live in their own partials. Makes changing layout (or typography, or color) easy because they are all separated.

The benefit to using ems to size your fonts AND your grids is if the user increases the font-size in his browser, then the grids containers will all increase as well. If you size your grid in pixels, when the user increases the font-size, your grid won't change - text will grow in boxes that stay the same size. This may or not be a big deal depending on your layout.

Everything I've said applies equally if you use pixels for all of your grid settings. You would just use pixels as well to trigger your media queries that result in: @media (min-width: 768px) --> for all viewports at least 768px wide, do ABC. You can do the opposite way like this: @media (max-width: 768px) --> for all viewports smaller than 768px, do XYZ.

Sorry for the stream of consciousness...

Neal

Alan Hogan

unread,
Jun 11, 2012, 1:01:07 PM6/11/12
to compas...@googlegroups.com
On the Susy web site docs, it mentions you can configure the em-to-px ratio by setting a variable ($font-size maybe?) that Susy uses for these calculations.

--
You received this message because you are subscribed to the Google Groups "Compass" group.
To view this discussion on the web visit https://groups.google.com/d/msg/compass-users/-/yH4h1YWpFbMJ.
To post to this group, send email to compas...@googlegroups.com.
To unsubscribe from this group, send email to compass-user...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/compass-users?hl=en.

Suleiman Leadbitter

unread,
Jun 11, 2012, 3:55:13 PM6/11/12
to compas...@googlegroups.com
Thanks for your time dude. It's greatly appreciated. One more question. How do I change the amount of columns for different breakpoints?

I thought it was a case of:

$total-columns  : 4;              // a 4-column grid for Mobile First
$column-width   : 4em;            // each column is 4em wide
$gutter-width   : 1em;            // 1em gutters between columns
$grid-padding   : $gutter-width;  // grid-padding equal to gutters

$break-1: 6;
$break-2: 8;
$break-3: 12;

Where is has $break-1: 6; < that meant four columns and $break-3: 12; would use 12 columns. I'm resizing in Safari but it's still just showing the default 4 regardless of width.

Neal Sheeran

unread,
Jun 11, 2012, 6:10:01 PM6/11/12
to compas...@googlegroups.com
Are you displaying the the columns using the "@include susy-grid-background;" on your wrapper element? And if so, when you expand your Safari window, does the wrapper grow, but still just display the four columns, but wider?

My page did the same thing -- you have to do the following:

#wrap {
  @include container ($total-columns, $break-1, $break-2);
  
  @include susy-grid-background;

  @include at-breakpoint($break-1)  {
    @include susy-grid-background;
    }
  @include at-breakpoint($break-2)  {
    @include susy-grid-background;    
    }
}

The first @include susy-grid-background; (line 2 under wrap) sets your column background under your default 4 column layout. The next line,

@include at-breakpoint($break-1)  {
    @include susy-grid-background;
    }

... says that at your first media query (6 columns), it will redraw the columns (6). Just repeat for your $break-2, break-3. And your column background will redraw with more columns as your display widens.

Now, lets say you have some element, <div class="posts"> the contains some content. If you do nothing else, this div will be the full width of your "wrapper" at 4, 6, 8, etc columns. Lets say when the display widens to 6 columns, you want his div to be only 4 columns wide. Find the media query line that will contain your 6 column styles:

@include at-breakpoint($break-1)  {
    
}

And inside that Susy media query, write something like this:

@include at-breakpoint($break-1)  {
    .posts {
        @include span-columns(4, $break-1)
    }
    /* -- Rest of your 6 columns styles here -- */
}

Make sense? Then do the same thing for your other break variables. If you column problem is different than what I've described above, then I would need some more specific info.

v/r,
Neal

Suleiman Leadbitter

unread,
Jun 11, 2012, 8:36:00 PM6/11/12
to compas...@googlegroups.com
WOOOO!!!! Mate I would buy you a coffee if you was right here now (although it's now 1:35am so you would have to wait a few hours).

Thank you!!!!

Neal Sheeran

unread,
Jun 11, 2012, 9:22:30 PM6/11/12
to compas...@googlegroups.com
Glad I could help. I been messing around with for hours myself, learning as I go.

Cheers,
Neal

Suleiman Leadbitter

unread,
Jun 12, 2012, 2:53:09 PM6/12/12
to compas...@googlegroups.com
I'm so sorry about this, please if there is anything I can help you with (one day) I will.

I'm still confused about the em width malarkey.

So say I have a base-font of 14px how do I go about setting the columns and gutters to work on the iPhone, iPad (portrait and landscape), Desktop and Small Laptop. Basically widths of:

320px(iPhone portrait, default), 480px (iPhone landscape), 600px, 768px(iPad portrait), 900px, 1024px (iPad landscape), 1140+ (Desktops).

I was working with percentages before when I was using plain old CSS so this he screwed with my humble little brain :/

Suleiman Leadbitter

unread,
Jun 12, 2012, 3:49:06 PM6/12/12
to compas...@googlegroups.com
Ok I sort of getting it in the mathematics area.

So looking at your example above: 45.5 (em) x 16 (pixel font size) = 728 (px)

I just need to work out how to work backwards from that :P

Neal Sheeran

unread,
Jun 14, 2012, 11:36:24 AM6/14/12
to compas...@googlegroups.com
If it is important to your project to align your media queries to the portrait and landscape widths of the iPhone and iPad, you can easily set your variables to pixels and then do some math to figure out the pixel width of X columns. Using your previous example, but changing from ems to pixels:

$total-columns  : 4;              // a 4-column grid for Mobile First
$column-width   : 58px;           // * Changed to pixels *
$gutter-width   : 24px;           // * Changed to pixels *
$grid-padding   : $gutter-width;  // grid-padding equal to gutters

$break-1: 6;
$break-2: 8;
$break-3: 12;

Your min width in pixels for your 6 column layout ($break-1) would be:

(# of columns x column-width) + ((#of columns - 1) x gutter-width) + (2 x grid-padding)
= (6 x 58) + (5 x 24) + (2 x 24)
= 516 pixels.

So any display with a width less than 516 pixels would be four columns. 516 and up would then be 6 columns (until the min-wdth for your next $break, and then it would be 8, etc). So an iPhone (320 portrait, 480 landscape) would get 4 columns. An iPad portrait (768) would get six columns, etc. If you wanted to convert these pixel widths to ems, just divide them by the base font-size:

= 516 / 14 = 36.8 ems. 

If you want a specific column layout to occur for a specific device and orientation, say the iPad in landscape (1024...assuming non-Retina version 3), and you are using ems for variables, convert the desired device width to ems:

= 1024 / 14 (or whatever base font size you are using) = 73.1 ems. 

Then you could use Excel or Numbers and have your grid variables and base font size size defined in separate cells, and then some formulas that does the above equation and returns pixel and/or em values. Then just tweak your variables and see what the formula spits out. This is what I did when I wanted my 12 column layout to kick in for landscape iPads (1024px). With 4 em columns and 1.5em gutters, it wasn't happening. Why not? Because:

(12 x 4em) + ( 11 x 1.5em) + (3.0em) = 67.5 ems.

And my base font-size is 16 px, so 67.5 x 16 = 1080px = the min width for my 12 column layout...which is too wide for a landscape iPad. So I went to excel, tweaked the column width down to 3.7ems and it spit out 1022 pixels. Now landscape iPads will have 12 columns. 

Another tool I found helpful is the Resizer Safari Extension. It adds a toolbar with buttons that you can configure for any width and when you select one, it automatically sets the safari window to that width and you can see how your layout adapts. Set a button to 600 pixels wide, and then see if you get the columns you want. If not, tweak your variables until you do. Works way better than manually dragging the Safari window back and forth.

Cheers,
Neal

Eric Meyer

unread,
Jun 15, 2012, 2:16:17 AM6/15/12
to compas...@googlegroups.com
Neal, I owe you a drink as well. Thanks for helping out.

I'm wild busy this month, but glad to see people are catching on and helping each other.

Cheers to you both,
-e

Suleiman Leadbitter

unread,
Jun 15, 2012, 6:58:48 PM6/15/12
to compas...@googlegroups.com
Seriously dude you are awesome. I managed to get my head straight and figured out the solution just earlier today. I was having a tense stressful week and I think I was making it worse by over thinking this whole thing. That is me just securing any dignity I had left :P

I never thought of the Excel formulas though, that is genius dude.

Once more, thank you. I hope others see this thread and it helps them out also.

Neal Sheeran

unread,
Jun 15, 2012, 7:03:37 PM6/15/12
to compas...@googlegroups.com
I copied your example into a file and it seemed to work for me. When you say the mobile jumps back to 12, are you referring to the susy grid background? With your settings, I did this:

#page {
  @include container ($total-columns, $tablet, $mobile )
}

#page {
  @include susy-grid-background;

  @include at-breakpoint($tablet) {
    @include susy-grid-background;
  }
  @include at-breakpoint($mobile) {
    @include susy-grid-background;
  }
}

And it worked. If you are using susy-grid-background, you need to do it for each breakpoint.

Neal Sheeran

unread,
Jun 15, 2012, 7:45:47 PM6/15/12
to compas...@googlegroups.com
Steve - My replies are below:

This has been helpful, thanks.  

I need to define my layouts starting from the desktop, though, since that's what the designers built.

So I am building it with 12 columns for >768px, 8 columns > 340px, and then 4 columns for mobile.

How would this modify what you have above?

Looks like your example in the next post works out fine. 

 
Also, do all your css selectors need to be children of the wrapping container?  You have it like that and so does the "magic" demo, but I want to check.

You'll want all of your css selectors for default desktop width to be right after your initial include that sets the container. Using your example:

#wrap { @include container ($total-columns, $tablet, $mobile ) 

/* -- All your full-width styles go here --*/

Then you define your tablet styles like this:

@include at-breakpoint($tablet) {

/* Then put all you styles for your 8-column width inside this block */

}

And then do the same for your mobile styles:

@include at-breakpoint($mobile) {

/* Then put all you styles for your 4-column width inside this block */

}

And I notice none of your breakpoints specify a width of any kind; is this because Susy just determines what will "fit" at your column width/margin?

I believe that is correct. 

Lastly, can you please expand upon the syntax of @include container ($total-columns, $break-1, $break-2); ? Is it just that you include this include once on the selector that's going to be the container? This part has me a bit confused.  Thanks.

Yes, you need to just have that one include as a rule for your "containing element". Using your example below:

#page { @include container($total-columns, $tablet, $mobile);}
 
... the CSS it then produces is this:

#page {
  *zoom: 1;
  max-width: 60.3em;
  _width: 60.3em;
  margin-left: auto;
  margin-right: auto;
  padding-left: 1.5em;
  padding-right: 1.5em;
}

---> The above sets the max width of your container according to your default variables (12 columns of 3.65em)

#page:after {
  content: "";
  display: table;
  clear: both;
}

@media (max-width: 50em) {
  #page {
    max-width: 39.7em;
    _width: 39.7em;
  }
}
---> The above changes the max-width to be 39.7ems when the viewport is 50em or less (your $tablet settings)


@media (max-width: 30em) {
  #page {
    max-width: 19.1em;
    _width: 19.1em;
  }
---> The above changes the max-width to be 19.1ems when the viewport is 30em or less (your $mobile settings)

And that is all it does - change the size of the containing element at the specific breakpoints you specify. Again, you modify what happens to HTML elements  within the container at those break points as follows:

@include at-breakpoint($tablet) {
    .content { @include span-columns (5, %tablet); ---> Makes div.content 5 columns wide, floated left
    .sidebar { @include span-columns (3 omega, $tablet) ---> makes div.sidebar 3 columns, floated right.
}

Then do same for the mobile breakpoint.

On Tuesday, June 12, 2012 8:59:51 PM UTC+9, Steve Lombardi wrote:
This has been helpful, thanks.  

I need to define my layouts starting from the desktop, though, since that's what the designers built.

So I am building it with 12 columns for >768px, 8 columns > 340px, and then 4 columns for mobile.

How would this modify what you have above?

Also, do all your css selectors need to be children of the wrapping container?  You have it like that and so does the "magic" demo, but I want to check.

And I notice none of your breakpoints specify a width of any kind; is this because Susy just determines what will "fit" at your column width/margin?

Lastly, can you please expand upon the syntax of @include container ($total-columns, $break-1, $break-2); ? Is it just that you include this include once on the selector that's going to be the container? This part has me a bit confused.  Thanks.

Suleiman Leadbitter

unread,
Jun 16, 2012, 6:05:15 AM6/16/12
to compas...@googlegroups.com
This is purely for reference is it helps anyone else then cool :)

I still need to add in some of the breakpoints but my screen.scss looks a little like this now:

@import "susy";

$total-columns  : 4;              // a 4-column grid for Mobile First
$column-width   : 3.8em;          // each column is 3.8em wide
$gutter-width   : 1.5em;          // 1em gutters between columns
$grid-padding   : $gutter-width;  // grid-padding equal to gutters

$break-1 : 6; //
$break-2 : 8; // iPad (Portrait) 728
$break-3 : 12; //

// Font Sizes

$relative-font-sizing : true;
$base-font-size       : 14px;
$base-line-height     : 20px;

$default-rhythm-border-style: solid;


// General Layout Elements
@import 'partials/layout';

// Media Queries
@import 'partials/media-queries';



//   Notes
//   ==========================================================
//
//   Default start off style 320
//
//   320px Gutters = 1.5em(21px)  Columns(4) = 3.8em(53.75px) // Smartphone Portrait 
//   480px Gutters = 1.5em(21px)  Columns(6) = 3.9em(55.5px) // Smartphone Landscape
//   600px Gutters = 1.5em(21px)  Columns(6) = 5.39em(75.5px) // Small Tablet
//   768px Gutters = 1.5em(21px)  Columns(6) = 7.39em(53.75px) // Tablet Portrait
//   992px Gutters = 1.5em(21px)  Columns(8) = 7.16em(100.375px) // Netbooks
//   1382px Gutters = 1.5em(21px)  Columns(12) = 6.6em(92.41px) // Desktops and Widescreen laptops
//
//

Suleiman Leadbitter

unread,
Jun 16, 2012, 6:08:20 AM6/16/12
to compas...@googlegroups.com
Also if you use Photoshop then this amazing extension really helps out to make the grids spot on. Guide Guide is an amazing time saver.

Steve Lombardi

unread,
Jun 21, 2012, 1:08:00 PM6/21/12
to compas...@googlegroups.com
Thanks. My one remaining issue is that although everything seems to work fine, at the $phone size, defined as

$phone: 4 35em;

I get the 4 columns, but the width of the layout does not "fill" the width of the phone screen.  It's flush left and there is a gutter on the right; not good.

I tried setting a meta-viewport tag device-width initial zoom=1, which fixed the width in portrait, but then the whole layout would "jump" to the right when rotated to landscape (both in phone AND tablet.  Removing initial zoom=1 fixed the jump, but now my layout is too narrow for the viewport.  What am I missing here?


Reply all
Reply to author
Forward
0 new messages