В последнее время мы видели довольно много статей об управлении z-index
- Нахальное управление z-index для сложных макетов от Jackie Balzer в журнале Smashing Magazine
- Sass и z-index: (немного) лучший способ Дуга Эвери в Viget
- Обработка z-index Крисом Койером в CSS-Tricks
Хотя эта последняя статья Криса Койера, безусловно, помогла мне начать работу с моим решением, ни одна из предыдущих статей с технической точки зрения не привела к представлению простого и удобного в использовании метода.
Отсюда и эта статья. Я проведу вас по моей очень простой системе, покажу, как я ее построил и как вы можете использовать ее в своих проектах сегодня .
Зачем нужно управлять значениями z-index
Сначала давайте ответим на этот вопрос: зачем нам управлять z-index с помощью Sass? Мы не видим, как появляются многочисленные статьи об управлении padding
Так зачем делать это для z-index
Ну, это связано с тем, что z-index
Более того, принятие значения без единиц измерения между -infinity и бесконечностью дает вам много поводов облажаться.
Поэтому вместо использования таких значений, как 9999999
Что такое концепция?
Концепция здесь в основном одинакова во всех статьях по этой теме: Создайте функцию, которая принимает ключевое слово в качестве аргумента, которое сопоставляется со значением. Это значение является z-index, который будет распечатан.
Джеки Балзер использует списки. Дуг Эвери использует смесь списков и карт. Крис Койер использует карты. На самом деле, решение Криса Койера действительно близко к тому, что я получил в итоге, за исключением того, что ему не хватает этого небольшого дополнительного, что делает всю систему великолепной в использовании.
В конечном итоге мы придем к этому:
.element {
z-index: z("modal");
}
Зачем использовать функцию, а не миксин?
Даг Эвери использует миксин в своей статье. Основное различие с функцией заключается в способе ее использования:
// With a mixin
// Me no likey!
.element {
@include z("modal");
}
Хотя я понимаю, что это действительно вопрос предпочтений, я действительно стараюсь не использовать миксины, когда выводится только одно свойство CSS. Функция является идеальным вариантом использования для чего-то подобного.
Открытие зверя
Поэтому нам нужна функция, принимающая один аргумент. Не стесняйтесь называть это как угодно; Я пошел со layer
@function z($layer) {
// ... where the magic happens.
}
Что делает функция в любом случае? Он будет искать заданный аргумент в карте слоев, чтобы увидеть, соответствует ли он значению z-index
Если это так, он возвращает значение, иначе он возвращает сообщение об ошибке. Итак, нам нужна карта.
$z-layers: (
"goku": 9001,
"shoryuken": 8000,
"default": 1,
"below": -1,
"bottomless-pit": -9000
);
Две вещи здесь:
- Мне нравится, когда мои переменные конфигурации находятся вне их в миксин / функциях, в отдельном файле (например,
_config.scss
Не стесняйтесь перемещать его внутри функцииz()
- Вы можете добавить / удалить / обновить столько ключей / значений, сколько хотите, это только примеры.
Теперь вернемся к нашей функции.
@function z($layer) {
@return map-get($z-layers, $layer);
}
На данный момент мы сделали не больше, чем синтаксический сахар для map-get($z-layers, ...)
Это на самом деле довольно круто, потому что ввод этой вещи снова и снова может быстро стать раздражающим.
Если ключ существует на карте, он вернет значение индекса, сопоставленное с ним. Если ключ не был определен, он вернет null
Когда свойство имеет null
Таким образом, в случае, если вы вызываете неизвестный ключ, Sass просто молча провалится, что не идеально. Давайте улучшим это, используя директиву @warn
@function z($layer) {
@if not map-has-key($z-layers, $layer) {
@warn "No layer found for `#{$layer}` in $z-layers map. Property omitted.";
}
@return map-get($z-layers, $layer);
}
Там. Если вы запрашиваете неопределенный ключ (например, «SitePoint»), Sass выведет в консоли следующее:
«Не найден слой для
SitePoint
Собственность опущена. »
Довольно круто, правда?
Играя с новой игрушкой
Теперь, когда мы закончили строить нашу функцию, пришло время поиграть с ней! Как вы видели в начале этой статьи, использовать функцию довольно просто:
.modal {
// ...
z-index: z("modal");
}
.modal-overlay {
// ...
z-index: z("modal") - 1;
}
Идея состоит в том, чтобы всегда использовать эту функцию при определении значений z-index
Использование его только часть времени не имеет смысла и в значительной степени убивает систему.
Кроме того, я думаю, что лучше держать карту слоя максимально светлой. Чем больше слоев вы добавляете, тем больше сложность Z-шкалы. Попробуйте найти пару повторяющихся значений, сопоставить их с общими ключевыми словами, и вам будет хорошо.
Продвигая вещи дальше с помощью вложенных контекстов
Вы, вероятно, не без знания, что значения z-index
Все они связаны с их собственным стековым контекстом. Это в основном означает, что если вы попытаетесь заставить элемент из Context-A появиться поверх элемента из Context-B, но Context-B будет нарисован поверх Context-A, то даже индекс более девяти тысяч не будет довольно.
Примечание. Для получения дополнительной информации о контекстах стека и z-index
эту потрясающую статью Филиппа Уолтона.
Теперь, если мы хотим, чтобы наша система знала контексты стекирования, мы могли бы иметь вложенные карты. Например, если наш modal
$z-layers: (
"goku": 9001,
"shoryuken": 8000,
"modal": (
"base": 500,
"close": 100,
"header": 50,
"footer": 10
),
"default": 1,
"below": -1,
"bottomless-pit": -9000
);
Проблема в том, что мы не можем легко получить значение из вложенных карт, ни в коем случае не используя map-get
К счастью, создать такую функцию легко:
@function map-deep-get($map, $keys...) {
@each $key in $keys {
$map: map-get($map, $key);
}
@return $map;
}
Достаточно. Просто, не правда ли? Теперь мы можем написать наш модальный модуль так:
// New stacking context
.modal {
position: absolute;
z-index: z("modal", "base");
.close-button {
z-index: z("modal", "close");
}
header {
z-index: z("modal", "header");
}
footer {
z-index: z("modal", "footer");
}
}
Что даст следующий результат:
.modal {
position: absolute;
z-index: 500;
}
/* This is `100` in the modal stacking context */
.modal .close-button {
z-index: 100;
}
/* This is `50` in the modal stacking context */
.modal header {
z-index: 50;
}
/* This is `10` in the modal stacking context */
.modal footer {
z-index: 10;
}
В будущем!
Когда-нибудь в светлое будущее, о котором мы все мечтаем, у нас будут собственные переменные CSS. Тогда нам все это больше не нужно. Вместо этого вот что произойдет:
:root {
--z-goku: 9001;
--z-shoryuken: 8000;
--z-modal: 500;
--z-default: 1;
--z-below: -1;
--z-bottomless-pit: -9000;
}
.modal {
z-index: var(--z-modal);
}
Видеть? Практически то же самое, за исключением того, что это var()
z()
--key
key
Немного больше времени для ввода и, возможно, немного более хаотично, поскольку это отдельные переменные, а не карта. Но он хорошо справляется с работой, сохраняя при этом нативность.
Последние мысли
Я не знаю как вы, но я думаю, что это прекрасный метод для обработки z-index
Мало того, что все организовано с каждым z-индексом, хранящимся в карте слоев, но также довольно легко иметь небольшие вариации с операторами, как мы видели в нашем последнем примере.
Вот и все. Вот демоверсия Sassmeister, чтобы вы начали. Нет причин не применять это в ваших проектах, начиная с сегодняшнего дня.