Skip to main content

Responsive Layouts with Zen 5.x

Using Zen 5.x as a base theme for DrupalCon Sydney's website introduced me to a new approach to theming that other Drupal themers may find useful. The theme makes responsive Drupal layouts easier by combining the old Zen sidebar magic with Sass and Compass by way of Zen Grids. You can further improve your theming process with new functionality in Sass 3.2.

by Robert Caracaus /

Sass 3.2 Media Query Mixin

The new version of Sass has a solution to make your media queries more semantic. Zen has an issue to include these easier-to-read media query mixins, however it hasn't yet, so I manually included the mixin in my theme. I have included an example below for your convenience. Meet the respond-to() mixin. It lets you turn this:

@media all and (min-width: 480px) and (max-width: 959px) { MY AMAZING STUFF }

Into this:

@include respond-to(medium-screens) { MY AMAZING STUFF }

Now your responsive CSS can be semantically separated:

@include respond-to(handhelds) { MOBILE-LAYOUT-CODE }

@include respond-to(medium-screens) { TABLET-LAYOUT-CODE }

@include respond-to(wide-screens) { DESKTOP-LAYOUT-CODE }

Using the respond-to() mixins throughout your stylesheet allows you to theme complex responsive elements much easier. The actual respond-to() mixin is demonstrated below, I also add my breakpoints as variables in case I need to use them again. You need Sass 3.2 for the mixin below to work.

$break-small: 720px;
$break-large: 960px;

@mixin respond-to($media) {
 @if $media == handhelds {
   @media only screen and (max-width: $break-small) { @content; }
 }
 @else if $media == medium-screens {
   @media only screen and (min-width: $break-small + 1) and (max-width: $break-large - 1) { @content; }
 }
 @else if $media == wide-screens {
   @media only screen and (min-width: $break-large) { @content; }
 }
 @else if $media == both-screens {
   @media only screen and (min-width: $break-small) { @content; }
 }
}

If you are using a mobile-first approach then you may not need the "handheld" respond-to() mixin. Also, there is a Compass extension called "Breakpoint" that may be a better alternative to the above technique.

Zen Grids

The Zen Grids sass-extension is included in your Zen subtheme and gives you the power to create fluid, percentage-based grids on the fly. You can specify how many columns you want use and it does all the math for you. Steering away from manually-set pixel sizes will make you layout more flexible. Zen Grids does the clear, float, and sizing CSS magic required to make grids for you.

The $zen-column-count will give every grid item called after it a percentage width of 1/$zen-column-count (for example: $zen-column-count = 3 = width:33.33%)

The zen-grid-item() mixins allow us to specify size and placement of individual grid items. For instance we can place a sidebar to the right that spans one column and a content area to the left that spans two columns. See example below:

$zen-column-count = 3
.sidebar-second {
  
#content { /* Span 2 columns, starting in 1st column from left. */
      @include zen-grid-item(2, 1);
    }
    .region-sidebar-second { /* Span 1 column, starting in 3rd column from left. */
      @include zen-grid-item(1, 3);
    }
}

All layout code is located in the layout/responsive-sidebars.scss folder within your sub-theme, this is where the Zen layout magic happens. The sidebar code in responsive-sidebars.scss works similar to older versions of Zen. It basically allows you to have different layouts for different sidebar scenarios. Zen gives the <div> that surrounds your content and sidebar(s) a class. 

<div class=”MAGIC-CLASS”>
[First Sidebar Div] [Content Div] [Second Sidebar Div]
</div>

If the first column exists, Zen generates a “sidebar-first” class. If the second column exist Zen generates a “sidebar-second” class, if BOTH columns exist zen generates a “sidebar-both” class. The reason these columns are named first and second, and not left and right is because you can actually float these divs right or left depending on the order you want them to display when they collapse.

.sidebar-first { LAYOUT-CODE }
.sidebar-second { LAYOUT-CODE  }
.sidebar-both { LAYOUT-CODE }

A layout with blocks only enabled in the .region-sidebar-second region would look like this.

.sidebar-second {
  
#content { /* Span 2 columns, starting in 1st column from left. */
      @include zen-grid-item(2, 1);
    }

    .region-sidebar-second { /* Span 1 column, starting in 3rd column from left. */
      @include zen-grid-item(1, 3);
    }
}

If you want different layouts for different sidebar/display scenarios, your layout code can become a little more complicated, especially if you want different column counts on each display. Check out a more complete example below where I tell Zen "for medium-screens, divide a layout into three columns, display a sidebar on the right that spans one column".

$zen-column-count = 3
@include respond-to(medium-screens) {
     .sidebar-second {
      #content { /* Span 2 columns, starting in 1st column from left. */
               @include zen-grid-item(2, 1);
           }
           .region-sidebar-second { /* Span 1 column, starting in 3rd column from left. */
                @include zen-grid-item(1, 3);
           }
     }
}

You can repeat these layout rules throught your responsive-sidebars.scss file to match any display or sidebar scenario you can imagine.

Cool new responsive layout tools are only the beginning of what you can do with Zen 5.x:

  • The theme's cutom implementation of normalize.scss, Vertical Rhythm, and the default Compass styling of core Drupal elements give you a headstart with consistency and typography. 
  • Conditional stylesheets and RTL support give make browser and language support easier. 
  • Drush support makes setting up a subtheme from Zen's starterkit a flash.
  • Last but not least, Zen was one of Drupal's first base themes to make the accessibility pledge, and has mixins and tools like the Skip Link to make themes easier to use for impaired users.

Zen doesn't just make themers' lives easier, its documentation and processes teach people new to Drupal the Sass way to build Drupal themes. If you have any more tips to offer, better way to do things, or questions about my explaination above, leave a comment!

 

Posted by Robert Caracaus
Front-End Developer

Dated

Comments

Comment by Anonymous

Dated

is it a built-in feature of zen 5.x for the navigation menu turned into drop-down list box ?

Comment by DrupalBoy

Dated

Great post! Loved reading it.

Comment by thamas

Dated

It seems that you used fluid grids inside static fixed width wrappers at the DC Sydney site. Would you share the ideas and reasons of this solution. It would be also good to see the source the real layout scss that you use at the site, of course just in that case if it is not Top Swecret! ;o)

One more interesting topic to talk about is the method of Zen using touching layout elements. I thin, you used wrapper divs too to have the needed gutters. Am I right? Would you write the concept of it?

Comment by Robert Caracaus

Dated

@thamas.. the reason I used fluid grid inside fixed wrappers is because.

A) When you shrink down to 720px (i think) the layout becomes fluid.

B) I started theming with Zen's fluid layout css file. Not the fixed one.

I thin, you used wrapper divs too to have the needed gutters. > I think ZenGrids handles the gutters for you. You can set a variable that sets the gutter size.

Comment by thamas

Dated

@Robert
"… the source, they can download …" - Vow, I didn't know, thanks for the information!

"I think ZenGrids handles the gutters for you." When I talked about the wrapper (and inner) divs, I was think to this problem: http://drupal.org/node/1593842

Comment by CPJ

Dated

How can one make an fixed width item followed by some inline responsive items and still the grid work correctly?

Pagination

Add new comment

Restricted HTML

  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd> <h2> <h3> <h4> <h5> <h6>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.
Not sure where to start? Try typing "hello" or "help" if you get stuck.