Статьи

Совет: как z-index и Auto Margins работают во Flexbox

Flexbox хорошо известен тем, что решает такие распространенные проблемы, как липкие колонтитулы и столбцы одинаковой высоты. Помимо этих возможностей, он также предоставляет несколько других полезных функций, которые не так популярны. Давайте рассмотрим два из них!

Flexbox и z-index

Как вы, наверное, уже знаете, свойство z-index работает только для позиционированных элементов. По умолчанию все элементы имеют position: static и не позиционируются. Элемент «позиционируется», когда его свойство position установлено на relative , absolute , fixed или fixed .

Однако «непозиционированный» элемент, такой как элемент flex, также может получить свойство z-index . Спецификация CSS Flexible Box Layout гласит:

Элементы Flex рисуют точно так же, как и встроенные блоки [CSS21], за исключением того, что порядок документов с измененным порядком используется вместо порядка необработанных документов, а значения z-index, отличные от auto, создают контекст стека, даже если позиция статическая.

Чтобы понять это поведение, рассмотрим следующий пример:

Здесь мы определяем два элемента: элемент .back элемент .back . У элемента .front есть один дочерний элемент, поле с номером «1». Сам элемент .front абсолютно позиционирован. В частности, он имеет position: fixed и охватывает весь видовой экран.

Наш элемент .back представляет собой гибкий контейнер. Он содержит два дочерних элемента — поля с номерами «2» и «3». Основываясь на том, что мы обсуждали выше, мы можем установить свойство z-index его flex-элементов, даже если они не являются позиционированными элементами (то есть они имеют position: static ).

Обратите внимание, что когда мы добавляем z-index: 2 к элементам flex, нажимая кнопку в демонстрационном примере выше, они располагаются поверх элемента .front .

Flexbox и Auto Margins

Применяя автоматические поля для гибких элементов, мы можем решать общие шаблоны пользовательского интерфейса. Для начала давайте предположим, что мы хотим построить этот типичный макет заголовка:

Что мы будем строить

Чтобы построить его, мы будем использовать flexbox. Никаких поплавков, фиксированной ширины или чего-то в этом роде.

Вот наша разметка:

 <header> <nav> <h1 class="logo">LOGO</h1> <ul class="menu"> <li> <a href="">About</a> </li> <li> <a href="">Projects</a> </li> <li> <a href="">Contact</a> </li> </ul> <ul class="social"> <li> <a href="">Facebook</a> </li> <li> <a href="">Twitter</a> </li> </ul> </nav> </header> 

Наш CSS выглядит так:

 header { background: #333; } nav { display: flex; align-items: center; width: 90%; max-width: 1200px; margin: 0 auto; } .menu { margin-left: 60px; margin-right: auto; } 

В этом примере наш элемент nav — это гибкий контейнер, а логотип, главное меню и социальное меню — элементы flex. Как видно из предыдущей визуализации, первые два элемента flex выровнены по левой стороне контейнера flex вдоль главной оси. Напротив, социальное меню выровнено по правому краю своего родителя вдоль главной оси.

Один из способов добиться этого пользовательского выравнивания — добавить margin-right: auto в главное меню. Всего одной строкой кода мы можем переопределить выравнивание по умолчанию для социального меню и сдвинуть его вправо от контейнера. Точно так же мы используем свойство align-self чтобы переопределить выравнивание по умолчанию для гибкого элемента вдоль поперечной оси.

Помимо авто-полей, есть второй метод, который мы можем использовать для создания желаемого макета. Сначала мы удаляем свойство margin-right из главного меню, а затем добавляем в него flex-grow: 1 .

Хотя результат в обоих случаях кажется одинаковым, есть одно большое отличие. При первом решении наше меню имеет начальную рассчитанную ширину. Так, например, когда ширина области просмотра равна 1100px, ширина меню будет выглядеть примерно так:

Ширина нашего меню автоматического выбора полей

С другой стороны, со вторым решением ширина меню flex-grow: 1 потому что мы указываем flex-grow: 1 . Вот соответствующая ширина, когда ширина области просмотра составляет 1100 пикселей:

Ширина нашего меню с flex-grow 1

Демоверсия Codepen:

Давайте теперь предположим, что мы хотим изменить макет заголовка. Вот новый желаемый:

Наш заголовок реализован вертикально

Разметка остается прежней. Мы просто делаем несколько изменений в CSS:

 nav { background: #333; display: flex; flex-direction: column; height: 100vh; width: 180px; padding: 20px; box-sizing: border-box; } .menu { margin-top: 60px; margin-bottom: auto; } 

В этом примере обратите внимание, что социальное меню выровнено по нижнему краю его родителя. Опять же, это делается путем добавления margin-bottom: auto в главное меню. Конечно, мы также можем использовать flex-grow: 1 , но это решение увеличит высоту меню.

Посмотрите демоверсию Codepen ниже:

Следует также помнить, что если мы определим свойство justify-content в любом из наших примеров, мы не увидим никакой визуальной разницы. Это происходит потому, что мы используем авто поля для выравнивания элементов flex. Только когда мы удалим авто поля, вступит в силу свойство justify-content . Согласно спецификации :

Если свободное пространство распределяется по автоматическим полям, свойства выравнивания не будут действовать в этом измерении, потому что поля украли все свободное пространство, оставшееся после сгибания.

Далее, давайте создадим новый вариант нашего заголовка:

Вариация в заголовке

Несомненно, это может быть легко достигнуто установкой justify-content: space-between для гибкого контейнера. Но опять же, мы можем создать тот же макет с автоматическими полями. Все, что нам нужно сделать, это применить margin: 0 auto к главному меню.

Демоверсия Codepen:

Вывод

В этой статье мы рассмотрели два малоизвестных совета по flexbox. Перед закрытием давайте подведем итоги:

  • Мы можем применить свойство z-index для гибких элементов, даже если они имеют position: static .
  • Мы можем использовать автоматические поля для достижения настраиваемого выравнивания наших изгибаемых элементов по главной оси.

Если вы использовали какие-либо из этих советов в своих проектах, сообщите нам об этом в комментариях ниже.