While playing around with some CSS, I found a nifty technique to produce equal height faux columns with pure CSS, using the pseudo-element; :after. No background image, and no javascript required. Here is how it works:
Lay out your mark-up. Nothing unusual, just a container holding two divs with some content.
|
1 2 3 4 5 6 7 8 9 10 11 12 |
<div class="columns"> <div class="column"> Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. </div> <div class="column"> Look - It's expanding! </div> </div> |
Now, apply some CSS
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
p {font: 12px/1.4em Arial, sans-serif ;} .columns { margin: 0 auto; /*Center it, for no real reason*/ width: 440px; overflow:hidden; /*clear floats, otherwise, .columns will collapse, and there will be no height for the faux-cols*/ position: relative; /*This is key*/ } .column { width: 170px; float: left; padding: 20px; margin-right: 20px; } .column:last-child {margin-right: 0;} .column:after { content: ''; display: block; position: absolute; z-index: -1; /*Places the element behind*/ width: 210px; height: 100%; /*Getting height from .columns*/ top: 0; /*Do not specify left value*/ background: #cfcfcf; border-radius: 5px; margin-left: -20px; /*Using margin to compencate for the padding of .column. */ } |
Check out, and play with this example
Explained
Using the :after pseuso-element you are basically creating a new element, with a static width, equal to the width of the column (170px + 40px of padding = 210px) and a height equal to the columns parent element (100%). What happens is; the pseudo-element gets it’s height from the closest parent which do not have a static position. Style this element to taste and use a negative z-index to place it behind the actual column.
This outlines an interesting way of laying out stuff, and creative use of the :before and :after pseudo-element combined with positioning, and outlines some concepts which can be used in several instances, not just for creating faux cols. I’ve never seen this before, so this is possibly something different to add in your arsenal of tools
That be said, the need for this – exact technique for faux cols – will in time die with the new flexible layout box model, in short; flexbox. The only problem is the lacking support for this in IE, and having to rely on javascript to make it work cross-browser. But is that really a problem?
Thanks a lot for the article post. Great.
Great post. I noticed that the design of YouTube uses a similar technique without “:after” pseuso-element , but directly creates a new div and is compatible with Internet Explorer.
Ah, cool! Yes, using an extra div will work in the same way, this is just a litte slicker
…And actually works perfectly with Internet Explorer as well. What ruined it in the example was the use of “last-child” (not supported), instead of “first-child” (At least they made support for one of the sides – just keep forgetting which one). That resulted in the pseudo-column getting placed behind the real column.
Updated here: http://jsfiddle.net/hravad/qV48w/
Works with Internet Explorer 8.0 (besides the rounded corners of course – use CSS3PIE for that)
Hello! Quick question that’s totally off topic. Do you know how to make your site mobile friendly? My site looks weird when browsing from my apple iphone. I’m trying to find a template or plugin that might be able to correct this problem. If you have any suggestions, please share. Cheers!
The problem with this code is when the construction is put within another with background, or even in this example, when the background is added to .columns class – the background of 2 columns will not be seen, only the text. The problem is with z-index:-1. If it is deleted, then the 2 columns are seen on the background of the .columns, but the text of the columns dissapears. This method is good when the .columns are put just after the body to form the page layout columns, but it doesn’t work within the page for equal-height blocks when it is put on the background. I need the content (text) to be seen… Any ideas?
Hi Andrew, thank you for pointing this out. The negative z-index for the :after elements is absolutely necessary, you just need to give .colums any z-index and it should work perfectly fine within any layout
), or by putting .columns inside another wrapper.
But there is one problem, and that is if you want .colums to have any top or bottom padding, since the .colmun:after elements always will be 100% of the height of .columns, including padding. That also can be solved though, by either using calc (-moz-calc(100% – 40px); http://caniuse.com/calc – not too widely supported, but getting there
Thanx Håvard, funny that I missed that possibility
. Thanx a lot again. Have put .columns inside another wrapper.
Glad to be of help, Andrew
Dear Håvard,
Have one more question for you. Was trying to fight that problem, but effortlessly.
Was trying to add to the .column:after class border and shadow – wanted to make it more picturesque, not only the plain background with the rounded corners. But, unfortunately, couldn’t do anything – the border remains only on top or bottom (depending on whether to put top:0 or bottom:0) and on one right side, and shadow as well was omitted. Well, it is clearly because of the .column:after class parameters – border is out of the box. Was trying to change this and that, but couldn’t put the border 1px solid #000 and 5px shadow around that grey box with rounded corners.
Can you please help me with that? Any possible solutions?
Thank you!
Andrew
Hi Andrew
The reason this won’t work is the use of overflow:hidden to clear the floats inside .colums and to prevent .colums from collapsing. This will cut off the borders and shadows. What you can do is to use the so called clearfix method to clear the floats instead.
I made an example for you here, with some comments: http://jsfiddle.net/hravad/vLwPP/13/
Hope this will clear things up, and if not – just yell
Dear Håvard,
Thank you very much for youir help! One headache lost!
Regards,
Andrew