Internet Explorer и z-index
ИЕ воспринимает z-index не совсем так, как все остальные браузеры. Это поведение настолько часто встречается в моей жизни, что я решил о нём написать целый пост.
Меня часто просят поправить ошибки в верстке. Так вот эта — входит в топ-5.
z-index работает?
Да, совершенно точно работает. Берем два блока, с position:absolute (для работы z-index нужен либо relative либо absolute)
Задаем им обоим что-то такое:
- #block1, #block2{
- position:absolute
- }
- #block1{z-index:10}
- #block2{z-index:20}
На самом деле, мне просто больше нравятся зеленые блоки.
Не обращайте внимания на Гитлера.
Блок с большим z-index отобразится поверх блока с меньшим z-index. Все как бы работает. И в IE в том числе.
работает, но…
Классическая обстановка для «проблемы в вёрстке».
В коде идут подряд два блока с position:relative. Например, два блока новости, или блоки вроде header и content. В relative ничего необычного нет, может добавили для absolute блоков внутри, или для хаков.
Как-то так:
- <div class="entry"></div>
- <div class="entry"></div>
И теперь, например, в одном из них появляется всплывающее окошко, или попап, или выпадающее меню:
- <div class="entry">
- <div class="popup">Попап</div>
- </div>
- <div class="entry"></div>
И такой вот дизайн:
Попап должен находиться в блоке 1
Будь вы мной, вы написали бы такой CSS:
- .entry{
- position:relative
- }
- .popup{
- position:absolute;
- z-index:10;
- top:10px;left:100px;
- }
Если добавить цвета и размеры, все отобразится и правда так, как в дизайне.
Но, разумеется, не в ИЕ.
Там это будет выглядеть так:
Попап или выпадающее меню скроется за следующие блоки
Я это понимаю так: ИЕ сравнивает не только z-index блоков, но и z-index их родителей. Причем родительский важнее. В моем примере роль «родительского z-index» исполняет просто последовательность блоков в коде. Какие блоки дальше в коде, те и отобразятся поверх.
Я сделал специальный пример, смайлик из acid-теста будет улыбаться всем браузерам кроме ИЕ. (его улыбка зависит от этого вот поведения с relative блоками)
решение?
- Убрать position:relative для .entry
- Задавать разные z-index для .entry. В случае новостей это невозможно, они ведь генерируются симметрично. Однако когда у нас header и content, вполне подходит.
Может быть есть еще?
В конце
Мне не хочется называть это багом, поскольку для него требуется куча обстоятельств, скорее всего не описанных w3c. (или описанных?)
Поведение имеет место в IE5-7. И, наверное, 8.
Как всегда буду рад вашему опыту и мыслям по этому поводу.
Статьи на тему этого поведения:
Никто никогда не обращает внимания на Гитлера.
Ваш дiзайн — отстой!
Очень мешает данное поведение IE, когда, бывает, хочется хитро извернуться в верстке. В результате приходится перемещать некоторые элементы кода в другое место.
P.S. Юра, что стало со шрифтом на блоге? Шрифт стал мелким и пропало сглаживание.
абсолютные блоки для осла нужно перемещать в конец body.
то есть, когда popup включаем, то перед этим делаем так
$(’.popup’).insertBefore($(body));
Не обращайте внимания на Гитлера.
это из 3-х Tt Crowd ? )
У меня самая распространенная проблема с z-index’ом - это выпадающие меню и какой-то absolute-ный или relative-ный контент. Лечилось выставлением z-index:1 для родителей выпадающего элемента по-очереди.
Всё дело в волшебных контекстах стэков :) У ИА с ними особое отношение.
Вот матерем клянусь — видел решение этой проблемы. Попробую применить гипноз и вспомнить…
Нашёл! Да здравствует делишез — Effect of z-index value to positioned elements
Да, но его способ это задать для блоков-родителей z-index =(. Это обычно невозможно когда у нас список новостей, я ж как раз этот способ и написал (#2)
@Dimox, боюсь что ты установил себе на винду шрифт Myriad. Ничего не могу поделать с ее пахабным сглаживанием к сожалению =(
IT Crowd хорош ;)
@akella: ну, почему — если мы правим баги для IE, то вполне можно использовать одноразовый expression, который расставит z-index’ы по списку.
И правда, забыл о нашем колдовстве :)
Я, правда, решил по-другому, ставил position:relative блоку только при :hover. Таким образом его “деть” как и он сам был “на высоте” по сравнению с остальными без relative.
angizij, Вы будете удивлены, но чувство юмора есть не только у британских сценаристов.
Как это ни банально, но
http://css-discuss.incutio.com/?page=OverlappingAndZIndex
И там всё есть )
Спасибо! Добавил в пост =)
Спасибо! Буквально вчера пытался сам разобраться в спеке, кто из браузеров прав (причем мое имхо склонялось в пользу старых эксплореров). А тут по ссылкам в три клика нашлось доходчивое объяснение, почему правы современные браузеры, а IE6-7 заблуждаются :).
Кстати, в самом стандартном режиме IE8 c z-index’ами уже тоже все в порядке. Хотя своих приколов с позиционированием пока тоже хватает, надеюсь, к релизу исправят…
Гитлер форева. Тьфу блин в смысле прикольно, но больше Гитлера не надо ).
Шрифт в Висте ужасен полностью согласен - муть какая-то :(
скажите, а z-index одинаково ведет себя в IE6 и IE7 ?
Да, в целом одинаково, и этот глюк тоже у них общий
Свой вариант предложу: обрамляем все новости (новостные блоки) в общий блок, в котором делаем дочерний блок-попап с зет-индексом 1. Его позиционируем относительно родителя (общего блока), и проблем нема :)
[…] Internet Explorer и z-index — описание одного распространенного и вредного бага в ИЕ […]
>Задавать разные z-index для .entry. В случае новостей это невозможно,
Не совсем понимаю этот вывод, если новости генерятся, значит им автоматом можно и разные z-index сгенерить, по id или просто по итерациям цикла (с рассчётом чтобы максимально возможный не был больше чем используется где-то ещё на странице, если используется).
Совершенно верно, можно задать разные. Но только в темплейтах этого не получится сделать =( да и лишние телодвижения, не очень красивое решение будет
1. ёпть, не ввёл 4 и пост потерялся, плохо. Надо поле подтверждения вынести ближе к кнопке “Отправить”, и как-то выделить.
2. страница с “Дважды два 4, нужно было ввести цифру 4 в поле.” без указания кодировки, а не у всех по умолчанию включен утф.
Отпало желание по второму разу писать то же, но попробую.
Я давно смирился что практические и быстрые решения - не самые красивые и правильные с точки зрения каких-то стандартов “правильной” вёрстки.
Держать оформление и вёрстку исключительно в шаблонах и цсс это скорее идеал, к нему можно стремится, но зачастую думаешь лишь о том чтобы всё работало, а не о том что завтра прийдётся менять дизайн и при этом возникнут лишние трудности. Помоему это зависит от ситуации, времени, верстает и порграмит один человек или разные, применяемых инструментов и решений, привычек и т.п. Хотя возможно я не дорос до того “уровня” когда всё верстается быстро, кроссбраузерно, идеально по всем стандартам, легко к изменению и красиво прои просмотре кода.
P.S. >в темплейтах этого не получится сделать =(
Это тоже не аксиома, смотря кто на чём темплейты строит, думаю не проблема передать в темплейт из модуля новости некое сгенерированное число, а в темплейте его использовать. Хотя лично я не совсем понимаю смысл такого |модуль выдающий данные в цикле|, тогда все данные получатся в одном блоке, или же сам шаблон надо будет прогонять через цикл n-раз, но зачем…
Эмм, вырезаются теги, я имел ввиду [див style=”z-index:x;”] |модуль выдающий данные в цикле|[/див]
>Какие блоки дальше в коде, те и отобразятся поверх.
А существуют ли какие-нибудь способы указания порядка расположения одного блока над другим?
У меня на блоге самописный движок, так вот там можно задавать параметры отображения для каждого блока в числовом значении. Оформляется это также через CSS.
И еще: сейчас многие пробуют новую версию IE для вебмастеров. Там есть какие-то различия в отображении по сравнению с перечисленными релизами эксплорера?
Спасибо за пост. А теперь расскажите как расположить абсолютно-позиционируемый элемент поверх элементов форм? В IE6 всякие селекты вылезают на самый верхний уровень. Единственное решение нашел, тупо visibility:hidden скриптом прописывать, ну это только в том случае если используется что-то вроде lightbox/thickbox.
Обычно эту проблему (с оверлеем) решают отображением ифрейма с фильтром поверх селектов, он их “покрывает”, а его прячут в СС, или меняют его ширину как надо через ЖС. Когда дело касалось хинтов, я обычно корректировал их позиции чтобы они с селектом не пересекались. Ну и приятно помнить что в ИЕ7 это решили, хоть это и не освобождает от ИЕ6 ответственности.
Возможно в вашем частном случае можно придумать что-то хитрое? Есть ли пример?
Ну как, если есть веб-сайт с контролами типа select (например last.fm, там сверху есть выбор раздела для поиска). При клике на сылку (например «Войти») появляется div развернутый на всё окно (сделаный примерно так же как lightbox), который затемняет всё содержимое веб-страницы. По центру затемненного фона появляетя форма входа, а сверху на этом же темном фоне вылезает упомянутый select.
Насчёт iframe — не мой вариант. Терпеть его не могу. Лучше jQuery уберет контролы с глаз долой, а потом вернёт при закрытии попапа.
Кстати, может лучше «поиск сбежавшего бота» поближе к кнопке «Отправить» поместить? А то замечаю это поле в последний момент :)
Ну вот эти всякие лайтбоксы просто растягивают ифрейм в ИЕ6 и все.
А что такого страшного в ифрейме? он ведь появится только для одного браузера? Ну сожрет он ему памяти, но и убирание всех селектов тоже откушает =)
Но вариант со скрытием селектов на всей странице тоже отличный.
Просто как видно из блога разработчиков, сделать больше мало что можно. Все остальные хаки будут еще более грязные =)
Эта проблема не только IE, я сталкивался с подобным и в других браузерах. для себя зарекся давать z-index абсолютным элементам которые меряются им с относительными. оборачиваю абсолютный в относительный и на него уже z-index.
спасибо за разъяснения
Спасибо ОГРОМЕННОЕ!
Никто не думал менять z-index у главного родительского елемента на 1000 к примеру при событии вызывающим попап (js естественно)?это решит ваши проблемы. И даже в том случае если у идущих подряд блоков индексы отличаются задайте их в диапазоне от 0 до 999.Этого диапазона вам за глаза хватит и попап всегда будет поверх.
ЗЫ на возгласи типо “js может быть отключен в браузере” я отвечу: “У кого в браузере отключен javascript тому и попапы не нужны.
Столкнулся со второй проблемой…
>решение?
>Убрать position:relative для .entry
С таким же успехом можно было бы написать: “Уволиться с должности верстальщика” - тоже неплохое решение этой проблемы.
В реальных ситуациях position:relative не появляется просто так, если он стоит значит он там очень нужен. Пол сайта придется теперь переверстывать (((
Ну убрать relative для .entry не значит отказаться от него совсем, просто нужно попробовать применить его к другому элементу, чему-то внутри .entry, чтобы обойти баг в ИЕ.
Огромное спасибо!
После получасовых мучений с IE наконец-то помогло :)
Сначала всегда считала, что обходить подобные вещи можно только располагая выпадающее меню в самом низу страницы и position:absolute подгонять в нужное место. Когда надо, чтобы весь сайт центрировался это заставляло перепланировать полностью структуру сайта и делать чуть ли не весь сайт на абсолютах (left:50% … left:-300px …) и в этом полно своих минусов.
И как-то случайно вспомнила про z-index … и все бы ничего, но в IE6-7 не работает. И только наткнувшись на вашу статью (и это время сказать спасибо за нее) вспомнила что даже в htmlbook читала об relative или absolute для z-index но успешно об этом позабыла.
Долго искал решение проблемы с Z-idex и IE6. Но решилось все просто - http://tjkdesign.com/articles/z-index/teach_yourself_how_elements_stack.asp
Подобрал, открыв эту ссылку в IE6 позиционирование и значение Z-idex для двух верхних блоков. Оказывается нужно было задать для нижнего блока значение Z-Index: - 1; позиционирование realativ , у верхнего static и положительный Z-Index и IE все прекрасно понял. Дочернее меню стало отображаться над нижним блоком.
Вот тут объясняется проблема: http://www.webcocktail.ru/coding/z-index-position-bug-in-internet-explorer/
У родительских блоков, содержащих в себе блоки с абсолютным позиционированием, также должен быть указан z-index. Именно он и влияет в IE на то, какой блок будет находится “выше”.