Columns… Yet Again
Tutorials on how to create columns and multi-column layouts with CSS have been done a million times over, it seems every person who has touched CSS wants to tell someone else how to achieve this one thing in particular more than anything else. I don’t have anything new or groundbreaking to explain here - though it will give me opportunity to explain some very clean tricks that I am using these days to keep my markup light and my CSS efficient. A neat clearing method, negative margins, and working around IE.
Firstly - If Internet Explorer supported web standards and wasn’t so bent on keeping backwards compatibility we could use CSS3’s multi-column module, unfortunately this won’t happen for a long long time so let’s look at what we can do in the here and now.
Some code to start with
What do we want to achieve should be the first question you always ask - In this case it’s 50 / 50 columns - So we’ll start with a container for our columns and a sensibly named class ‘columns’ and have two inner containers ‘left’ and ‘right’. We use classes so we can re-use this style many times in the page and keep the markup valid.
<div class=”columns”> <div class=”left”></div> <div class=”right”></div> </div>
Some CSS to start with
We are wanting 2 block level elements side by side each occupying 50% of the total width of the container. So we float both columns left and give them width: 50%;
.columns .left {
float: left;
width: 50%;
}
.columns .right {
float: left;
width: 50%;
}
In IE there’s already problems, all Internet Explorers have a rounding bug when it comes to calculating widths of two floats side by side - It seems 50% + 50% = 101%!
There’s a simple fix we can just drag one of the columns left by 1px and the columns will happily sit next to each other.
A negative margin will drag an element from it’s original position, it’s a technique that offers a whole range of opportunity to the CSS coder who knows how to use it.
.columns .right {
float: left;
width: 50%;
margin-left: -1px;
}
And there you have it - it’s that simple to add 50 / 50 columns with CSS, no tables are necessary
More flexibility - less maintenance
Padding / Border both add to the total width of an element, so adding any of these properties will break the layout and cause the right column to drop. So, the method I prefer to get around this limitation is to simply add another element as a buffer in between that we can apply the padding / border to without effecting the outer column elements.
<div class="columns">
<div class="left">
<div class=”inner”>
<p>Sed egestas, lectus a sollicitudin imperdiet, ipsum leo sagittis sem, ac porttitor sapien nulla vitae justo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Suspendisse potenti. Donec condimentum facilisis ante. Pellentesque arcu ligula, eleifend ut, semper in, tincidunt id, sapien. Donec at sapien. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aenean sodales iaculis elit. Mauris dolor leo, lobortis nec, fringilla at, nonummy eu, nibh. Nunc neque dui, vestibulum ut, euismod eget, tincidunt ac, sapien. Sed sem mi, vehicula ut, aliquam eget, fringilla nec, odio. Integer metus sapien, pretium accumsan, vehicula vitae, scelerisque non, felis. Sed nibh. Ut turpis ante, lobortis sed, viverra vel, blandit eget, nibh. Duis mi urna, lobortis vitae, adipiscing vel, hendrerit a, leo. Vivamus viverra, elit pulvinar vestibulum tempor, nibh pede posuere pede, in auctor mi velit a elit. In nunc ante, ornare nec, feugiat in, dictum in, est. Fusce eu tortor. Morbi aliquam.</p>
</div>
</div>
<div class=”right”>
<div class=”inner”>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Fusce facilisis est nec arcu. Sed sem. Praesent ut elit. Donec ultrices lacinia metus. Nam euismod. Praesent sit amet mi et justo commodo convallis. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Cras vitae turpis auctor tortor bibendum congue. In viverra arcu eu erat. Maecenas orci eros, blandit eget, vulputate et, commodo mollis, quam. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Fusce id purus. Curabitur in mauris vel mauris viverra ullamcorper. Ut rhoncus turpis ut dui. Suspendisse augue tellus, elementum id, gravida vel, gravida eu, dui. Fusce et nisi. Donec ornare ornare risus. Donec blandit facilisis diam. Donec blandit.</p>
</div>
</div>
</div>
And now we can add padding to our columns safely
.columns .inner { padding: 20px }
You can add other styles to the columns as long as you take into account the issues outlined above
- IE’s rounding bug, padding / border adding to total widths - you can usually get around these issues using negative margins. Let’s say I wanted to add a dividing line between these two columns, we add a 1px border to one of the columns and increase the negative margin by 1px to accommodate the change.
.columns .left {
float: left;
width: 50%;
border-right: 1px solid #EFEFEF;
}
.columns .right {
float: left;
width: 50%;
margin-left: -2px;
}
.columns .inner { padding: 20px }
/* The middle is now clearly defined so we should
make the padding the same either side */
.columns .right .inner { padding-left: 22px }
And, last but certainly not least
Clearing your floats! This is a most important step to understand, When we floated our columns we removed them from the normal flow of the document, essentially this means that our container collapses because it has nothing left inside. I’m thankful to the folks at Sitepoint for introducing me to this clearing method that doesn’t need to any additional markup and it’s wonderfully simple - Give the container overflow: hidden; and width: 100%;
.columns {
overflow: hidden; /* Clear floated children */
width: 100%; /* Clear floated children in IE */
}
I’ve tested this method in all the popular modern browsers as well as IE5, IE5.5 and it seems to work fine and dandy. So here’s the 50% width columns with CSS example