Блог для начинающих веб разработчиков. HTML, СSS, Jquery, Drupal и другое.

→ Что такое CSS Flexbox. Основные понятия.

Опубликовано: 24 декабря 2015

Привет всем на HeavenWeb! Cегодня поговорим о том, что такое CSS технология Flexbox. Если сказать коротко, применение модели Flexbox позволяет верстальщику более гибко управлять положением блоков на веб-странице с помощью CSS.

До выхода браузеров с поддержкой Flexbox, макеты веб-страниц строились сначала при помощи таблиц (не совсем предназначенных для этого), а затем (как и чаще всего в настоящее время) при помощи, так называемой блочной вёрстки, когда блоки прижимались к разным сторонам окна браузера при помощи свойств float:left или float:right. Однако этот способ тоже имеет недостатки и не обладает большой гибкостью. Требуется создавать специальные очистители потока (clearfix), чтобы одни блоки не наезжали на другие, и.т.д.

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

На самом деле в Flexbox нет ничего сложного. Давайте посмотрим на практике.

Создадим div-контейнер, дадим ему класс, например .wrap, а внутри вложим, скажем, ещё 5 элементов div.

<div class="wrap">
    <div class="inner">1</div>
    <div class="inner">2</div>
    <div class="inner">3</div>
    <div class="inner">4</div>
</div>

Если не применять никаких css-свойств, то у всех элементов свойство display установится в display:block, и ожидаемо внутренние блоки займут всю ширину окна браузера, и выстроятся друг за другом с верху вниз по вертикали. Я добавлю некоторые стили, чтобы выглядело понятнее: зададим размеры и отступы div-ам, фон, и границы, ну и шрифтовое оформление:

Чтобы применить возможности Flexbox добавим контейнеру .wrap следующие свойства:

.wrapper{
    display: flex;       
}

И как видно всё изменилось. Элементы расположились по горизонтали, слева направо. Так произошло потому что к элементам внутри и к родителю применились все свойства по умолчанию, которые мы пока не указали.

Теперь немного теории.

Свойства Flex-контейнера.

  • 1. Flex-элементы (те, что у нас .inner) внутри Flex-контейнера, могут располагаться вдоль так называемой основной оси, которую мы можем направить как горизонтально (слева направо или справа налево), так и вертикально (сверху вниз или снизу вверх). Для этого контейнеру дают одно из значений свойства flex-direction:
flex-direction: row; /* т.е. в строку, Flex-элементы располагаются друг за другом слева направо */
flex-direction: row-reverse; /* то же, но справа налево */
flex-direction: column; /* т.е. в столбик, Flex-элементы располагаются друг за другом сверху вниз */
flex-direction: column-reverse;  /* то же, но снизу вверх */

  • 2. Flex-контейнер может быть и многострочным, тогда не уместившиеся элементы будут переноситься. Переноситься они могут на новую строку, которая может быть выше или ниже первой, это зависит от направления так называемой поперечной оси. Для всего этого есть одно свойство flex-wrap, которое может применять три значения:
flex-wrap: nowrap; /* Блоки не переносятся - однострочный вариант */
flex-wrap: wrap; /* Блоки переносятся вниз, если не помещаются */
flex-wrap: wrap-reverse;  /* Блоки переносятся вверх */

Имеется так-же свойство flex-flow - сокращенный вариант flex-direction и flex-wrap, например:

/* Синтаксис:  flex-flow: <'flex-direction'> || <'flex-wrap'> */
flex-flow: column;
flex-flow: row wrap;
flex-flow: column-reverse wrap-reverse;
  • 3. Если контейнер шире чем блоки внутри него, то остаётся свободное место. Можно расположить блоки внутри по разному, и это зависит от значения свойства justify-content, применённого опять же к контейнеру.
justify-content: flex-start; /* Элементы прижимаются к началу главной оси, т.е если элементы идут слева направо (указано flex-direction: row;) то к левой границе. Это чем-то похоже на float:left применённый ко всем блокам */
justify-content: flex-end;  /* к противоположной границе */
justify-content: center;  /* элементы центрируются */
justify-content: space-between;  /* Первые и последние элементы в строках прижимаются к левой и правой границе (или к верхней и нижней, если направление главной оси вертикальное), а элементы между ними находятся на равном расстоянии друг от друга */
justify-content: space-around;  /* Элементы располагаются на равном расстоянии друг от друга и от границ контейнера - рассредоточиваются */

  • 4. Если flex-контейнер многострочный, если у его элементов разная высота, то свойством align-items можно указать как именно строки с flex-элементами будут выравниваться вдоль поперечной оси (по горизонтали).
align-items: flex-start; /* элементы выравниваются по границе контейнера, соответствующей началу поперечной оси */
align-items: flex-end;  /*  элементы выравниваются по границе контейнера, соответствующей концу поперечной оси */
align-items: center;  /* строки выравниваются по центру контейнера. */
align-items: space-between;  /* элементы распределяются равномерно (первый и последний блоки в строке прижимаются к краям, а те, что между ними - на равных расстояниях друг от друга). */
align-items: space-around;  /* элементы распределяются равномерно с равным расстоянием друг от друга и от границ. */
align-items: stretch;  /* элементы растягиваются, заполняя свободное пространство, учитываются свойства min-width и max-width */

И наконец, если вдоль поперечной оси остаётся ещё место после строк, то можно управлять выравниванием всех строк в контейнере свойством align-content.

align-content: flex-start; /* строки выравниваются относительно начала контейнера. */
align-content: flex-end;  /* строки выравниваются относительно конца контейнера. */
align-content: center;  /* строки выравниваются по центру контейнера. */
align-content: space-between;  /* строки распределяются равномерно (первая и последняя строки прижимаются к краям, а те, что между ними - на равных расстояниях друг от друга). */
align-content: space-around;  /* строки распределяются равномерно с равным расстоянием друг от друга и от границ. */
align-content: stretch;  /* строки растягиваются, заполняя свободное пространство, высота блоков становится одинаковой. */

Свойства Flex-элементов.

До сих пор мы рассматривали все свойства, применяемые к flex-контейнеру (.wrap). Но есть много интересных свойств которые применяются к flex-элементам внутри него. Можно гибко управлять порядком элементов, их растяжением и сжатием, а также выравнивать элементы по отдельности. Давайте рассмотрим как это делается:

  • Свойство Order:

По умолчанию элементы располагаются согласно их порядку в HTML-коде, данное свойство у всех них равно 0, но если применить к элементу например order:1; то он встанет последним. То есть, если свойство order задано, то элементы будут располагаться согласно значениям этих свойств (это чем-то похоже на z-index, однако имеет другой смысл). Если нужно расположить элементы перед всеми остальными, то значению order можно присвоить и отрицательные числа.

Все это даёт возможность менять местами блоки, не трогая HTML-разметку страницы.

  • Свойства flex-grow и flex-shrink

Два данных свойства позволяют управлять тем насколько блок может растянуться (flex-grow), если это возможно или сжаться (flex-shrink) если это необходимо. Значения этих свойств - число (по умолчанию 0), которое задаёт пропорцию между блоками. Пока это может быть непонятно, но чуть позже рассмотрим пример вместе со следующим свойством:

  • Свойство flex-basis.

Это свойство определяет размер блока по умолчанию для элемента, на основе которого будет происходить растяжение или сжатие при распределении места в контейнере.

Давайте теперь поймем, как работают три последних свойства на практике. Допустим, у нас имеется разметка как в начале поста в виде 4 блоков внутри контейнера. Зададим вначале всем им:

  .inner{
         flex-basis:100px;
         flex-grow:1;
  }

Допустим, ширина окна браузера 800px, тогда ширина всех блоков будет равна 400px (100px • 4) и у нас остаётся ещё 400px свободного места, которое делится поровну между четырьмя блоками и каждому достаётся ещё по 100px. Итого, ширина каждого блока получается одинаковой и равной 200px.

Тут всё понятно, а теперь дадим первому .inner flex-grow:2; что тогда?

Получается, что те самые свободные 400px делятся уже не на 4 части, а на 5, и две из них достаются этому первому блоку, а остальные три делятся между тремя оставшимися поровну, т.е. первый блок будет шириной 320px (800/5 • 2), а остальные по 160px (800/5 • 1).

Думаю, принцип понятен. Как-то на конференции «CodeFest 2013» в докладе «Flexbox, теперь понятно», автор сказал можно считать, что flex-grow это показатель жадности блока при расширении контейнера - мне кажется, это отличное объяснение данному механизму.

Для свойств flex-grow, flex-shrink и flex-basis существует сокращённое свойство flex.

/* Синтаксис flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ] */

/* 0 0 auto */
flex: none;

/* Одно значение, число без размерности: flex-grow */
flex: 2;

/* Одно значение, ширина/высота: flex-basis */
flex: 30px;
flex: auto;
flex: content;

/* Два значения: flex-grow | flex-basis */
flex: 1 30px;

/* Два значения: flex-grow | flex-shrink */
flex: 2 2;

/* Три значения: flex-grow | flex-shrink | flex-basis */
flex: 2 2 10%;
  • Свойство align-self.

Рассмотрим последнее на сегодня свойство align-self. Оно позволяет переопределить выравнивание блока заданное в align-items для отдельного flex-элемента. Может иметь те же значения, что и align-items, (auto, flex-start, flex-end, center, baseline, stretch). Удобно, когда блоки в макете нужно выровнять по-разному.

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

Спасибо, что прочитали данный пост. Любые вопросы оставляйте в комментариях.

Поделиться:
Комментировать