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!

 

Front-End Developer