CSS stacking with display:table

With responsive design, one of the things that we often want to do is to change the stack order of certain elements, moving the aside on the left below the main text which we want to bring to the top. CSS3‘s Flexbox will do this for us, but there is a quicker, if dirtier, way which we can use now.

I say “use now” when of course we can use Flexbox now but implementations vary across browsers as does the required syntax. Opera’s Chris Mills has written two excellent in-depth articles (Flexbox basics and Advanced cross-browser flexbox) on the different flavours of Flexbox.

Flexbox will of course offer more than simple re-stacking of elements, but if that is all you need, you can look no further than CSS‘s display property.

(Incidentally this idea is based on something Bruce Lawson told us at beyond tellerrand )

Let’s take four boxes whose very simple HTML is laid out as follows:

<div class="boxes">
   <div class="one box">Box One</div>
   <div class="two box">Box Two</div>
   <div class="three box">Box Three</div>
   <div class="four box">Box Four</div>
</div>

And whose styling is equally as simple:

.boxes {
   width:50%;
   margin:0 auto;
}
.box {
   display:inline-block;
   width:24%;
   height:15em;
   text-align:center;
   line-height:15em;
   color:#fff;
}
.one { background:#333;	}
.two { 
   background:#fff;
   color:#333;
}
.three { background:#aaa; }
.four { background:#dc002e; }

We can easily change the ordering of these boxes in a media query, say at 48em (768px) by taking advantage of display:table. For demo purposes, we’ll put box three at the top, followed by box four, two and then one.

First of all we need to set the containing element, .boxes as display:table.

Then we set the element we want at the top, Box Three, as display:table-caption.

To push an element to the bottom, in this case Box One, we set display:table-footer-group.

And finally to push an element to the top, but not the very top we set Box Four to display:table-header-group.

/* 768px */
@media only screen and (max-width:48em) {
   .boxes { 
      display:table;
      width:100%;
   }
   .box {
      display:block;
      width:100%;
   }
   .three { display:table-caption; }
   .four { display:table-header-group; }
   .one { display:table-footer-group; }
}

You can see this simple demo in action if you resize your browser.

Now I know that purists will probably be appalled by this, I know that I am a bit, but I will admit to having used it in production code simply because it works and it’s a lot less hassle than the various incarnations of Flexbox at the moment. It also works cross browser down to and including Internet Explorer 8.

This “solution”, if I can call it that, also has its limitations as you don’t have the fine tuning of deciding the exact stack order of many elements which Flexbox will give you, but it works well for a small number of elements as the demo shows.

As always, thoughts and comments are welcome.