Twitter Bootstrap – How to Style Rows
There is a lot of great things going on with the new CSS framework from Twitter, Bootstrap -> http://twitter.github.com/bootstrap/. I used 1.0 for creating this site and a few others. Version 2.0 was just released and it fixed a lot of issues and is really just plain awesome.
Unfortunately, there have been a few things that have been bothering me about it, particularly the grid system. I felt constrained by the requirement of a containing .row around the spans. I couldn’t quite put a finger on what it was though. Then after doing a project with Blueprint -> http://blueprintcss.org/ last month, it hit me. In Bootstrap, you can’t style rows.
Bootstrap’s grid system will use left-margin in between columns to have built in padding between content areas. By default, it is 20px. Everyone does this. The problem that happens though is that the first column can’t have any left-margin or your content won’t be centered. (And likely be over 960px) To get around this, most frameworks will nip off the left-margin on the first column by using a pseudo css selector: first-child.
Boostrap uses a different technique. It places a negative left-margin on the containing .row instead of using a pseudo class. For the following markup, imagine we want to put a border around the row:
<div class="container"> <div class="row"> <div class="span6"></div> <div class="span6"></div> </div> </div>
Notice how the row in the above illustration sticks out past the .container element?
Their reason for this is valid. :first-child causes problems with calculating widths and makes things more complicated. But using a .row with negative left-margin means that any styling applied to the row (borders, backgrounds, etc) will stick out on the left hand side by an extra 20px. In the simplest case illustrated above, this is exactly how it occurs in your page.
So how do we fix this?
Simple. Add a <div> or HTML5 element like <article> or <section> as a parent to the row. Then style the parent element. Because of the .container that is used for the entire page, this div will be the appropriate width. When using a <section> tag, it even feels right, semantically. So, yay!
Here we have the fix:
<div class="container"> <section> <div class="row"> <div class="span6"></div> <div class="span6"></div> </div> </section> </div>
Which results in: