Drupal Meets Sass: Getting Started With Aurora (Part 3)

Mike Crittenden, Software Architect
#Drupal | Posted

If you're just now joining us, you might want to breeze through Part 1 and Part 2 of my Series on Sass, to catch up. And away we go...

Our friend Oliver has a serious problem--his organic olive oil oatmeal business is exploding and his phone is ringing off the hook. So he decided to put together an online order form so that he's not on the phone taking orders at all hours, and he asks you to theme it for him. The catch is that he needs it done yesterday. And the second catch is that it needs to be responsive.

So naturally you turn to Aurora, the only base theme that comes with time travel built in. But where to start?

What we're working with

I always find it helpful to build the basic layout before anything else, so that as you style things, they're already in kinda-sorta the right position instead of one super wide ugly column.

So we need to build a grid that matches the wireframes that Oliver gave to us. Here's how the layout should behave on the desktop:

  1. =================================================
  2. |  SIDEBAR  |        CONTENT        |  SIDEBAR  |
  3. |           |                       |           |
  4. |           |                       |           |
  5. |           |                       |           |
  6. |           |                       |           |
  7. |           |                       |           |
  8. |           |                       |           |
  9. |           |                       |           |
  10. |           |                       |           |
  11. |           |                       |           |
  12. |           |                       |           |
  13. =================================================

And on tablets, we get two columns over one.:

  1. =====================================
  2. |     SIDEBAR     |     CONTENT     |
  3. |                 |                 |
  4. |                 |                 |
  5. |                 |                 |
  6. |                 |                 |
  7. |                 |                 |
  8. =====================================
  9. |              SIDEBAR              |
  10. |                                   |
  11. |                                   |
  12. |                                   |
  13. =====================================

And on mobile, we drop down to a single column layout:

  1. =========================
  2. |        SIDEBAR        |
  3. |                       |
  4. |                       |
  5. |                       |
  6. =========================
  7. |        CONTENT        |
  8. |                       |
  9. |                       |
  10. |                       |
  11. =========================
  12. |        SIDEBAR        |
  13. |                       |
  14. |                       |
  15. |                       |
  16. =========================

Grid it together!

To build this layout, we'll make use of two things, both of which are bundled with Aurora.

  • Singularity, the Sassy grid system that Aurora prefers.
  • Breakpoint, a mixin which lets you include media queries without breaking a sweat.

Breakpoint is the easiest to understand so we'll take a look at that first. Here's a generic looking bit of CSS (NOT Sass) that we'll use as an example:

  1. .sidebar {
  2.   width: 100%; /* Full width on mobile */
  3. }
  4. @media (min-width : 768px) and (max-width : 1024px) {
  5.   .sidebar {
  6.     width: 400px; /* Fixed width for tablets */
  7.   }
  8. }
  9. @media (min-width : 1025px) {
  10.   .sidebar {
  11.     width: 25%; /* Fluid width for desktop */
  12.   }
  13. }

So here we have a basic mobile-first CSS snippet that tells the browser what width the sidebar should be at different resolutions. Specifically, full width on mobile, fixed width on tablets, and fluid width on desktop.

Now, when we convert this to Sass and make use of the Breakpoint mixin, it looks like this:

  1. // Set up our variables in _variables.scss.
  2. $tablet: 768px 1024px;
  3. $desktop: 1025px;
  5. // Set up your layout where you like layout rules.
  6. // I prefer separate files under a custom sass/partials/_layout folder.
  7. .sidebar {
  8.   width: 100%;
  9.   @include breakpoint($tablet) {
  10.     width: 400px;
  11.   }
  12.   @include breakpoint($desktop) {
  13.     width: 25%;
  14.   }
  15. }

Not only is this a lot cleaner and more easily readable, but it's also a lot more maintainable since you're not hardcoding media query resolutions all over the place.

So that handles media queries. Now how about the grid? This is where things get a little interesting.

Using the wireframes above, we first need to tell Singularity how many columns we want per-layout, like so:

  1. $grids: 1;  // Mobile 
  2. $grids: add-grid(2 at 768px); // Tablet
  3. $grids: add-grid(1 3 1 at 1024px); // Desktop

As you can (maybe not) see, the $grids property tells Singularity how to set up our grids. If you give it a single number, it just creates that many equal width columns. If you give it multiple numbers, it creates one column per number, and uses the numbers to determine the relational size between them.

Confused yet? Basically, this just means that if you want a symmetric grid, just tell it how many columns you want. If you want an asymmetric grid, you give it one number per column, where the number is the same as the width of that column compared to the others. So in our desktop example, we said "1 3 1" which means create 3 columns, where the first and third are 1/5 of the total width, and the middle one is 3/5 of the total width.

Also of note is the fact that we default to the mobile layout and then add in grids for tablet and desktop resolutions since we're going with mobile first. If you want bonus points, you can use the $tablet and $desktop variables created earlier in the "Breakpoint" example here instead of hardcoding widths.

So now that Singularity knows about our columns, what about the gutters? This part's easy. Just tell it how big the gutter should be in relation to a single column. So if you want the gutter to be 1/4 the size of a single column, you just need to say:

$gutters: 1/4;

That gives us the foundation for our grid. Now how about actually putting content into it? This is where the "grid-span" mixin comes into play.

Let's say that the markup for our page is just a basic 3-div setup (realistically, it will match whatever you set up in page.tpl.php), then to get our desktop layout, all we'd have to do is this:

  1. @include breakpoint($desktop) {
  2.   .sidebar-first {
  3.     @include grid-span (1, 1);
  4.   }
  5.   .content {
  6.     @include grid-span (1, 2);
  7.   }
  8.   .sidebar-last {
  9.     @include grid-span (1, 3);
  10.   }
  11. }

The first number you pass into grid-span() tells it how many columns you'd like that element to span, and the second number tells it which column you want it to start on. So since we're basically working with a 5-column 1-3-1 layout on the desktop, we tell Singularity to let the sidebars span the first and last column, and that the content should fill in the space between them.

And of course, since we're interested in responsiveness, we'll need to add rules for tablet and mobile. Here's what the whole shabang looks like when you smush it together.

  1. // _variables.scss
  2. $grids: 1  // Mobile 
  3. $grids: add-grid(2 at 768px) // Tablet
  4. $grids: add-grid(1 3 1 at 1024px) // Desktop
  5. $gutters: 1/4;
  7. // _layout.scss (or something like it)
  8. .sidebar-first {
  9.   @include grid-span (1, 1); /* Mobile/Desktop/Tablet */
  10. }
  11. .content {
  12.   @include grid-span (1, 1); /* Mobile */
  13.   @include breakpoint($tablet) {
  14.     @include grid-span (1, 2); /* Tablet */
  15.   }
  16.   @include breakpoint($desktop) {
  17.     @include grid-span (1, 2); /* Desktop */
  18.   }
  19. }
  20. .sidebar-last {
  21.   @include grid-span (1, 1); /* Mobile */
  22.   @include breakpoint($tablet) {
  23.     @include grid-span (2, 1); /* Tablet */
  24.   }
  25.   @include breakpoint($desktop) {
  26.     @include grid-span (1, 3); /* Desktop */
  27.   }
  28. }

And there you have it. A responsive, custom (even asymmetric!) grid with three breakpoints and we still have all our hair!

Very Vicious Variables

With the grid set up, let's throw in some variables so that we can reuse them when we're coding the actual design.

So open up sass/partials/_variables.scss. In our case, since Oliver's one page signup form is pretty simple, we basically only need to store the font stacks and colors we're using so that we can reference them later without hardcoding anything. Luckily, Aurora already comes with some nice font stacks by default in _variables.scss:

  1. $times-new-roman: "Times New Roman", Times, Georgia, "DejaVu Serif", serif;
  2. $times: Times, "Times New Roman", Georgia, "DejaVu Serif", serif;
  3. $georgia: Georgia, "Times New Roman", "DejaVu Serif", serif;
  4. $verdana: Verdana, Tahoma, "DejaVu Sans", sans-serif;
  5. $tahoma: Tahoma, Verdana, "DejaVu Sans", sans-serif;
  6. $helvetica: Helvetica, Arial, "Nimbus Sans L", sans-serif;
  7. $arial: Arial, Helvetica, "Nimbus Sans L", sans-serif;

So all we need to do is tell Aurora that we want to default to the $georgia stack (a web-serif that matches Oliver's earthy brand), and we can do that a little farther down by changing the $font-body property to $georgia. While we're at it, let's make sure that forms use a nice Arial based stack so that they stand out a bit.

  1. $font-body: $georgia;
  2. $form-font-family: $arial;

So that gets our fonts in order. Let's add some color. Oliver's brand only has three colors:

  • Light gray (#AAA)
  • Dark gray (#333)
  • Earthy tan (#F2ECCC)

A few lines below the font variables we can see some color variables which hold default branding colors for some popular sites (YouTube, Facebook, etc.) and we can add our colors there like so:

  1. $color-tan: #F2ECCC;
  2. $color-lightgray: #AAA;
  3. $color-darkgray: #333;

Devilish Defaults

That does it for the variables, so we can move on to some default styles for actual elements. For example, we have a form, so let's set up some default form styles. Open up sass/partials/global/_forms.scss and add some basic input styling.

  1. input,
  2. button,
  3. select,
  4. label,
  5. textarea {
  6. font-family: $form-font-family;
  7. }
  8. textarea {
  9. height: 10em;
  10. }
  11. label {
  12. display: block;
  13. margin-top: 20px;
  14. font-weight: bold;
  15. text-transform: uppercase;
  16. }
  17. input[type="text"],
  18. input[type="password"],
  19. input[type="email"],
  20. textarea,
  21. select {
  22. border: 1px solid $color-tan;
  23. outline: none;
  24. font-size: 16px;
  25. margin-top: 10px;
  26. padding: 5px;
  27. &:focus {
  28. border: 1px solid $color-darkgray;
  29. }
  30. }

Rinse and repeat for any other default elements that need styling. For example, set up some default heading styles (in the <h1> through </h6> sense of the word) in sass/partials/globals/_type.scss, or style tables in sass/partials/globals/_defaults.scss. You may also want to set up some reusable utility classes  like "pull-right" or "no-pad" in sass/partials/globals/_extendables.scss, according to your preferences.

Section Directions

So you have your grid, you have your default styles, and you have variables set up to re-use elsewhere. Now you can finally style the individual site sections and make everything look pretty.

Starting with the header, let's go with a full width black bar with the logo text on the left and a nav menu on the right. So after putting the site name's <h1> and the nav menu's block in the header region, like you would with any other theme, you'll want to create a new file for this section's styles.

Remember that designey section-specific styles go into the sass/partials/design directory, so open up sass/partials/design/_design.scss and you'll find yourself staring at an empty file. Rather than adding code right there, let's split it up a bit. Add a line to _design.scss which tells it to include a new header design file.

@import 'header';

Now let's create sass/partials/design/_header.scss. Try this on for size:

  1. #header {
  2. background: $color-darkgray;
  3. width: 100%;
  4. overflow: hidden;
  5. h2 {
  6. margin: 0;.
  7. padding: 0;
  8. float: left;
  9. font-size: 30px;
  10. color: white;
  11. font-weight: normal;
  12. margin: 10px;
  13. }
  14. ul {
  15. float: right;
  16. margin: 17px 10px 10px;
  17. li {
  18. display: inline;
  19. padding: 0 10px;
  20. a {
  21. color: $color-lightgray;
  22. text-decoration: none;
  23. text-transform: uppercase;
  24. font-weight: bold;
  25. font-size: 16px;
  26. font-family: $form-font-family; // Use sans-serif for the nav, and match the form fonts.
  27. &:hover {
  28. color: $color-tan;
  29. }
  30. }
  31. }
  32. }
  33. }

And there's our header. I won't bore you with the gritty details of doing this for the other sections, but the process is always the same:

  1. Create a new file inside sass/partials/design/ named after your section
  2. Add the new file's name to sass/partials/design/_design.scss as an include
  3. Put your super sweet section-specific styles into your new file

Committin' And Quittin' Time

So you've done a solid day's theming and you have a newfound love of Aurora. Oh joy! Now you're ready to commit your changes to version control so that Oliver can check them out. (You are using version control, right?)

There's a bit of a debate on whether you should commit the compiled CSS into your repository or have it auto-generate on the server instead. In fact, heavyweights Sam Richard (Aurora's creator) and John Albin (Zen's creator) don't even see eye to eye on it. Both approaches have their pros and cons, so it's really a personal decision.

If you decide to commit your generated CSS then you don't have to worry about adding a server-side build to compile it for you--it's one less thing to worry about, especially if you're dealing with multiple environments. On the other hand, if you only commit your Sass and let the server compile the CSS, then you can rest assured that there is one final source of truth in the CSS (i.e., whatever the server itself compiles) rather than whatever everyone's Compass versions/configs decide to spit out, and this avoids some would-be merge conflicts and keeps your repo clean and tidy.

Whatever you decide, make sure that your entire team is on the same page about it.

Wrapping up

You rock! Oliver's new site looks great and you knocked out the theme in an afternoon. Plus, since you kept everything neatly organized with Aurora's standards and made use of variables, it'll be easy to add to or alter stuff whenever Oliver comes along asking for a new and different order form for his new "Oliver's Organic Olive Oil Oatmeal On Ostrich (Or Owl)" line of products, and if the "O's OOOOOO(OO)" request is like most client requests, then it'll need to be quick!  If you missed my first two blog posts about Sass, check them out!

Mike Crittenden

Mike Crittenden

Software Architect