Skip to content ↓


Вертикальная перестановка блоков средствами CSS

Краткое описание
Техника полноценной кроссбраузерной вертикальной перестановки блоков произвольной высоты средствами CSS.

Вертикальный порядок следования блоков на HTML-странице можно изменить, придав им табличное представление при помощи CSS-свойств семейства display: table. Вне зависимости от порядка расположения блоков в HTML-коде, «шапка» (table-header-group) такой таблицы отображается в её верхней части, «подвал» (display: table-footer-group) — в нижней, а основная часть таблицы (table-row-group) — между ними.

HTML:
<div id="example">
    <div id="block-1">Первый</div>
    <div id="block-2">Второй</div>
    <div id="block-3">Третий</div>
</div>
CSS:
#example {display: table; width: 100%; }

#block-1 {display: table-footer-group; } /* Отобразится внизу псевдотаблицы */
#block-2 {display: table-row-group;    } /* Отобразится посередине */
#block-3 {display: table-header-group; } /* Отобразится вверху */

Получим:

Третий
Второй
Первый

В отличие от абсолютного позиционирования, где высота блоков должна быть заранее известна, здесь высота блоков может быть любой. Вертикальное положение блоков будет взаимозависимым: вертикальное увеличение блока приведёт к соответствующему сдвигу визуально следующего за ним блока вниз (в том числе при динамическом изменении высоты, например, при увеличении размера шрифта средствами браузера).

Описанным образом можно изменять порядок до трёх соседних блоков. Дополнительно можно задействовать display: table-caption (отображение блока в роли подписи к таблице) в сочетании с CSS-свойством caption-side: top/bottom. Но обратите внимание, что в браузере Opera 11 ссылки внутри такого элемента были недоступны для щелчка либо не реагировали на наведение указателя мыши, игнорируя CSS-правила для псевдоклассов :hover (идентификатор бага в баг-трекере Opera — DSK-338752). Начиная как минимум с Opera 12, проблема, похоже, устранена.

Метод работает в большинстве распространённых браузеров, в том числе в Internet Explorer начиная с версии 9 (IE8 — с оговорками, см. далее).

IE 6, 7 и 8

Устаревшие браузеры IE6 и IE7 не поддерживают CSS-свойства семейства display: table*.

Кроме того, в IE8 в некоторых случаях наблюдается динамическая ошибка рендеринга: если перемещаемый блок содержит в себе псевдотабличные элементы (display: table*) (проявление нюанса замечено только в этом случае), возможно спонтанное пропадание некорых ячеек (всегда разных и в разном количестве) псевдотаблицы при первичной отрисовке страницы.

Поэтому для IE8 и ниже можно отменить CSS-правила, придающие блокам табличный вид, и дополнительно переместить блоки в нужные позиции DOM-дерева HTML-документа уже с помощью JavaScript:

/**
 * Перестраивает соседние элементы в DOM-дереве в заданном порядке.
 * @param {Array} elems Соседние элементы в необходимом порядке.
 */
function reorderElements(elems) {
    // http://tanalin.com/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);
    }
}

// Если IE8 или ниже (http://tanalin.com/articles/ie-version-js/)
if (document.all && !document.addEventListener) {
    var blocks = [
        document.getElementById('block-3'),
        document.getElementById('block-2'),
        document.getElementById('block-1')
    ];

    reorderElements(blocks);
}

Абсолютное позиционирование

Для изменения вертикального порядка блоков средствами CSS широко применяется абсолютное позиционирование. Блок в этом случае не перемещается, а позиционируется относительно ближайшего родительского элемента, для которого задано CSS-свойство position: absolute или 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; } /* «Приклеен» к нижней кромке контейнера */
#block-3 {top: 0; height: 100px; } /* «Приклеен» к верхней кромке контейнера */

Большой недостаток абсолютного позицинирования — позиционируемый таким образом блок вырывается из общего потока элементов и перестаёт оказывать влияние на положение других элементов. Поэтому абсолютное позиционирование для перестановки блоков применимо только в том случае, если высота позиционируемого блока заранее известна и не зависит (либо зависит несущественно) от настроек размера шрифта в браузере и на уровне операционной системы.

Способ с применением табличного CSS-представления лишён недостатков абсолютного позиционирования и позволяет получить результат, аналогичный ситуации, когда блоки в HTML-коде располагаются именно в том порядке, в каком отображаются.