Here's a pretty spiffy layout trick I learned this week. Let's say you find yourself with a two-column layout where you've floated both columns to get them to appear side-by-side. Maybe you've used
display: inline-block, but either way you have two columns. This looks great when the viewport is large but once it starts getting a little smaller perhaps you'd like to stack the columns on top of one another. Typically the way you would approach this is to de-float the columns (or switch to
display: block) in a media query that only takes effect once the viewport width drops below a certain threshold. The columns now each take up 100% of the width of their container and stack on top of one another naturally.
However, they now stack up in the same order as your source code with the first column in your source appearing on top and the last column in your source appearing on the bottom. Lots of times that's exactly what you are trying to achieve but sometimes you want the opposite order. For instance, maybe you have an image on the left and some text on the right. When the viewport gets small, you (or your designer/copy writer/etc.) may feel that it's more important to show the text on top, even though it comes last in the source.
This is a common design pattern and it seems like it should be a pretty easy thing to accomplish until you actually try it. So what to do? Well, at this point you could take a couple of approaches:
1. Duplicate the source and toggle the visibility of each copy
This approach would have you write out the same markup twice but re-order the source in the second markup block. Then you can style each one individually so that the first one is side-by-side and the other one is stacked. Lastly you set
display: none/block on each of your chunks of markup so that the side-by-side one shows when the viewport is large and the stacked one shows when the viewport is small. This is a common solution because it's very simple to implement, especially if you don't have a lot of markup to contend with. However, it's also a little controversial, as there is some concern about whether or not the duplicated content is harmful to SEO and/or screen readers. While I can't confirm that there is indeed a negative impact, I really can't see it improving matters so I would at least consider this approach a little risky. You also have to admit that there's something kind of dirty feeling about duplicate content - one of the best things about responsive design is that it frees us from the burden of having to create two entire sites to cover both desktop and mobile. Duplicating the content seems like a step backwards from the goal of serving one website with one set of content to all platforms and devices.
window.innerWidth/innerHeight will give you the dimensions of the viewport and you can check those each time the window resize event fires. Or even better, you could use
So what do we do? Table model to the rescue!
3. Do a source-order shift using the CSS table model
This is so simple it's actually kind of beautiful. Tables often have
<caption> elements that let you put some kind of descriptive text either on top or at the bottom of the table. We can make use of this in our small-screen media query by setting
display: table and
caption-side: top on the element that contains both of our columns. This tells the container to use the table model to display itself and, if there is a caption present, show it at the top and not the bottom. Finally, by specifying
display: table-caption on the last column, we essentially tell the browser that our last column should behave like a table caption (and thus be shown above the first column). That's it! 3 lines of CSS and we're done.
Here's a pen that illustrates the solution:
Support for this technique goes way back considering that these properties are not new at all.
display: table and
display: table-caption are all part of the CSS 2.1 table model and go all the way back to version 1.0 in Firefox, Chrome and Safari. Opera goes back to version 7 and even IE picked up support in version 8 so I'd feel totally comfortable using this everywhere. In the future, hopefully this kind of technique will be made obsolete by more powerful layout tools like flexbox but until then this is an easy and reliable solution to a common problem.