Inline flex


Привет, хабр!

Одним прекрасным вечером, не предвещающим ничего интересного, в наш чатик поступило предложение от автора публикации «Переводим в код 5 действительно полезных шаблонов адаптивной разметки», написанной им весной 2012 года, написать статью-ремейк, но с применением FlexBox и сопутствующим пояснением что и как работает. После некоторой доли сомнений, интерес глубже разобраться в спецификации все таки победил и я благополучно сел верстать те самые примеры. В ходе погружения в эту область стало выясняться множество нюансов, что переросло в нечто большее чем просто переверстать макетики. В общем в данной статье хочу рассказать о такой чудесной спецификации, под названием «CSS Flexible Box Layout Module» и показать некоторые ее интересные особенности и примеры применения. Всех кому интересно, любезно приглашаю под хабракат.

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


Техническая часть

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

Итак. Во FlexBox есть два основных типа элементов: Гибкий Контейнер (Flex Container) и его дочерние элементы — Гибкие Элементы (Flex Item). Для инициализации контейнера достаточно присвоить, через css, элементу display: flex; или display: inline-flex;. Разница между flex и inline-flex заключается лишь в принципе взаимодействия с окружающими контейнер элементами, подобно display: block; и display: inline-block;, соответственно.

Внутри гибкого контейнера создаются две оси, главная ось (main-axis) и перпендикулярная или кросс ось (cross axis). Преимущественно гибкие элементы выстраиваются именно по главной оси, а потом уже по кросс оси. По умолчанию главная ось горизонтальная и имеет направление слева направо, а кросс ось вертикальна и направлена сверху вниз.

Inline flex

Направлением осей можно управлять с помощью css-свойства flex-direction. Данное свойство принимает ряд значений:
row (default): Главная ось гибкого контейнера имеет ту же ориентацию, как и инлайн ось текущего режима направления строк.


чало (main-start) и конец (main-end) направления главной оси соответствуют началу (inline-start) и концу (inline-end) инлайн оси (inline-axis).
row-reverse: Все то же самое, что и в row только main-start и main-end меняются местами.
column: так же само как и row, только теперь главная ось направлена сверху вниз.
column-reverse: так же само как row-reverse, только главная ось направлена снизу вверх.
Как это работает можно посмотреть в примере на jsfiddle.

По умолчанию все гибкие элементы в контейнере укладываются в одну строку, даже если не помещаются в контейнер, они выходят за его границы. Данное поведение переключается с помощью свойства flex-wrap. У этого свойства есть три состояния:
nowrap (default): гибкие элементы выстраиваются в одну строку слева направо.
wrap: гибкие элементы строятся в многострочном режиме, перенос осуществляется по направлению кросс оси, сверху вниз.
wrap-reverse: так же как и wrap, но перенос происходит снизу вверх.
Смотрим пример.

Для удобства есть дополнительное свойство flex-flow, в котором можно одновременно указать flex-direction и flex-wrap. Выглядит это следующим образом: flex-flow: <flex-direction> <flex-wrap>

Элементы в контейнере поддаются выравниванию при помощи свойства justify-content вдоль главной оси.


о свойство принимает целых пять разных вариантов значений.
flex-start (default): гибкие элементы выравниваются по началу главной оси.
flex-end: элементы выравниваются по концу главной оси
center: элементы выравниваются по центру главной оси
space-between: элементы занимают всю доступную ширину в контейнере, крайние элементы вплотную прижимаются к краям контейнера, а свободное пространство равномерно распределяется между элементами.
space-around: гибкие элементы выравниваются таким образом, что свободное пространство равномерно распределяется между элементами. Но стоит отметить, что пространство межу краем контейнера и крайними элементами будет в два раза меньше чем пространство между элементами в середине ряда.
Конечно же поклацать пример работы этого свойства можно тут.

Это еще не все, мы так же имеем возможность выравнивания элементов по кросс оси. Применив свойство align-items, которое принимает также пять разных значений, можно добиться интересного поведения. Это свойство позволяет выравнивать элементы в строке относительно друг друга.
flex-start: все элементы прижимаются к началу строки
flex-end: элементы прижимаются к концу строки
center: элементы выравниваются по центру строки
baseline: элементы выравниваются по базовой линии текста
stretch (default): элементы растягиваются заполняя полностью строку.


Еще одно похожее свойство на предыдущее это align-content. Только оно отвечает за выравнивание целых строк относительно гибкого контейнера. Оно не будет давать эффекта если гибкие элементы занимают одну строку. Свойство принимает шесть разных значений.
flex-start: все линии прижимаются к началу кросс-оси
flex-end: все линии прижимаются к концу кросс-оси
center: Все линии паком выравниваются по центру кросс оси
space-between: линии распределяются от верхнего края до нижнего оставляя свободное пространство между строками, крайние же строки прижимаются к краям контейнера.
space-around: линии равномерно распределяются по контейнеру.
stretch (default): линии растягиваются занимая все доступное пространство.
Попробовать как работают align-items и align-content можно в этом примере. Я специально два этих свойства представил в одном примере, так как они довольно плотно взаимодействуют каждый выполняя свою задачу. Обратите внимание что происходит когда элементы помещаются в одну строку и в несколько.

С параметрами гибкого контейнера разобрались, осталось разобраться со свойствами гибких элементов.
Первое свойство с которым мы познакомимся это order. Это свойство позволяет менять позицию в потоке конкретному элементу. По умолчанию все гибкие элементы имеют order: 0; и строятся в порядке естественного потока. В примере можно увидеть как меняются местами элементы если к ним применять разные значения order.


Одно из основных свойств является flex-basis. С помощью этого свойства мы можем указывать базовую ширину гибкого элемента. По умолчанию имеет значение auto. Это свойство тесно связано с flex-grow и flex-shrink, о которых я расскажу чуть позже. Принимает значение ширины в px, %, em и остальных единицах. По сути это не строго ширина гибкого элемента, это своего рода отправная точка. Относительно которой происходит растягивание или усадка элемента. В режиме auto элемент получает базовую ширину относительно контента внутри него.

flex-grow на нескольких ресурсах имеет совершенно некорректное описание. Там говорится о том, что якобы оно задает соотношение размеров элементов в контейнере. На самом деле это не так. Это свойство задает фактор увеличения элемента при наличии свободного места в контейнере. По умолчанию это свойство имеет значение 0. Давайте представим, что у нас есть гибкий контейнер, который имеет ширину 500px, внутри него есть два гибких элемента, каждый из которых имеет базовую ширину 100px. Тем самым в контейнере остается еще 300px свободного места. Если первому элементу укажем flex-grow: 2;, а второму элементу укажем flex-grow: 1;. В результате эти блоки займут всю доступную ширину контейнера, только ширина первого блока будет 300px, а второго только 200px. Что же произошло? А произошло вот что, доступные 300px свободного места в контейнере распределились между элементами в соотношении 2:1, +200px первому и +100px второму. Собственно так это и работает.


Тут мы плавно переходим к другому аналогичному свойству, а именно flex-shrink. По умолчанию имеет значение 1. Оно так же задает фактор на изменение ширины элементов, только в обратную сторону. Если контейнер имеет ширину меньше чем сумма базовой ширины элементов, то начинает действовать это свойство. Например контейнер имеет ширину 600px, а flex-basis элементов по 300px. Первому элементу укажем flex-shrink: 2;, а второму flex-shrink: 1;. Теперь сожмем контейнер на 300px. Следовательно сумма ширины элементов на 300px больше чем контейнер. Эта разница распределяется в соотношении 2:1, получается от первого блока отнимаем 200px, а от второго 100px. Новый размер элементов получается 100px и 200px, у первого и второго элемента, соответственно. Если мы устанавливаем flex-shrink в значение 0, то мы запрещаем сжиматься элементу до размеров меньше чем его базовая ширина.

На самом деле это очень упрощенное описание того как это все работает, дабы было понятен общий принцип. Более подробно, если кому интересно, алгоритм описан в спецификации.

Все три свойства можно записать в сокращенной форме при помощи выражения flex. Это имеет следующий вид:
flex: <flex-grow> <flex-shrink> <flex-basis>;
А так же мы можем писать еще два сокращенных варианта, flex: auto; и flex: none;, что означает flex: 1 1 auto; и flex: 0 0 auto; соответственно.


Последним свойством гибких элементов остался align-self. Тут все просто, это то же самое, что align-items у контейнера, позволяющее переопределять выравнивание для конкретно взятого элемента.

Все, надоел! Примеры давай!

С технической частью разобрались, получилось довольно затянуто, но в это нужно вникнуть. Теперь можно перейти к практическому применению.
В ходе верстки тех самых «пяти действительно полезных шаблонов адаптивной разметки», пришлось решать типичные ситуации, с которыми разработчик сталкивается довольно часто. С flexbox реализация этих решений становится проще и гибче.
Возьмем все тот же 4-ый макет, т.к. в нем больше всего интересных элементов.

Inline flex

Для начала обозначим основную ширину страницы, выровняем по центру, прижмем футер к низу страницы. Как всегда в общем.

html { 	background: #ccc; 	min-height: 100%; 	font-family: sans-serif; 	display: -webkit-flex; 	display: flex; 	flex-direction: column; } body { 	margin: 0; 	padding: 0 15px; 	display: -webkit-flex; 	display: flex; 	flex-direction: column; 	flex: auto; } .header { 	width: 100%; 	max-width: 960px; 	min-width: 430px; 	margin: 0 auto 30px; 	padding: 30px 0 10px; 	display: -webkit-flex; 	display: flex; 	flex-wrap: wrap; 	justify-content: space-between; 	box-sizing: border-box; } .main { 	width: 100%; 	max-width: 960px; 	min-width: 430px; 	margin: auto; 	flex-grow: 1; 	box-sizing: border-box; } .footer { 	background: #222; 	width: 100%; 	max-width: 960px; 	min-width: 430px; 	color: #eee; 	margin: auto; 	padding: 15px; 	box-sizing: border-box; }   

За счет того что мы для .main указали flex-grow: 1; он растягивается на всю доступную высоту, тем самым прижимая футер к низу. Бонусом в этом решении является, то что футер может быть нефиксированной высоты.

Разместим теперь логотип и меню в хедере.

.logo { 	font-size: 0; 	margin: -10px 10px 10px 0; 	display: flex; 	flex: none; 	align-items: center; } .logo:before, .logo:after { 	content: ''; 	display: block; } .logo:before { 	background: #222; 	width: 50px; 	height: 50px; 	margin: 0 10px 0 20px; 	border-radius: 50%; } .logo:after { 	background: #222; 	width: 90px; 	height: 30px; } .nav { 	margin: -5px 0 0 -5px; 	display: -webkit-flex; 	display: flex; 	flex-wrap: wrap; } .nav-itm { 	background: #222; 	width: 130px;  	height: 50px; 	font-size: 1.5rem; 	color: #eee; 	text-decoration: none; 	margin: 5px 0 0 5px; 	display: -webkit-flex; 	display: flex; 	justify-content: center; 	align-items: center; } 

Поскольку для хедера указано flex-wrap: wrap; и justify-content: space-between; логотип и меню раскидывает по разным сторонам хедера, при этом если места для меню будет не хватать оно элегантно сместится под логотип.

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


нас есть картинка справа и текст с заголовком слева. Я лично придерживаюсь идеи, что любые элементы должны быть максимально гибкими, независимо от того адаптиваная это верстка или статика. Итак у нас есть в этом посте сайд-бар в котором размещена картинка, строго говоря мы не можем точно сказать какая ширина нам нужна, ибо сегодня у нас большая картинка, завтра маленькая и каждый раз переделывать элемент с нуля неохота. Значит нам нужно, чтобы сайд-бар занял нужное ему место, а остальное место пошло на контент. Так и сделаем:

.box { 	font-size: 1.25rem; 	line-height: 1.5; 	font-style: italic; 	margin: 0 0 40px -50px; 	display: -webkit-flex; 	display: flex; 	flex-wrap: wrap; 	justify-content: center; } .box-base { 	margin-left: 50px; 	flex: 1 0 430px; } .box-side { 	margin-left: 50px; 	flex: none; } .box-img { 	max-width: 100%; 	height: auto; } 

Как вы видите для .box-base, там где у нас заголовок и текст, я указал базовую ширину посредством flex-basis: 430px;, а так же запретил усадку блока при помощи flex-shrink: 0;. Этой манипуляцией мы сказали, что контент не может стать меньше чем 430px в ширину. А ввиду того что для .box я указываю flex-wrap: wrap; в тот момент, когда сайд-бар и контент не будут помещаться в контейнер .box, сайд-бар автоматически провалится под контент. И это все без применения @ media! Я считаю это действительно очень круто.

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

.content { 	margin-bottom: 30px; 	display: -webkit-flex; 	display: flex; 	flex-wrap: wrap; }   

В контейнере три колонки, .banners, .posts, .comments

.banners { 	flex: 1 1 200px; } .posts { 	margin: 0 0 30px 30px; 	flex: 1 1 200px; } .comments { 	margin: 0 0 30px 30px; 	flex: 1 1 200px; } 

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

По макету, нам с контентом, обойтись без @ media не получится, поэтому еще немного настроим поведение колонок для ширины <800px и <600px.

@media screen and (max-width: 800px) { 	.banners { 		margin-left: -30px; 		display: -webkit-flex; 		display: flex; 		flex-basis: 100%; 	} 	.posts { 		margin-left: 0; 	} } @media screen and (max-width: 600px) { 	.content { 		display: block; 	} 	.banners { 		margin: 0; 		display: block; 	} 	.comments { 		margin: 0; 	} } 

Вот и вся магия, что касается построения лейаута на FlexBox. Еще одна задача, которая мне понравилась, находится в 5-ом макете, конкретно это касается адаптации контента.

Inline flex

Мы видим, как на десктопном разрешении посты построены в сетку по три штуки в ряд. Когда ширина viewport становится меньше 800px, то сетка превращается в колонку с постами, где фото поста выстраивается с левой и правой стороны от контента поста, поочередно. А при ширине меньше 600px фото поста прячется вовсе.

.grid { 	display: -webkit-flex; 	display: flex; 	flex-wrap: wrap; 	justify-content: space-between; } .grid-itm { 	margin-bottom: 30px; 	flex-basis: calc(33.33% - 30px * 2/3);  	display: -webkit-flex; 	display: flex; 	flex-wrap: wrap; } .grid-img { 	margin: 0 auto 20px; 	flex: 0 1 80%; } .grid-cont{ 	flex: 0 1 100%; } .grid-title { 	text-align: center; } @media screen and (max-width: 800px) { 	.grid-itm { 		flex-wrap: nowrap; 		flex-basis: 100%; 	} 	.grid-img { 		flex: 0 0 auto; 	} 	.grid-itm:nth-child(even) .grid-img { 		margin: 0 0 0 30px; 		order: 2; 	} 	.grid-itm:nth-child(odd) .grid-img { 		margin: 0 30px 0 0;  	} 	.grid-cont { 		flex: 1 1 auto; 	} 	.grid-title { 		text-align: left; 	} } @media screen and (max-width: 600px) { 	.grid-img { 		display: none; 	} } 

На самом деле это всего лишь малая часть того, что можно реализовать на FlexBox. Спецификация позволяет строить весьма сложные макеты страниц при этом применяя простой код.

Немного ссылок

Примеры шаблонов можно увидеть по ссылке на github.
Знания впитывал отсюда.

Надеюсь мой пост кому-то поможет и позволит скорее использовать новые технологии в полную силу.
На этом у меня все. Благодарю за внимание!

habr.com

Базовый макет

Чтобы понять, каково это — создавать макеты на каждой системе, мы сделаем одну и ту же HTML-страницу дважды — один раз с помощью Flexbox, а затем на CSS Grid. Вы можете скачать оба проекта отсюда или проверить их в этой демонстрационной версии.

Уменьшенный макет веб-страницы

Уменьшенный макет веб-страницы

Дизайн довольно простой — он состоит из выровненного по центру контейнера, внутри которого у нас есть шапка, основной раздел, боковая панель и подвал. Вот главные «испытания», которые мы должны провести, сохраняя CSS и HTML по возможности чистыми:

  1. Разместить четыре основных раздела макета.
  2. Сделать страницу адаптивной (боковая панель опускается ниже основного содержимого на маленьких экранах).
  3. Выровнять содержимое шапки — навигация слева, кнопка справа.

Как вы можете видеть, ради сравнения мы оставили всё максимально простым. Начнём с первого испытания.

Испытание 1. Размещение разделов страницы

Решение на Flexbox

Добавляем display: flex к контейнеру и задаём направление дочерних элементов по вертикали. Это позиционирует все разделы друг под другом.

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

Теперь нам нужно сделать так, чтобы основной раздел и боковая панель располагались рядом. Поскольку flex-контейнеры обычно однонаправлены, нам нужно добавить дополнительный элемент.

<header></header> <div class="main-and-sidebar-wrapper">  <section class="main"></section>  <aside class="sidebar"></aside> </div> <footer></footer>

Затем мы устанавливаем этому элементу display: flex и flex-direction с противоположным направлением.

.main-and-sidebar-wrapper {  display: flex;  flex-direction: row; }

Последний шаг — задать размеры основного раздела и боковой панели. Мы хотим, чтобы основное содержимое было в три раза шире боковой панели, что несложно сделать с помощью flex или процентов.

.main {  flex: 3;  margin-right: 60px; } .sidebar {  flex: 1; }

Как вы можете видеть, Flexbox сделал всё хорошо, но нам кроме этого понадобилось довольно много свойств CSS плюс дополнительный элемент HTML. Давайте посмотрим, как будет работать CSS Grid.

Решение на CSS Grid

Существует несколько вариантов использования CSS Grid, но мы воспользуемся синтаксисом grid-template-areas, как наиболее подходящего для наших целей.

Сперва мы определим четыре grid-area, по одному на каждый раздел страницы:

<header></header> <!-- Обратите внимание, что в этот раз нет дополнительных элементов --> <section class="main"></section> <aside class="sidebar"></aside> <footer></footer>
header {  grid-area: header; } .main {  grid-area: main; } .sidebar {  grid-area: sidebar; } footer {  grid-area: footer; }

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

.container {  display: grid;    /* Определяем размер и число колонок нашей сетки.   Единица fr работает подобно Flexbox:  колонки делят свободное пространство в строке согласно их значениям.  У нас будет две колонки — первая в три раза больше второй. */  grid-template-columns: 3fr 1fr;    /* Связываем сделанные ранее области с местами в сетке.  Первая строка — шапка.  Вторая строка делится между основным разделом и боковой панелью.  Последняя строка — подвал. */  grid-template-areas:   "header header"  "main sidebar"  "footer footer";   /* Интервал между ячейками сетки будет 60 пикселей */  grid-gap: 60px; }

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

Испытание 2. Делаем страницу адаптивной

Решение на Flexbox

Выполнение этого шага строго связано с предыдущим. Для решения на Flexbox нам придётся изменить flex-direction и отрегулировать margin.

@media (max-width: 600px) {  .main-and-sidebar-wrapper {  flex-direction: column;  }    .main {  margin-right: 0;  margin-bottom: 60px;  } }

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

Решение на CSS Grid

Поскольку мы уже определили grid-areas, нам просто нужно переопределить их порядок в медиа-запросе. Мы можем использовать ту же настройку колонок.

@media (max-width: 600px) {  .container {  /* Выравнивание областей сетки для мобильного макета */  grid-template-areas:   "header header"  "main main"  "sidebar sidebar"  "footer footer";  } }

Или можем переопределить весь макет с нуля, если считаем, что это решение чище.

@media (max-width: 600px) {  .container {  /* Переделываем сетку в одноколоночный макет */  grid-template-columns: 1fr;  grid-template-areas:   "header"  "main"  "sidebar"  "footer";  } }

Испытание 3. Выравнивание компонентов шапки

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

Решение на Flexbox

<header>  <nav>  <li><a href="#"><h1>Logo</h1></a></li>  <li><a href="#">Link</a></li>  <li><a href="#">Link</a></li>  </nav>  <button>Button</button> </header>

Мы уже делали похожий макет на Flexbox в одной из наших старых статей — Простейший способ создания адаптивной шапки. Техника довольно простая:

header {  display: flex;  justify-content: space-between; }

Теперь список навигации и кнопка выровнены правильно. Осталось только разместить пункты внутри <nav> по горизонтали. Проще это сделать с помощью display: inline-block, но поскольку мы собираемся целиком использовать Flexbox, применим решение только для него:

header nav {  display: flex;  align-items: baseline; }

Только две строки! Совсем неплохо. Давайте посмотрим, как с этим справится CSS Grid.

Решение на CSS Grid

Чтобы разделить навигацию и кнопку, мы должны добавить display: grid к header и настроить двухколоночную сетку. Нам также понадобятся две дополнительные строки в CSS, чтобы позиционировать всё на соответствующих границах.

header{  display: grid;  grid-template-columns: 1fr 1fr; } header nav {  justify-self: start; } header button {  justify-self: end; }

Что касается ссылок в одну строку внутри навигации, у нас не получилось сделать это корректно с CSS Grid. Вот как выглядит наша лучшая попытка:

Inline flex

Ссылки строчные, но они не могут быть выровнены правильно, поскольку не существует варианта baseline, как у align-items. Мы также должны определить ещё одну вложенную сетку.

header nav {  display: grid;  grid-template-columns: auto 1fr 1fr;  align-items: end;  }

Понятно, что CSS Grid не справилась с этой частью макета, но это и не удивительно — основное внимание уделяется выравниванию контейнеров, а не содержимому внутри них. Эта система не для нанесения последних штрихов.

Выводы

Если вы прочитали статью целиком (а это отличная работа!), выводы не должны вас удивить. На деле нет лучшей системы — и Flexbox и CSS Grid хороши по своему и должны использоваться совместно, а не как альтернатива друг другу.

Для тех из вас, кто перепрыгнул непосредственно к выводам этой статьи (не волнуйтесь, мы тоже так делаем), вот краткий итог сравнения:

  • CSS Grid отлично подходит для создания большой картины. Эта система облегчает управление макетом страницы и даже может иметь дело с нестандартным и асимметричным дизайном.
  • Flexbox отлично подходит для выравнивания содержимого внутри элементов. Используйте эту систему для размещения мелких деталей дизайна.
  • Используйте CSS Grid для двумерных макетов (строк И колонок).
  • Flexbox лучше работает только в одном измерении (со строками ИЛИ с колонками).
  • Нет причин применять только CSS Grid или только Flexbox. Изучайте их и используйте совместно.

htmlbook.ru

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

Свойство display

Во-первых , обязательным является указание для контейнера свойства display: flex или inline-flex:

Обратите внимание, что в первом случае (display: flex) размер контейнера доходит до пределов родительского блока, а дочерние элементы занимают по 100px, а во втором (display: inline-flex) размер родительского контейнера совпадает с размером содержимого, т.е. размером дочерних элементов.

С префиксами css-код будет выглядеть несколько иначе:

Далее префиксы мы будем опускать для читабельности кода. Но в реальных проектах их стоит добавлять с помощью  autoprefixer, который автоматически добавит css-правила и вендорные префиксы для тех браузеров, которым они нужны.

Важное примечание: flex-контейнер сам не является блочным контейнером, поэтому для внутренних блоков не работают такие css-свойства, как floatclearvertical-align. Также, на flex-контейнер не оказывают влияние свойства column-, создающие колонки в тексте и псевдоэлементы ::first-line и ::first-letter.

Свойство flex-direction

Вернемся к примеру: все блоки с классом item внутри flex-контейнера выстроились по горизонтали слева направо. В спецификации  Flexbox это определяется свойством flex-direction: row, которое задано для flex-контейнеров по умолчанию. Также оно может иметь следующие значения:


Как только значение row или row-reverse (строка) меняется на column или column-reverse (столбец), внутренние элементы выстраиваются по вертикали. Это происходит потому, что в модели Flexbox есть 2 направления, или 2 оси — главная (main axis) и поперечная (cross axis). По умолчанию оси направлены слева направо и сверху вниз, но используя значения с суффиксом -reverse можно поменять направление на противоположное.Inline flexПримечание: при использовании rtl направления меняются на противоположные, т.е. row будет идти справа налево.

Свойство justify-content

Css свойство justify-content определяет то, как будут выровнены элементы вдоль главной оси. Очень важное свойство для построения системы сеток, т.к. позволяет распределить контент внутри контейнера.

Возможные значения свойства justify-content:

  • flex-start (значение по умолчанию) : блоки прижаты к началу главной оси
  • flex-end: блоки прижаты к концу главной оси
  • center: блоки размещаются по центру главной оси
  • space-between: первый блок располагается в начале главной оси, последний блок – в конце, все остальные блоки равномерно распределены в оставшемся пространстве.
  • space-around: все блоки равномерно распределены вдоль главной оси, разделяя все свободное пространство поровну.

Свойство align-items

Css-свойство align-items определяет то, как будут выровнены элементы вдоль поперечной оси. Для того чтобы это свойство можно было использовать, высота контейнера должна быть больше высоты блоков. В примере она задана свойством height: 300px. Например, это свойство хорошо подойдет для шапки сайта с большим изображением, чтобы разместить текст по центру.

Возможные значения свойства align-items:

  • stretch (значение по умолчанию) : блоки растянуты, занимая все доступное место по поперечной оси, при этом все же учитываются min-width/max-width, если таковые заданы.
  • flex-start: блоки прижаты к началу поперечной оси, т.е. к верху
  • flex-end: блоки прижаты к концу поперечной оси, т.е. к низу
  • center: блоки располагаются в центре поперечной оси
  • baseline: блоки выровнены по базовой линии текста в них. Зависит от размера шрифта. На примере в разных блоках цифры помещены в заголовки разных уровней. Например, блок с цифрой 2 больше остальных, т.к. в нем использован заголовок h1.

Свойство flex-wrap

Первоначально подразумевается, что flexbox — это контейнер для установки его элементов в одну единственную строку. Свойство flex-wrap управляет тем, как flex-контейнер будет устраивать свои элементы — в одну строку или в несколько, и направлением, в котором будут укладываться новые строки. Т.е. при изменении значения по умолчанию получается многострочный контейнер.

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

В примере ниже указаны такие свойства:

Возможные значения flex-wrap:

  • nowrap (значение по умолчанию) : блоки расположены в одну линию слева направо (в rtl справа налево)
  • wrap: блоки расположены в несколько горизонтальных рядов (если не помещаются в один ряд). Они следуют друг за другом слева направо (в rtl справа налево)
  • wrap-reverse: то-же что и wrap, но блоки располагаются в обратном порядке.

Свойство flex-flow

flex-flow – удобное сокращение для двух свойств Flexbox-модели: flex-direction + flex-wrap

По сути,flex-flow предоставляет возможность в одном свойстве описать направление главной и многострочность поперечной оси.

Поскольку по умолчанию значение flex-flow: row nowrap, то имеет смысл его использовать тогда, когда нужно изменить оба эти значения, например:

или хотя бы одно

Свойство align-content

Существует также свойство align-content, которое определяет то, каким образом образовавшиеся ряды блоков будут выровнены по вертикали и как они поделят между собой все пространство flex-контейнера. Это свойство удобно использовать там, где нужно указывать высоту контейнера и распределять внутренние блоки по вертикали.

Примечание: align-content работает только в многострочном режиме (т.е. в случае flex-wrap:wrap; или flex-wrap:wrap-reverse;)

Возможные значения align-content:

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

Свойства дочерних элементов flex-контейнера

Свойство order

Это свойство определяет порядок (англ. order), в котором дочерние элементы flex-контейнера появляются внутри него. По умолчанию, flex-элементы следуют друг за другом в том порядке, в котором добавлены во flex-контейнер в html-коде. Задается order целым числом и по умолчанию для всех элементов равен 0. Можно использовать как положительные, так и отрицательные числа.

В примере ниже увеличьте значение в поле с номером элемента и посмотрите, куда он «переедет».

Использовать это свойство можно, например, для изменения положения боковой колонки — справа или слева от основного контента. Или при сортировке блоков с какими-либо товарами.

Стоит сказать, что все свойства Flexbox-модели могут быть полезны при построении адаптивной верстки. Например, это свойство используется при перестройке контента вкладок при уменьшении ширины экрана. Чтобы посмотреть на эффект, включайте вкладки HTML или CSS. Кроме того, вы можете отредактировать этот код на codepen.io.

See the Pen Flexbox tabs by Elen (@ambassador) on CodePen.18892

Свойство align-self

Свойство align-self позволяет изменить выравнивание отдельно взятого flex-блока по поперечной оси по сравнению со свойством flex-контейнера align-items.
В качестве значений align-self имеет те же 5 вариантов, что и свойство align-items, а именно:

  • stretch (значение по умолчанию) : flex-блок растянут, чтобы занять все доступное место по поперечной оси, при этом учитываются min-width/max-width, если таковые заданы.
  • flex-start: flex-блок прижат к началу поперечной оси
  • flex-end: flex-блок прижат к концу поперечной оси
  • center: flex-блок располагаются в центре поперечной оси
  • baseline: flex-блок выравнен по baseline

Свойство flex-grow

Это свойство указывает, каким будет фактор растягивания flex-элемента. Что значит «фактор растягивания»? По сути дела это коэффициент, который определяет, насколько больше будет растянут flex-элемент относительно других flex-элементов при распределении свободного пространства внутри flex-контейнера.

По умолчанию это свойство имеет значение 0. Можно указывать только целые положительные числа. Отрицательные значения будут проигнорированы.

Принято думать, что если у какого-либо элемента указано свойство flex-grow, равное 2, то этот элемент будет занимать в 2 раза больше пространства, чем остальные. На самом деле это будет так только при отсутствии контента внутри flex-элемента, что бывает только в демо-примерах и для реальной верстки не подходит. На самом деле это свойство определяет способность flex-элемента изменять свои размеры для заполнения собой свободного пространства.  Т.е., если ширина одного flex-элемента 500px, второго — 200px, а ширина их родительского flex-контейнера 1000px, то свободными останутся 300px

Т.е. для распределения в соответствии с flex-grow останется только часть пространства, а не все оно.

Если у одного элемента flex-grow: 2, а у второго — flex-grow: 1, то 300px нужно будет делить на 3 части:

Соответственно, ширина первого элемента увеличится на 200px (500px + 100px*2 = 700px), а ширина второго станет больше всего на 100px: 200px+100px*1 = 300px.

Если flex-grow у первого и второго элементов будет по 1, то они разделят 300px свободного пространства поровну, т.е. по 150px:

В этом случае ширина первого станет 500px + 150px = 650px, а второго 200px+150px = 350px. И так будет происходить при любых равных значениях для свойства flex-grow для обоих элементов.

В примере ниже вы можете сами посмотреть, какова будет ширина блоков section и aside при различных значениях свойства flex-grow. Первоначально оба элемента имеют 0 в качестве значения этого свойства внутри составного свойства flex, поэтому свободное пространство мы видим справа от aside.

Свойство flex-shrink

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

Свойство flex-shrink похоже на flex-grow, но имеет свои нюансы. Оно зависит от flex-basis элемента и убавляется от величины, указанной или рассчитанной браузером для  flex-basis каждого из flex-элементов.

В примере у 5 flex-элементов flex-shrink равен 1, также каждому задано значение flex-basis в 25%. Однако, исходя из того, что родительский элемент имеет ширину 100%, а элементов 5,  реальная ширина  каждого из них составляет 20%. Здесь мы сталкиваемся с недостатком пространства в 25% . Т.е. отрицательное свободное пространство составляет 250px (исходя из ширины flex-контейнера 1000px*25% = 250px). Поэтому каждый из элементов получает -50px, и реальная ширина каждого из элементов будет 200px.

Если для одного из этих элементов изменить коэффициент flex-shrink, то ширина этого отдельного элемента будет больше (flex-shrink: 0) или меньше (flex-shrink: 2) . В случае flex-shrink: 0 «рулит» свойство flex-basis элемента, и его ширина составляет 250px (25% от 1000px), и сжиматься ему не нужно.

Если flex-shrink: 2, то расчетная величина «убавляемого» пространства увеличивается и будет такова:

4 элемента имеют фактор flex-shrink: 1 (4*1) и один имеет flex-shrink: 2, поэтому делить отрицательное пространство нужно на 6. Каждый из элементов, имеющих flex-shrink: 1, получает такую ширину:

А элемент с flex-shrink: 2 имеет ширину:

Некоторое количество пикселей может отличаться, т.к. есть еще контент, который может не помещаться в расчетную ширину.

Свойство flex-basis

Свойство flex-basis определяет базовый размер отдельно взятого flex-элемента до распределения свободного пространства в соответствии с flex-grow и flex-shrink. Оно в какой-то мере напоминает width, но несколько отличается по поведению, т.к. в «довесок» к нему идут коэффициенты flex-grow и flex-shrink, корректирующие конечную ширину элемента.

Свойство flex-basis может быть указано в различных единицах: px, pt, em, rem, mm  или в % вдоль главной оси (main axis). В  последнем случае размер вычисляется относительно родителя. Нельзя использовать отрицательные величины. По умолчанию имеет значение auto, и тогда за основу вычисления размеров блока берутся его размеры (свойства width, height), а они, в свою очередь, могут зависеть от размера контента, если не указанны явно. Т.е. контент может растянуть или «ужать» блок в зависимости от своего размера.

Для flex-basis доступно в спецификации еще значение content, но оно пока не поддерживается браузерами и отображается как auto. Обозначает это свойство, что размер элемента рассчитывается на основе его контента.

Сокращенное свойство flex

Предыдущие 3 свойства желательно писать не по отдельности, а указывать в одном общем свойстве flex :

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

Значения:

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

flex-grow странный. Так ли это?

Зачем верстальщику лягушки?

В сети довольно давно существует ресурс, посвященный изучению свойств Flexbox-модели в виде небольшой интерактивной игры с лягушками. Доступен он и на русском языке — http://flexboxfroggy.com/#ru. Очень советую пройти ее — помогает разобраться со свойствами на наглядных примерах.

И в конце вы можете попробовать еще раз различные свойства Flexbox-модели:

See the Pen Animated Flexbox Playground by Elen (@ambassador) on CodePen.18892

Полезные ссылки:

  1. Все свойства Flexbox-модели от CSS Trics (англ)
  2. Расчет размера flex-элементов на основе flex-basis, flex-grow, flex-shrink
  3. Интерактивное размещение flex-элементов и управление их свойствами 

Метки: align-items align-self flex flex-basis flex-direction flex-grow flex-shrink flex-wrap Flexbox justify-content order верстка по сетке

You May Also Like

About the Author: admind

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.