Parent pages:
  1. Home
  2. Articles
  3. Vertical reordering of blocks with CSS

Vertical reordering of blocks with CSS

Summary
Technique for full-fledged cross-browser vertical reordering of blocks of arbitrary height with CSS.

It is possible to change vertical order of blocks on HTML page using CSS table presentation using properties of display: table family. Regardles of block order in HTML code, header (table-header-group) of such table is displayed at the top of it, footer (display: table-footer-group)—at the bottom, and table body (table-row-group)—between header and footer.

HTML:
<div id="example">
    <div id="block-1">First</div>
    <div id="block-2">Second</div>
    <div id="block-3">Third</div>
</div>
CSS:
#example {display: table; width: 100%; }

#block-1 {display: table-footer-group; } /* Will display at the bottom of pseudo-table */
#block-2 {display: table-row-group;    } /* Will display in the middle */
#block-3 {display: table-header-group; } /* Will display at the top */

Result:

Third
Second
First

Unlike absolute positioning where block height should be known beforehand, blocks may have any height here. Vertical positions of the blocks will be interdependent: vertical enlarging of a block will result visually next block to shift down appropriately (including cases when height is changing dynamically, for example, as a result of increasing font size in browser settings).

With this method, it is possible to change order up to three sibling blocks. It would be possible to also utilize display: table-caption (displaying block as table caption) in combination with CSS-property caption-side: top/bottom. But, unfortunately, in current versions of Opera browser, links inside of such preudo-caption element are unclickable or do not respond to mouse hovering, ignoring CSS-properties for :hover preudo-classes (the bug id in Opera’s bug tracker is DSK-338752).

The method works in most of popular browsers, including Internet Explorer as of version 9 (using the method in IE8 is limited, see hereafter).

IE 6, 7, and 8

Old browsers IE6 and IE7 do not support CSS-properties of display: table family.

Also, in some cases, dynamic rendering bug in IE8 appear: if block to move contains preudo-table elements (display: table*) (this is the only buggy case noticed currently), some pseudo-table cells (such cells as well as cells count are different each time page is reloaded) may disappear randomly when page is initially rendered.

So, for IE8 and lower, we can override CSS-rules that make blocks tably, and additionally move blocks to required positions of DOM tree of HTML document with JavaScript instead of CSS:

/**
 * Reorders sibling elements in DOM tree according to specified order.
 * @param {Array} elems Sibling elements ordered according to required block order.
 */
function reorderElements(elems) {
    // http://tanalin.com/en/articles/css-block-order/
    var count = elems.length;

    if (!count) {
        return;
    }

    var parent = elems[0].parentNode;

    for (var i = count - 1; i >= 0; i--) {
        parent.insertBefore(elems[i], parent.firstChild);
    }
}

// If IE8 or lower (http://tanalin.com/en/articles/ie-version-js/)
if (document.all && !document.getElementsByClassName) {
    var blocks = [
        document.getElementById('block-3'),
        document.getElementById('block-2'),
        document.getElementById('block-1')
    ];

    reorderElements(blocks);
}

Absolute positioning

To change visual vertical order of blocks with CSS, absolute positioning is widely used. In this case, block is not actually moved, but positioned relatively to nearest parent element that have CSS-property position: absolute or position: relative:

#example {padding: 100px 0 200px; position: relative; }

#block-1,
#block-3 {position: absolute; left: 0; width: 100%; }

#block-1 {bottom: 0; height: 200px; } /* Positioned to the bottom of container */
#block-3 {top: 0; height: 100px; } /* Positioned to the top of container */

Big shortcoming of absolute positioning is that positioned block is removed from normal element rendering flow and does not affect positions of next sibling elements anymore. So, absolute positioning is applicable to reorder blocks only in cases when height of positioned block is known beforehand and does not depend (or depends a bit) from settings for font size in browser or operating system.

Using CSS table presentation if free from shortcomings of absolute positioning and allows to get a result similar to a case when block order in HTML code is exactly the same as its visual order on rendered page.