Xiper

z-index в IE6-7

Автор: Евгений Рыжков Дата публикации:

Проблема

В IE6-7 элементы, находящиеся в блоках с position: absolute/relative, не воспринимают z-index.

Теория

Согласно спецификации CSS 2.1 каждый позиционируемый блок имеет значение z-index (по умолчанию z-index: auto, что эквивалентно z-index: 0). Чем больше это значение, тем выше элемент по z-оси. При равных значениях z-index, будет показан тот элемент, который по HTML коду ниже. Но IE6-7 и их Mac версии это правило игнорируют:

  • z-index элемента зависит от z-index родителя (и не может быть больше значения родителя в общем потоке);
  • z-index с заданным числом может перекрываться z-index: auto.

Например, возьмем 2 блока, идущих друг за другом с position:relative — header и content. В header у нас есть выпадающее меню(menu), которое позиционируется с помошью position:absolute; , и частично перекрывает блок content. Присваиваем menu z-index:1000 (чтобы явно было больше, чем у других блоков) — menu должно быть поверх блока content.

HTML код

<div class="header"><div class="menu"></div></div>
<div class="content"><div>

CSS код

.headaer {
[...]
position: relative;
}
.menu {
[...]
position: absolute;
z-index: 1000;
}
.content {
[...]
position: relative;
}

Результат.
Для IE6 не сработает выпадение меню(лень было делать javascript для отмирающего браузера).

В данном примере в браузерах IE6 и IE7 блок menu не перекрывает блока контента, так как IE принимает во внимание z-index родителей, при чём z-index родителя важнее, чем у данного элемента.

В IE меню не перекрыло контент - z-index проигнорирован
В IE меню не перекрыло контент - z-index проигнорирован
В FF с z-index все нормально
В FF с z-index все нормально

Решение

Явно задаем z-index родителям. При чем z-index родителя, в котором будет всплывающий элемент, должен быть больше, блока, который будет перекрываться:

Как правильно задать z-index блокам

По идее для menu можно не задавать z-index, но для уверенности все же можно указать. CSS код:

.headaer{
[...]
position: relative;
z-index: 2;
}
.menu{
[...]
position: absolute;
z-index: 3;
}
.content {
[...]
position: relative;
z-index: 1;
}

Результат. А теперь представь ситуацию, когда идет ряд блок друг за другом и в каждом есть появляющийся блок, например в строки таблицы. Придется учитывать чтобы у каждого последующего блока z-слой был ниже, чем у предыдущего:

Как правильно задать z-index когда блоков несколько

В ручную не всегда удастся задать z-index, особенно в тех случаях, когда на перед неизвестно сколько будет блоков. В тах случаях выручает javascript.

Решение с помощью jQuery

Ниже пример подобного решения с применением jQuery:

$(function() {
var zIndexNumber = 1000;
$('div').each(function() {
$(this).css('zIndex', zIndexNumber);
zIndexNumber -= 10;
});
});

Вариант без jQuery

update by Dmitry Balan: нормальные браузеры слои расставят и так нормально, для IE же можно воспользоваться подобным expression:

div{
behavior:expression(onmouseover=function(){this.className +=" zindex"},onmouseout=function() this.className=this.className.replace("zindex","")},style.behavior=null);}
.zindex {
z-index:1000;
}

Смысл в том, что родителю, на который навели мышью, присваиваем z-index больше, чем у остальных блоков. У этого способа есть плюс — не нужно подключать библиотеки или внешние js-файлы.

Материалы

  • IE7 lessons learned: the z-index bug
  • Fixing IE7 Z-Index Issues with jQuery
  • Effect of z-index value to positioned elements