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



Введение


Некоторое время назад я написал ознакомительную статью про flexbox на сайте SitePoint. В данной статье я постарался выяснить и ответить на вопрос:

А готовы ли мы использовать flexbox?

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

Да, мы готовы использовать flexbox!

Если вы еще не знакомы с flexbox, то вот небольшое пояснение. CSS модуль построения гибкой разметки — это модуль, позволяющий легко размещать блоки на экране, в пределах выделенного пространства. Это большое достижение по сравнению с классической блочной моделью, т.к. flexbox позволяет вообще не использовать свойство float. Блоки могут быть объединены в строки или разбиты на колонки. Для каждого flexbox-элемента может быть задан определенный порядок. А также можно сразу управлять выравниванием, отступами и размерами этих элементов.

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

  • Простая сеточная система
  • Разметка трехколоночного сайта
  • Резиновая навигация с изменяющейся шириной поля поиска
  • Два разных варианта вертикального выравнивания

Хорошо, давайте приступать!

Простая сеточная система


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

Представьте, что у нас есть следующая простая разметка:

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

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

<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-элементам, мы заставляем их занимать равное количество места относительно общей ширины контейнера. Теперь у вас может быть сколько угодно строк в сетке, а в каждой из них может быть свое собственное количество элементов. И это будет простая полностью отзывчивая сеточная система без всякого дополнительного CSS.

А что можно сказать насчет breakpoint-ов и колоночной разметки? Если мы хотим, чтобы элементы сетки выстраивались в колонки, а не в строки, то мы можем просто объявить свойство 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;
  }

}

И вуа-ля. Супер-простая отзывчивая сеточная система размером всего в несколько CSS строк. Эта система настолько непробиваемая, что вы даже можете вкладывать сетки друг в друга, не заботясь о последствиях:

<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>

В моем демо-примере разметка находится внутри документа, поэтому в ней нет тегов body или main, как это показано выше. Но в данном случае, нас интересуют имена классов и сами разделы нашей разметки, а не непосредственно сами элементы. В частности, обратите внимание на классы, которые используются для двух боковых колонок, и на тот порядок, в котором они следуют в разметке. Давайте последовательно рассмотрим, что здесь происходит:

  1. У нас есть родительский контейнер, .holy-grail, а в нем у нас находится три flex-элемента. Это элементы с классами .holy-grail__header, holy-grail__body и holy-grail__footer.
  2. Данные три элемента расположены друг над другом и занимают 100% от ширины экрана. Таким образом, для flex-контейнера должно быть задано колоночное направление.
  3. Тело нашей разметки, .holy-grail__body, является внутренним flex-контейнером. Его дочерние 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 {
  /* ничего на небольших экранах */
}

.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;
  }

}

Это действительно настолько просто! Как я уже упоминал, мы изначально определяем два flex-контейнера (для небольших экранов). Для первого breakpoint-а мы изменяем flex-direction для обертки колонок на строчное, а боковым колонкам задаем ширину 180px, используя сокращенную запись — свойство flex. Данная запись позволит нам ограничить значения для свойств flex-grow и flex-shrink, а также явно указать ширину. Для контента используется свойство flex: 1, чтобы он заполнял доступное пространство. Расположение flex-элементов в нужном порядке также оказалось пустяком благодаря свойству order. Пожалуй, остались только дополнительные стили, которые вы захотите добавить с эстетической точки зрения… а в остальном это действительно просто и эффективно. А упомянул ли я о том, что по умолчанию flexbox создает колонки одинаковой высоты? Взгляните на этот демо-пример.

Резиновая навигация с изменяющейся шириной поля поиска


В нашем следующем примере мы будем создавать нечто веселое, включающее красивый переход. Мы создадим резиновую навигацию, которая растягивается на всю ширину, а в ней мы разместим поле поиска, которое будет плавно растягиваться в состоянии фокуса. Используя силу 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. Кнопка используется в качестве переключателя, в ненумерованном списке содержатся пункты основного меню, а в форме содержится поле поиска. Для небольших экранов нам нужно использовать колоночную разметку для всех трех элементов, а также нам нужно, чтобы каждый пункт меню располагался в отдельной колонке. На широких экранах нам нужно спрятать кнопку-переключатель, выстроить элементы списка в строку и задать для формы фиксированную ширину. Элементы списка будут равномерно распределены среди оставшегося пространства. Когда мы переключаемся на текстовое поле (поле поиска), нам бы хотелось, чтобы оно плавно растягивалось по ширине, а все элементы списка, наоборот, плавно сужались. Вот CSS:

/* сброс стилей */

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

button {
  cursor: pointer;
}

/* контейнер навигации */

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

/* пункты меню */

.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;
}

/* переключатель меню */

.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;
}

/* форма для поля поиска в навигации */

.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 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;
  }
}

Как и обещал, вот, до смешного простой, кусочек JavaScript кода, который позволит нам показывать/скрывать навигацию на небольших экранах:

(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, а также встроили плавный переход при изменении ширины у поля поиска. Мы можем сколько угодно добавлять или удалять ссылки, а также «на лету» изменять размеры поля поиска. И при этом функциональность нашего меню нисколько не пострадает. Ах, вот они прелести 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. Вот CSS:

.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-линии. А вот CSS:

.
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 поддерживается во всех современных браузерах, включая IE10 и выше. Если вы занимаетесь созданием современных веб-приложений, то flexbox — это мощный инструмент, и я очень рекомендую его использовать. Если вы создаете или переделываете веб-сайт, то проверьте статистику посещаемости, чтобы узнать вашу аудиторию. В настоящее время есть вероятность того, что около 99% вашей аудитории будет использовать современные браузеры.

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

Заключение


Вот и все! На этом я заканчиваю данную статью. Если вы хотите найти реальный сайт, на котором используется flexbox, то можете даже и не начинать поиски. На новом сайте callmenick.com flexbox используется практически везде! Спасибо, что прочли статью до конца. Не забудьте, что вы можете посмотреть демо-примеры, а также скачать исходники по нижеприведенным ссылкам. Если у вас есть какие-либо вопросы, замечания или пожелания, оставьте их, пожалуйста, в комментариях.

Ссылка на оригинал статьи: http://callmenick.com/post/flexbox-examples

Комментарии (7)


  1. Greatschemer
    06.05.2015 10:56
    -1

    Спасибо за перевод. Давно интересовался flexbox-ом, но никак руки не доходили покопаться.
    Не поленился проделать примеры упражнений, приведенных вами.
    Конечно не обошлось без ошибок (по вине автора).
    Во втором примере «Разметка трехколоночного сайта» привожу правильный код.

    HTML:

    <div class="holy-grail">
          <header class="holy-grail__header">
            <h1>This is the header</h1>
          </header>
          <div class="holy-grail__body">
            <div class="holy-grail__content">
              <h2>This is the main content</h2>
              <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Earum sequi nisi aliquam, ipsum tempore illo recusandae. Odit consectetur totam hic eius, commodi molestiae voluptates porro vel laboriosam, tempore, nostrum quis. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dignissimos mollitia vero facilis, deserunt omnis, fugit quod nam, neque iusto reprehenderit tempora. Atque fuga inventore perferendis harum et culpa repudiandae, laudantium. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Assumenda dolorum ea at nobis dolores doloremque incidunt voluptate, dignissimos, veniam soluta temporibus sint error odit nesciunt ducimus excepturi quam, itaque eos! Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ex, molestiae, delectus nemo quibusdam odit fugiat velit facilis soluta odio ipsam ullam alias repellat. Ipsam porro voluptate adipisci nihil assumenda, ab.</p>
            </div>
            <div class="holy-grail__sidebar holy-grail__sidebar--first">
              <h4>Sidebar 1</h4>
            </div>
            <div class="holy-grail__sidebar holy-grail__sidebar--second">
              <h4>Sidebar 2</h4>
            </div>
          </div>
          <footer class="holy-grail__footer">
            <small>This is the footer</small>
          </footer>
        </div>
    


    И оригинальный CSS-файл (по-ходу для всех примеров сразу):
    .grid, .grid__item {
        border: 1px solid #e7e7e7;
    }
    .flexy-nav, .flexy-nav__items, .grid__row, .holy-grail, .holy-grail__body {
    }
    .banner, .user {
        align-items: center;
    }
    .component__section {
        margin: 0 24px 48px;
    }
    .component__section:last-child {
        margin-bottom: 0;
    }
    .component__sub-title {
        color: #818181;
        font-size: 22px;
        font-weight: 300;
        margin-bottom: 12px;
        text-align: center;
    }
    .grid__row {
        display: flex;
        flex-direction: column;
    }
    .grid__item {
        flex: 1 1 0;
        padding: 12px;
    }
    @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;
    }
    }
    .holy-grail {
        display: flex;
        flex-direction: column;
    }
    .holy-grail__footer, .holy-grail__header {
        background-color: #f07850;
        flex: 0 0 100%;
        padding: 12px;
        text-align: center;
    }
    .holy-grail__footer small, .holy-grail__header h1 {
        color: #fff;
    }
    .holy-grail__body {
        display: flex;
        flex-direction: column;
    }
    .holy-grail__sidebar {
        background-color: #e7e7e7;
        padding: 12px;
    }
    .holy-grail__sidebar--first {
        order: 1;
    }
    .holy-grail__sidebar--second {
        order: 3;
    }
    .holy-grail__content {
        order: 2;
        padding: 12px;
    }
    @media all and (min-width: 720px) {
    .holy-grail__body {
        flex-direction: row;
    }
    .holy-grail__sidebar {
        flex: 0 0 180px;
    }
    .holy-grail__content {
        flex: 1 1 0;
    }
    }
    @media all and (min-width: 960px) {
    .holy-grail__sidebar {
        flex: 0 0 240px;
    }
    }
    button, input {
        -moz-appearance: none;
        box-shadow: none;
        font: inherit;
    }
    button {
        cursor: pointer;
    }
    .flexy-nav {
        display: flex;
        flex-direction: column;
    }
    .flexy-nav__items {
        display: none;
        flex: 1 1 0;
        flex-direction: column;
        list-style: outside none none;
        margin: 0 0 4px;
        padding: 4px;
        text-align: center;
    }
    .flexy-nav__items--visible {
        display: flex;
    }
    .flexy-nav__item {
        background-color: #f1f1f1;
        border-bottom: 1px solid #e7e7e7;
    }
    .flexy-nav__item:last-child {
        border-bottom: 0 none;
    }
    .flexy-nav__link {
        display: block;
        padding: 8px;
    }
    .flexy-nav__toggle {
        background-color: #f07850;
        border: medium none;
        color: #fff;
        margin: 0 0 4px;
        padding: 4px;
    }
    .flexy-nav__toggle:focus, .flexy-nav__toggle:hover {
        background-color: #c93f11;
        outline: 0 none;
    }
    .flexy-nav__form {
        height: 48px;
    }
    .flexy-nav__search {
        background-color: #fff;
        border: 2px solid #e7e7e7;
        color: #6d6d6d;
        display: block;
        height: 48px;
        margin: 0;
        padding: 0 4px;
        width: 100%;
    }
    .banner, .user__avatar {
        background-color: #e7e7e7;
    }
    .flexy-nav__search:focus {
        border: 2px solid #6d6d6d;
        outline: 0 none;
    }
    @media all and (min-width: 768px) {
    .flexy-nav, .flexy-nav__items {
        flex-direction: row;
    }
    .flexy-nav__items {
        display: flex;
        height: 48px;
        margin: 0;
        padding: 0;
    }
    .flexy-nav__item {
        border-bottom: medium none;
        flex: 1 1 0;
        margin-right: 4px;
    }
    .flexy-nav__link {
        line-height: 48px;
        padding: 0;
    }
    .flexy-nav__toggle {
        display: none;
    }
    .flexy-nav__form {
        flex: 0 0 auto;
    }
    .flexy-nav__search {
        transition: width 0.3s ease 0s;
        width: 240px;
    }
    .flexy-nav__search:focus {
        width: 360px;
    }
    }
    .user {
        display: flex;
        margin: 0 auto 24px;
        max-width: 960px;
    }
    .banner, .user {
    }
    .user:last-child {
        margin-bottom: 0;
    }
    .user__avatar {
        flex: 0 0 96px;
        height: 96px;
        width: 96px;
    }
    .user__description {
        border: 1px solid #e7e7e7;
        flex: 1 1 0;
        margin-left: 24px;
        padding: 12px;
    }
    .user__username {
        margin: 0 0 12px;
        padding: 0;
    }
    .user__excerpt {
        margin: 0;
    }
    .banner {
        display: flex;
        height: 180px;
        justify-content: space-around;
    }
    .banner__content {
        text-align: center;
    }
    .banner__sub, .banner__title {
        line-height: 1.5;
        margin: 0;
        padding: 0;
    }
    @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;
    }
    }
    


    1. grossws
      08.05.2015 05:20
      +1

      спойлер -- всему голова
      простыня дикая полчилась


  1. ElForastero
    06.05.2015 22:42
    -1

    Двойное подчеркивание в именах классов — это сильно.


    1. AYShestakov
      08.05.2015 13:43
      +1

      это же БЭМ :-)


      1. ElForastero
        08.05.2015 16:28

        Пардоньте… Слышал, но не вникал. Даже стыдно.


  1. AlexPTS
    11.05.2015 10:48
    +1

    Примерно пол года использую flexbox в работе (внутренний сайт, требования к браузерам позволяют благо:) ) Доволен как слон!


  1. vovansystems
    27.05.2015 12:29

    да, действительно, в примере с трёхколоночной вёрсткой ошибка — на маленьких экранах сайдбары не схлопываются по вертикали. вместо:

    .holy-grail__body {
      display: flex;
    }
    

    следует писать:
    .holy-grail__body {
      display: flex;
      flex-direction: column;
    }