Css свойство z-index не похоже на какие-либо другие css свойства. Многие разработчики, сталкиваясь с ним, приходили в замешательство из-за не правильного использования. Однако, когда вы поближе познакомитесь с z-index, вы поймете, что это свойство очень простое и предлагает эффективный метод решения многих задач верстки.
Начнем наш пост со знакомства. Свойство z-index определяет уровень стека html-элемента. «Уровень стека» обозначает позицию элемента на оси Z, направленную перпендикулярно оси X и оси Y. Элемент, которому назначено самое большое значение z-index, располагается в самом верху стека.
Если сначала не все понятно, то думаю после просмотра 3D представления «уровня стека» (оси Z) станет более понятно:
Обычный порядок стека или порядок элементов на оси Z, определяет ряд факторов. Далее предоставлен список, отображающий порядок, в котором элементы укладываются в стек, начиная снизу:
Этим трем блокам не назначен z-index.
Все секреты или почему появляется путаница?
Весь смысл свойства z-index заключается в том, чтобы изменять обычный порядок стека, но при неправильном использовании, оно может привести в заблуждение. Это заблуждение появляется потому, что свойство z-index будет работать только у элементов, которые имеют свойство position с одним из трех значений: fixed, relative или absolute.
Использование
Свойство z-index может влиять на порядок элементов как у блочных, так и у строчных элементов, и устанавливается назначением положительного или отрицательного целого значения, или значения auto. Значение auto определяет элементу такой же порядок слоев, как у родительского элемента.
#box{
position:relative;z-index:100;
}
На примере покажу как можно при помощи z-index поменять обычный порядок элементов с теми же блоками, как и в первом примере:
Красиво, просто, но при определенных обстоятельствах, в таких браузерах как IE6 и Firefox 2, свойство z-index может обрабатываться по-разному.
IE6: Даешь элементу select больше приоритета!
Дело в том, что такой чудесный браузер как IE6 ни в какую не хочет отображать элемент
С использованием iframe:
При помощи javascript:
Я не буду показывать вам пример, потому что реализация довольно таки простая и действенная. Вы просто прячьте элемент
Firefox 2: Что такое отрицательное значение? Аа?
Вот ведь. А firefox 2 тоже имеет свой недостаток. Хоть его и убрали с поддержки со стороны разработчиков, все же напомню, что forefox 2 не работает с отрицательными значениями z-index и ничего с этим поделать нельзя.
Ну вот. Такое страшное и неведанное css свойство z-index кажется таким простым. Надеюсь, я ничего не упустил. Если вам известны еще какие-то проблемы с z-index, милости прошу в комментарии, потому что я в своей практике с другими не встречался.
Вдохновил .
Проблема z-index в том, что многие просто не понимают, как он работает.
Всё, описанное ниже, есть в спецификации W3C. К сожалению, не все её читают.
Ниже представлен HTML код с базовым css оформлением.
Задача: сделать так, чтобы красный был позади синего и зеленого, при этом не нарушая ни одно из следующих правил:
Хм, что-то тут не так. Причем тут вообще прозрачность? Каким образом она может влиять на порядок перекрытия элементов? Вы думаете так же? Добро пожаловать в клуб!
Надеюсь, во второй части статьи всё встанет на свои места.
Любой элемент в HTML документе может быть либо на переднем, либо на заднем плане. Это известно всем. Правила, задающие этот порядок четко описаны в спецификации, но, как я уже говорил выше, не все в полной мере их понимают.
Если свойства z-index и позиционирование не заданы явно, всё просто: порядок наложения равен порядку следования элементов в HTML. (На самом деле всё немного сложнее , но пока вы не будете использовать отрицательные значения отступов для перекрытия строчных элементов, вы не будете сталкиваться с крайними случаями)
Если вы явно указываете позиционирование элементам (и их детям), то такие элементы будут перекрывать собой элементы без явно заданного свойства позиционирования. (Говоря «явно указываете позиционирование» – я имею ввиду любое значение, кроме статического, например: абсолютное, или относительное).
И наконец, случай, когда z-index задан. Для начала, вполне естественно предполагать, что элементы с большим z-index будут находиться выше элементов с меньшим z-index, а любой элемент с установленным z-index будет находится выше элемента без установленного z-index, но это не так. Во первых, z-index учитывается только на явно позиционированных элементах. Если вы попробуете установить z-index на не позиционированный элемент, то ничего не произойдет. Во вторых, значения z-index могут создавать контексты наложения. Хм, всё стало намного сложнее, не так ли?
Каждый контекст наложения имеет свой корневой элемент в HTML структуре. В момент формирования нового контекста на элементе, все дочерние элементы так же попадают в этот контекст и занимают своё место в порядке наложения. Если элемент располагается в самом низу одного контекста наложения, то никаким мыслимым и немыслимым образом не получится отобразить его над другим элементом в соседнем контексте наложения, располагающимся выше по иерархии, даже с установленным z-index равным миллиону.
Новый контекст может быть сформирован в следующих случаях:
Верстаю далеко не первую страницу, но с подобной проблемой столкнулся впервые. В одном из дизайнов мне потребовалось переделать меню для каталога. Изначально использовалось меню с одним уровнем, но бизнес заказчика вырос, и потребовалось реализовать типичное выпадающее многоуровневое меню. «Нет проблем!» - подумал я, и быстренько стал набрасывать дополнительные стили с разметкой. Времени много на это не потребовалось, но вот первое же тестирование оказалось неудачным. Уровни меню появлялись, как и было задумано, но вот почему-то их перекрывали элементы из центральной части страницы.
«Ха!» - промелькнуло у меня в голове. Наверное, в одном из стилей не хватает свойства «z-index», позволяющее управлять порядком наложения позиционированных элементов на странице. Начал добавлять «z-index» и ничего хорошего из этого не вышло. Какое бы значение я ему не присваивал, элементы из центральной части страницы все равно перекрывали мою менюшку.
Казалось бы, что может быть сложного с z-index? Всем известно, что позиционированные элементы на странице могут накладываться друг на друга. Управлять порядком наложения как раз и позволяет свойство «z-index». Например, если у нас два элемента с присвоенным значением z-index – 5 и 10, то последний будет выведен на переднем плане, т.к. десять больше пяти, а больше, значит ближе. Когда свойство «z-index» не задано, то порядок наложения определяется порядком элементов в документе.
Никаких сложностей вроде нет, пока не начинаешь копать глубже. Первые трудности начинаются при появлении так называемых контекстов наложения. Под контекстом наложения подразумеваются элементы с общими родителями, перемещающиеся вместе на передний или задний план.
У контекста наложения есть корневой элемент. Например, у нас есть какой-то
Для которого мы определяем контекст наложения. Следовательно, все его дочерние элементы тоже попадут в этот же контекст наложения.
Вот тут начинается самое интересное. Контексты наложения не пересекаются между собой. Расположив элемент в самом низу одного контекста, не получиться его поднять выше элемента соседнего контекста. Изменение значение «z-index» даже на самые невероятные цифры не будет приносить ожидаемого эффекта.
Спецификация определяет несколько условий формирования контекста наложения:
Забегая вперед, скажу, для решения моей задачи потребовалось лишь добавить прозрачность (opacity ) для корневого элемента меню и все сразу заработало, как было задумано.
Чтобы лучше закрепить все выше сказанное, запомним раз и навсегда порядок отображения элементов в одном контексте наложения (от дальнего к ближнему).
От автора: сегодня будет разговор о том, как работает свойство z index CSS. Это третий пост в «Как работает CSS» — серия статей, где мы глубоко погружаемся в фундаментальные строительные блоки CSS, которые иногда похожи на черную магию. Независимо от того, как вы пишите CSS, всегда полезно знать, что «runtime» вашей таблицы стилей позволяет писать эффективный масштабируемый CSS.
Сегодня мы собираемся погрузиться в одну из тех частей черной магии CSS. Играя с z-index, мы часто бросаем все большие значения и смотрим, какие из них сработают. Но если мы снимем слои с z-index, и взглянем на правила, которые его определяют? Мы увидим, что это не так страшно, как мы думали.
В конце концов, экраны, которые мы используем в браузере, представляют собой двумерные плоские поверхности с кучей пикселей. Но если вы в Интернете уже давно, скорее всего, вы часто имели «трехмерный» опыт. Например, вы можете щелкнуть по кнопке и открыть модальное окно или отобразить тултип «поверх» его кнопок.
Если вы предполагаете, что пользователь смотрит «на экран» и воображает, что экран представляет собой портал в трехмерный мир, вы можете начать визуализировать то, как выглядит это трехмерное пространство в браузере. Для начала, если бы мы визуализировали это пространство как комнату, то «стена», которая «находится дальше всего», называется «холст».
При рисовании пикселей на экране браузер гарантирует, что пиксели, которые ближе всего к холсту (или дальше от нас), будут нарисованы первее. Затем он постепенно продолжает рисовать элементы «ближе» к пользователю, перезаписывая ранее окрашенные пиксели.
Свойство z-index относится к порядку окраски элемента в этой иллюзии трехмерного браузера. По умолчанию все элементы имеют z-index 0, а браузер — в порядке DOM. Тем не менее, z-index фактически дает нам мелкозернистый контроль, когда элемент окрашивается. Назначая более высокий z-index мы можем заставить элемент окраситься таким образом, чтобы он был «ближе» к пользователю. Низкий (или отрицательный!) z-index позволяет нам рисовать элемент ближе к холсту.
Изучая CSS Position & Layout Spec, я нашел эту полезную диаграмму, чтобы визуализировать, как слои z-index смотрят на пользователя.
Элементы с более высоким z-index кажутся «ближе» к пользователю
Если мы посмотрим на это поведение z-index, можно подумать, что оно на 100% прямолинейно: более высокий z-index равен ближе к пользователю, более низкий z-index находится дальше. Тем не менее, есть пара нюансов z-index которые вызывают много путаницы.
Первая оговорка, связанная с z-index заключается в том, что свойство должно быть на позиционированном элементе, чтобы вступить в силу. Это означает, что z-index может использоваться только для изменения порядка укладки, если вы установили position отличную от static. В любой ситуации, когда вы не задали position для элемента, z-index будет иметь нулевой эффект.
Краски вокруг z-index сгущаются еще сильнее, когда мы рассматриваем второе предостережение z-index: свойство применимо только к элементам, расположенным в контексте стека.
Контекст стека включает узел HTML и все его дочерние элементы. Элемент HTML на корневом уровне контекста стека можно назвать корнем стека.
Контекст стека по умолчанию (или «контекст корневого стека») для документа имеет тег html как его «корень стека», и все элементы относятся к этому стековому контексту по умолчанию. Однако любой узел HTML также может быть корневым элементом «локального контекста стека».
Вот несколько способов, которыми можно назначить элемент как корень нового локального контекста стека:
position: absolute или position: relative вместе с любым z-index отличным от auto для элемента.
Использование position: fixed или position: sticky на элементе.
Установка opacity меньше 1 на элементе.
Использование transform или will-change в элементе.
В качестве примера давайте представим три дерева узлов HTML, визуализированных как три стека. На приведенной ниже диаграмме нижняя часть каждого стека является родительским узлом HTML, а дочерние элементы располагаются сверху (например, представление «вверх дном» дерева HTML). Давайте также притворимся, что каждый из этих элементов является прямым дочерним элементом тега body.
Три стека элементов, родительские элементы находятся внизу
Если бы мы просмотрели эти элементы HTML в браузере, это выглядело бы примерно так:
Заметили что-нибудь странное со слоями?
Заметили что-нибудь интересное?
Во-первых, почему blue-child-2 ниже всего остального? Он имеет z-index в миллион, поэтому он должен быть сверху, правда?
Кроме того, почему green-child-1 появляется поверх всего, хотя у него z-index 2? Разве мы не говорили, что более высокие z-индексы «выигрывают» над более низкими z-индексами?
Начнем с green-child-1. Поскольку его родительский элемент — green-parent — имеет z-index 999 , мы ожидаем, что green-parent также будет выше всего остального. Но если вспомнить наше первое предупреждение об использовании z-index, это не повлияет на статически позиционированные элементы. Это означает, что green-child-1 является частью контекста корневого стека, и он измеряется против red-parent и blue-parent, единственных других двух элементов в корневом слое стека. Он имеет более высокий z-index чем тот, и он отображается сверху.
Понимание того, что red-parent и blue-parent каждый создают свои собственные локальные контексты стека, также помогает понять, почему blue-child-2 отображается ниже red-parent, хотя его z-index намного выше. Поскольку z-index управляет только позицией элемента в локальном контексте стека, blue-child-2 определенно будет выше всех детей blue-parent. Но у red-parent более высокий z-index, чем у blue-parent, все элементы внутри red-parent будут отображаться выше, чем blue-parent, независимо от их z-index.
Чтобы отобразить blue-child-2 над red-parent нам действительно пришлось бы изменить нашу структуру HTML, чтобы получить blue-child-2 из текущего локального контекста стека и в контекст корневого стека (или, по крайней мере, в стеке контекста, который выше red-parent).
Такие вещи часто могут быть сложными (даже вероломными) в более крупном приложении, особенно когда вы пытаетесь управлять такими вещами, как семантическая структура HTML, доступность и модульные архитектуры компонентов.
Вы часто будете встречать множество библиотек компонентов, которые реализуют свой многоуровневый пользовательский интерфейс (такие как тултипы и модальные окна), добавляя элементы в тег body а не туда, где вы включили компонент — это в значительной степени сделано для обхода проблемы с контекстом стека. Это гарантирует, что z-index на компонентах, которые в значительной степени полагаются на слои, всегда ссылается на контекст корневого стека, и поэтому можно задать z-index примерно 1000 и полагаться на то, что элемент будет отображаться поверх большинства элементов.
Использование z-index может быть сложным в нескольких сценариях, но когда мы знаем правила того, как он работает внутри, мы обнаруживаем, что он действительно ведет себя вполне предсказуемо. Я бы предположил, что 99% путаницы вокруг z-index проистекает из непонимания двух подводных камней, которые мы обсуждали.
Быстро вспомним эти 2 предостережения.
z-index работает только с элементами, которые имеют значение position кроме static.
z-index применяется только к позиции элементов в контексте стека, к которому он принадлежит.
Надеюсь, что понимание внутреннего устройства z-index дает вам уверенность при создании многоуровневых UI с их различным ловушкам. Изучение z-index и слоев стека было очень полезно для меня для систематизации своего подхода к разработке UI – знать, какое число назначать намного лучше, чем просто бросать значения z-index.