z-index

Что такое z-index

Это css-свойство элемента, которое определяет его положение относительно других элементов по оси Z. Оно применяется только для элементов с позиционированием absolute, fixed, sticky или relative (соответствиенно при отсутствии указанного свойства position, добавление z-index'а никак не будет влиять на положение элемента).
 
Есть обычный порядок наложения элементов - это когда последующий перекрывает предыдущий с учетом родительской вложености. Но с помощью z-index'ов мы можем его изменять. Это настолько просто, что многие разработчики пользуются этим, не задумываясь о том, как важно структурировать z-index'ы, чтобы они не испортили проект в будущем.

Пример

Рассмотрим какой-нибудь стандартный проект на jQuery. Шучу-шучу, пусть будет проект на React'е. Но в целом это не принципиально. Допустим, у нас есть модальное окно, галерея и флэш-сообщения.

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

1. Бибилотека react-responsive-modal выставляет один z-index: 1000 для перекрывающего слоя, остальное "само" позиционируется внутри:


2. Плагин jQuery Modal задает z-index: 1 для подложки и z-index: 2 для модального окна:


Как видим из примера, нет единого подхода для определения z-index'ов в модальных окнах. Нет одного универсального способа сказать, что 1000 - это единственно верное число для z-оси. Так как 1 и 2 однозначно плохие варианты, потому что у нас могут быть на странице слайдер, анимация, placeholder, у которых тоже может быть значение 1, 2 и даже 3. И они будут перекрывать модальные окна.

Можем ли мы вывести, что 1000 - достаточное значение для модалок? Достаточно большое, чтобы удовлетворить все наши прихоти? Конечно, используя сторонние библиотеки, нам ничего не стоит переопределить свойства согласно нашему дизайну. Но как часто мы меняем z-index'ы? И если менять, то на какие?

Давайте для начала добавим в наш проект галерею. Возьмем стандартную, добротную и всеми любимую lightGallery и посмотрим на z-index'ы, которые она проставляет по умолчанию.

z-index:
1050 - общая перекрытие
1060 - для отдельного слайда
1080 - кнопки навигации влево-вправо, столько же подписи и пагинация
1081 - оверлей
1082 - верхняя навигация
1083 - статус прогресса загрузки



Выглядит немного странно. Где-то значения увеличиваются на десятки, а где-то - на единицы. Но самое главное - это то, что начинается с 1050. Это значит, что он перекроет наше модальное окно с z-index: 1000. Отлично!

Звучит классно. Но что если нам надо в галерею добавить слайд с кнопкой, которая вызывает модалку? Это не просто мое предположение, так было в одном из проектов, над которыми я работала. Какое значение должно быть тогда у модалки? z-index: 1090 или 1100? Может сразу поставить 2000 чтобы предупредить возможные коллизии?

Хорошо. А теперь добавим в проект флэш-сообщения. Надеюсь, вы уже начинаете догадываться, что вы больше не контролируете z-index'ы? Это они навязывают вам свою структуру. А вы ходите по разным файлам с галереей, модалками, флэш-сообщениями, анимацией  и пытаетесь привести весь этот зоопарк в порядок, каждый раз сжимая кулачки, надеясь, что нигде в другом месте ничего не выползет. И начинают появляться значения 1100, 10000, 10100...

Гомеопатическая панацея

Вы все еще думаете, что можете что-то контролировать, когда у вас есть sass. Вы определяете в файле с модалками переменную для общего перекрывающего слоя и внутреннего блока:

   $modal-overlay: 1000;
   $modal-under-overlay: $modal-overlay - 1;
   $modal-content: $modal-overlay + 1;

Но это лечение симптомов, а не болезни. Потому что помогает только для одного связного блока - блока модального окна. И никак не отражает отношение к другим модулям.

Оно же является источником заражения десятками. Что это значит? Чтобы определить другую переменую в другом модуле, нужно отступить от переменной $modal-overlay в обе стороны по 10 или 20 единиц. Это хорошо видно на примере lightSlider'а. Мифическя цифра 1050 у них появилась из предположения, что 1000 будет использована для модалок и вообще как самое большое число, а относительная флуктуация в ее пределах 10-20, но для верности они взяли отступ в 50. Итого вышло 1050.

Лично меня пугает не мифичность числа, потому что я знаю его происхождение, а его разрядность. 100 - это уже много. Я не могу представить, что будет 100 потребностей в перекрытии элементов!

Моя серебряная пулька

Для себя я нашла способ контроля - это вынести все z-index'ы в отдельный файл как переменные. Вы же выносите базовые цвета, типографику, размеры. Почему бы не сделать то же самое и для z-index'ов?

Итого мой файл "_z-index.scss" в одном из проектов выглядит так:

   $zIndexSubzero:         -1;
   $zIndexZero:            0;
   $zIndexMin:             1;
   $zIndexInputValue:      2;
   $zIndexInputAbove:      3;
   $zIndexFormCover:       4;
   $zIndexStickyTop:       5;
   $zIndexNavigation:      6;
  
$zIndexInfoBar:         7;
  
$zIndexPopupOverlay:    8;
   $zIndexPopup:           9;
   $zIndexConsentedCookie: 10;

Чем это удобно:
  1. Контроль. Все переменные z-index'ов находятся в одной файле, поэтому сразу видна иерархия.
  2. Легкоизменяемость. Нужно сделать флэш-сообщения поверх модалок? Просто меняете местами нужные строки с сохранением нумерации сверху вниз по возрастанию.
  3. Прозрачность. Все z-index'ы хранятся здесь. Нет никаких локальных переменных в других файлах. 
  4. Мелкая разрядность z-index'ов. Не нужно создавать значения в 100 и 1000 единиц. Все помещается в пределах 10-20 в зависимости от проекта.
  5. Наименование. По названию сразу понятно где используется каждая переменная. Исключение составляют первые три; они носят общий характер и, как правило, используются для позиционирования элемента относительного базового элемента или 0.

Выводы

На самом деле z-index'ы - это такая мелочь, на которую не сразу обращаешь внимание. Только после того, как проект разрастается и появляются новые слои перекрытия элементов, начинаешь задумываться, что что-то с ними не так. Но часто даже это не может послужить поводом для рефакторинга.

Я придумала эту систему в очень крупном проекте, том самом с галереей, попапами, тултипами и флэш-сообщениями. Но там я сохранила в переменных десятичную градацию. Сейчас же понимаю, что это не нужно, достаточно единичных. Не нужно оставлять себе лазеек для обхода этой системы, нужно просто уметь ею пользоваться.

В текущем же проекте у меня все идеально ^_^  Пример выше - тому подтверждение. И я каждый раз радуюсь, глядя на этот файл, потому что сразу вижу какую большую головную боль он мне решает с z-index'ами.

Гениальное - просто!
Пользуйтесь в удовольствие =)


Комментарии

Анонимный написал(а)…
По-моему, классная идея про отдельный файл! Потому как реально обычно хаос с з-индексами. А есть ведь ещё сторонние библиотеки - тогда вообще весело :)

Популярные сообщения из этого блога

Стайлгайд и компонентная разработка

Прогноз погоды в консоли

Погружение в React Native: навигация, работа оффлайн, пуш нотификации