Уроки Flexbox

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

Сложность

Простая система сеток

На сегодняшний день, при помощи системы сеток создаются большинство сайтов. Flexbox позволяет действительно легко реализовать мощную и масштабируемую сетку с помощью нескольких строк CSS кода.

Предположим, у нас есть такая разметка:

<div class="grid">
  <div class="grid__row">
    <div class="grid__item">1</div>
    <div class="grid__item">2</div>
    ...
  </div>
</div>

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

<div class="grid">
  <div class="grid__row">
    <div class="grid__item">1</div>
    <div class="grid__item">2</div>
  </div>
  <div class="grid__row">
    <div class="grid__item">1</div>
    <div class="grid__item">2</div>
    <div class="grid__item">3</div>
  </div>
  <div class="grid__row">
    <div class="grid__item">1</div>
    <div class="grid__item">2</div>
    <div class="grid__item">3</div>
    <div class="grid__item">4</div>
  </div>
</div>

Давайте теперь посмотрим на CSS. Я добавлю некоторые свойства чисто для эстетики (рамки и отступы):

.grid {
  border: solid 1px #e7e7e7;
}

.grid__row {
  display: flex;
}

.grid__item {
  flex: 1;
  padding: 12px;
  border: solid 1px #e7e7e7;
}

Здесь я добавил свойство display: flex для контейнера .grid__row, чтобы определить его в качество flex контейнера, каждый его подпункт является flex элементом. Все элементы, у которых установлено свойство flex: 1, будут занимать одинаковое количество пространства по отношению к ширине контейнера. Теперь вы можете иметь столько строк, сколько захотите и для каждой строки можете добавить произвольное количество вложенных контейнеров.

Если необходимо чтобы элементы сетки находились в расположении столбца, а не строки, мы можем просто добавить свойство flex-direction: column для контейнера .grid__row. Разметка может выглядеть следующим образом:

<div class="grid">
  <div class="grid__row grid__row--sm">
    <div class="grid__item">1</div>
    ...
  </div>
  <div class="grid__row grid__row--md">
    <div class="grid__item">1</div>
    ...
  </div>
  <div class="grid__row grid__row--lg">
    <div class="grid__item">1</div>
    ...
  </div>
</div>

CSS код:

.grid {
  border: solid 1px #e7e7e7;
}

.grid__row {
  display: flex;
  flex-direction: column;
}

.grid__item {
  flex: 1;
  padding: 12px;
  border: solid 1px #e7e7e7;
}

@media all and ( min-width: 480px ) {

  .grid__row--sm {
    flex-direction: row;
  }

}

@media all and ( min-width: 720px ) {

  .grid__row--md {
    flex-direction: row;
  }

}

@media all and ( min-width: 960px ) {

  .grid__row--lg {
    flex-direction: row;
  }

}

И вуаля! У нас есть простая адаптивная система сеток, в которой вы можете даже создавать вложенные сетки:

<div class="grid">
  <div class="grid__row grid__row--sm">
    <div class="grid__item">
      <div class="grid">
        <div class="grid__row grid__row--lg">
          <div class="grid__item">Nested 1</div>
          ...
        </div>
      </div>
    </div>
    <div class="grid__item">2</div>
  </div>
  <div class="grid__row grid__row--md">
    <div class="grid__item">1</div>
    ...
  </div>
</div>

Разметка макета Святого Грааля

Макет Святого Грааля довольно известный прием в веб-дизайне, даже в эпоху современных веб-приложений, этот макет по-прежнему играет очень важную роль в Интернете. В 2006 году, макет Святого Грааля был разработан и задокументирован на A List Apart. Здесь используются float, отрицательные margin и min-width, чтобы обеспечить комбинированные размеры, которые не будут конфликтовать и нарушать расположение элементов дизайна.

С Flexbox, мы можем определить столбцы или строки, а также явно установить порядок элементов в CSS, даже если в разметке они находятся совсем в другом порядке. Вот типичная разметка Святого Грааля:

<body class="holy-grail">
  <header class="holy-grail__header"></header>
  <main class="holy-grail__body">
    <div class="holy-grail__content"></div>
    <div class="holy-grail__sidebar holy-grail__sidebar--first"></div>
    <div class="holy-grail__sidebar holy-grail__sidebar--second"></div>
  </div>
  <footer class="holy-grail__footer"></footer>
</body>

Давайте разберем данную разметку:

  1. У нас есть родительский контейнер .holy-grail, а также 3 flex элемента: .holy-grail__header, holy-grail__body и holy-grail__footer.
  2. Эти три элемента, располагаются друг под другом и занимают 100% ширину экрана.
  3. Тело Святого Грааля, у которого есть класс holy-grail__body, является вложенным элементом flex контейнера. Его дочерние элементы будут отображаться в виде столбцов на небольших экранах и в виде строк на больших экранах.

Стиль Святого Грааля:

.holy-grail {
  display: flex;
  flex-direction: column;
}

.holy-grail__header,
.holy-grail__footer {
  flex: 0 0 100%;
}

.holy-grail__body {
  display: flex;
}

.holy-grail__sidebar {
  /* nothing at narrow screens */
}

.holy-grail__sidebar--first {
  order: 1;
}

.holy-grail__sidebar--second {
  order: 3;
}

.holy-grail__content {
  order: 2;
}

@media all and ( min-width: 720px ) {

  .holy-grail__body {
    flex-direction: row;
  }

  .holy-grail__sidebar {
    flex: 0 0 180px;
  }

  .holy-grail__content {
    flex: 1;
  }

}

@media all and ( min-width: 960px ) {

  .holy-grail__sidebar {
    flex: 0 0 240px;
  }

}

Адаптивная навигация с анимированным поиском

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

<nav class="flexy-nav">
  <button id="flexy-nav__toggle" class="flexy-nav__toggle">Toggle Nav</button>
  <ul id="flexy-nav__items" class="flexy-nav__items">
    <li class="flexy-nav__item"><a href="#" class="flexy-nav__link">Item 1</a></li>
    <li class="flexy-nav__item"><a href="#" class="flexy-nav__link">Item 2</a></li>
    <li class="flexy-nav__item"><a href="#" class="flexy-nav__link">Item 3</a></li>
    <li class="flexy-nav__item"><a href="#" class="flexy-nav__link">Item 4</a></li>
  </ul>
  <form action="" class="flexy-nav__form">
    <input class="flexy-nav__search" type="text" placeholder="Type search terms and hit enter...">
  </form>
</nav>

Давайте рассмотри разметку, прежде чем перейдем к CSS. Здесь я добавил основной flex контейнер с классом .flexy-nav. Кнопка работает как переключатель, для навигации я создал неупорядоченный список, а форма имеет строку поиска. Для небольших экранов, необходимо чтобы все три элемента, находились в одной колонке, под которой будет находится строка поиска. Для больших экранов, скроем переключатель, создадим неупорядоченный список с flex контейнером, расположим элементы списка в одну строку и сделаем форму фиксированной ширины. Элементы списка будут равномерно распределены на оставшемся свободном пространстве. При нажатии на поле ввода в поиске, его ширина плавно увеличится, в то время как все элементы списка плавно уменьшатся. CSS код:

/* resets */

input,
button {
  font: inherit;
  border-radius: none;
  box-shadow: none;
  appearance: none;
}

button {
  cursor: pointer;
}

/* nav container */

.flexy-nav {
  display: flex;
  flex-direction: column;
}

/* nav links */

.flexy-nav__items {
  display: none;
  flex: 1;
  flex-direction: column;
  list-style: none;
  margin: 0 0 4px 0;
  padding: 4px;
  text-align: center;
}

.flexy-nav__items--visible {
  display: flex;
}

.flexy-nav__item {
  background-color: #f1f1f1;
  border-bottom: solid 1px #e7e7e7;
}

.flexy-nav__item:last-child {
  border-bottom: 0;
}

.flexy-nav__link {
  padding: 8px;
  display: block;
}

/* nav toggle */

.flexy-nav__toggle {
  margin: 0 0 4px 0;
  padding: 4px;
  color: #fff;
  background-color: #f07850;
  border: none;
}

.flexy-nav__toggle:hover,
.flexy-nav__toggle:focus {
  outline: none;
  background-color: #c93f11;
}

/* nav form */

.flexy-nav__form {
  height: 48px;
}

.flexy-nav__search {
  display: block;
  margin: 0;
  padding: 0 4px;
  width: 100%;
  height: 48px;
  color: #6d6d6d;
  background-color: #fff;
  border: solid 2px #e7e7e7;
}

.flexy-nav__search:focus {
  outline: none;
  border: solid 2px #6d6d6d;
}

/* media queries */

@media all and (min-width: 768px) {
  .flexy-nav {
    flex-direction: row;
  }

  .flexy-nav__items {
    display: flex;
    flex-direction: row;
    margin: 0;
    padding: 0;
    height: 48px;
  }

  .flexy-nav__item {
    flex: 1;
    margin-right: 4px;
    border-bottom: none;
  }

  .flexy-nav__link {
    padding: 0;
    line-height: 48px;
  }

  .flexy-nav__toggle {
    display: none;
  }

  .flexy-nav__form {
    flex: none;
  }

  .flexy-nav__search {
    width: 240px;
    transition: width 0.3s;
  }

  .flexy-nav__search:focus {
    width: 360px;
  }
}

Смена навигации на небольших экранах:

(function() {
  var toggle = document.querySelector("#flexy-nav__toggle");
  var nav = document.querySelector("#flexy-nav__items");
  toggle.addEventListener("click", function(e) {
    e.preventDefault();
    nav.classList.contains("flexy-nav__items--visible") ? nav.classList.remove("flexy-nav__items--visible") : nav.classList.add("flexy-nav__items--visible");
  });
})();

Мы только что создали аккуратную и масштабируемую навигацию с flexbox и добавили форму поиска. Мы можем легко добавлять и удалять ссылки и они автоматически станут нужных размеров.

Центрирование по вертикали

Давайте посмотрим правде в глаза, вертикальное выравнивание в традиционном CSS - отстой. Иногда помогает inline-block, иногда хаки с позицией, ну и конечно же старая, табличная верстка. У них у всех есть свои плюсы и минусы и работают исключительно на магии.

С Flexbox вам не составит труда выровнять элемент по вертикали. Мы рассмотрим два примера, которые связанны с вертикальным центрированием:

  1. Во-первых, мы рассмотрим добавление медиа запросов, в которых разместим аватар пользователя с левой стороны, а имя и дополнительную информацию справой. Для вертикального центрирования воспользуемся Flexbox.
  2. Во-вторых, мы рассмотрим простое вертикальное (и горизонтальное) выравнивание элемента фиксированной ширины и переменной высотой в контейнере. Независимо от того, какой высоты элемент, он все равно будет находиться по центру контейнера.

Давайте начнем с первого примера. Как уже упоминалось ранее, мы должны разместить аватар пользователя слева, а описание справа. Независимо от того, насколько длинное или короткое будет описание, однако нам не нужно, чтобы оно всегда оставалось идеально вертикально относительно аватара. Типичная разметка:

<div class="user">
  <div class="user__avatar"></div>
  <div class="user__description">
    <h2 class="user__username">John Doe</h2>
    <p class="user__excerpt">I'm John Doe...</p>
  </div>
</div>

<div class="user">
  <div class="user__avatar"></div>
  <div class="user__description">
    <h2 class="user__username">Harry Potter</h2>
    <p class="user__excerpt">I'm Harry Potter...with a really long description...</p>
  </div>
</div>

Прежде чем перейти к CSS, примите к сведению, что мы будем использовать свойство, которое мы раньше не видели. Это свойство align-items, оно позволяет нам выровнять элементы по текущей flex линии в перпендикулярном направлении. Другими словами, если flex линия работает по горизонтали, мы можем перевести их относительно перпендикулярной линии. В нашем случае, для центрирования элементов, мы можем просто использовать align-items: center:

.user {
  display: flex;
  align-items: center;
}

.user:last-child {
  margin-bottom: 0;
}

.user__avatar {
  flex: 0 0 96px;
  width: 96px;
  height: 96px;
  background-color: #e7e7e7;
}

.user__description {
  flex: 1;
  margin-left: 24px;
  padding: 12px;
  border: solid 1px #e7e7e7;
}

Все просто, не правда ли!? Вы можете изменить стиль текста, изменить описание, размер аватара на свой вкус. Это не имеет значения, функциональность не поменяется.

Перейдем ко второй части вертикального выравнивания. На этот раз, давайте представим, что у нас есть изображение баннера в верхней части разметки, внутри баннера, мы хотим добавить небольшой заголовок. На небольших экранах, высота баннера будет 180px, она будет увеличиваться до 480px в зависимости от размера экрана. Нам нужно чтобы заголовок находился внутри этого баннера, идеально по центру, по горизонтали и по вертикали.

<div class="banner">
  <div class="banner__content">
    <h2 class="banner__title">Symmetrical Perfection</h2>
    <span class="banner__sub">A beautiful sight, achieved with flexbox.</span>
  </div>
</div>

На этот раз мы добавим свойство justify-content, которое позволит нам распределить пространство вокруг элементов вдоль flex линии.

.banner {
  display: flex;
  align-items: center;
  justify-content: space-around;
  height: 180px;
  background-color: #e7e7e7;
}

.banner__content {
  text-align: center;
}

.banner__title,
.banner__sub {
  margin: 0;
  padding: 0;
  line-height: 1.5;
}

@media all and ( min-width: 480px ) {

  .banner {
    height: 240px;
  }

}

@media all and ( min-width: 768px ) {

  .banner {
    height: 360px;
  }

}

@media all and ( min-width: 960px ) {

  .banner {
    height: 480px;
  }

}

Независимо от высоты баннера, содержание останется вертикально и горизонтально по центру, благодаря силе flexbox.

Поддержка и Префиксы

Flexbox поддерживается всеми современными браузерами, в том числе Internet Explorer 10 и выше. Если вы разрабатываете современные веб-приложения, flexbox станет идеальным инструментом для вас. Если вы разрабатываете или изменяете свой веб-сайт, проанализируйте вашу целевую аудиторию. Вероятнее всего, что 99% вашей аудитории используют современные браузеры.

В настоящее время существует большое количество flexbox префиксов и это сводит с ума. Лично я использую Gulp для автоматического расставления префиксов в CSS коде. В одной из следующих статей, мы рассмотрим работу Gulp совместно с Flexbox.

ДЕМО СКАЧАТЬ

 

Перевод статьи Building With Flexbox

Тэги: menusearchflexboxnavigation

Вход

Уважаемый пользователь! Мы обнаружили, что вы используете AdBlock и вынуждены скрыть часть материалов на нашем сайте. Siteacademy существует и развивается за счет доходов от рекламы. Просим внести наш сайт в список исключений или отключить Блокировщик рекламы на нашем сайте.