Верстка по Flexbox (работа с элементами).

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

Рис. 217 Изучение flexbox верстки. Часть вторая.

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

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

Порядок следования элементов

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

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


Обращаю Ваше внимание, что если вы указываете значение свойства ordercss3 для одного флекс элемента в контейнере, то это не будет являться его порядковым номером, а указывает только на "вес" его позиции по отношению к другим элементам. Допускается применение отрицательных значений (значение -1, например, смещает элемент к левому краю родительского контейнера). Значение по умолчанию 0.


Схематичное отображение работы свойства ordercss3 отображено на следующем изображении:

Рис. 218 Схематичное отображение работы CSS свойства order

Рис. 218 Схематичное отображение работы CSS свойства order

В этом учебнике мы уже неоднократно сталкивались со свойством z-indexcss3, благодаря которому, вы можете управлять видимостью элементов по оси z, принцип указания значений свойства ordercss3 аналогичен. Вы можете использовать в своей работе любые значения, которые будут вам интуитивно понятны, например, 100, 200, 300 и тому подобные.

Перейдем к рассмотрению примера:

<!DOCTYPE html>
<html>
<head>
	<title>Пример изменения следования элементов в колоннах</title>
<style> 
.container,
.container2,
.container3 {
	display: flex;  /* элемент отображается как блочный флекс контейнер */
}
div > div { 
	width: 50px; /* устанавливаем ширину блока */
	height: 50px;  /* устанавливаем высоту блока */
	color: #fff;  /* цвет текста */
	margin: 1px;  /* внешние отступы со всех сторон */
	background: rgb(0,150,208);  /* цвет заднего фона */
} 
.container div:nth-of-type(4) { /* выбираем четвертый <div> в первом контейнере */ 
	order: -1;  /* определяем порядок следования флекс элемента */
	background: violet;  /* цвет заднего фона */ 
}
.container2 div:nth-of-type(4) { /* выбираем четвертый <div> во втором контейнере */ 
	order: 1;  /* определяем порядок следования флекс элемента */
	background: violet;  /* цвет заднего фона */ 
}
.container3 div:nth-of-type(4) { /* выбираем четвертый <div> в третьем контейнере */ 
	order: 2;  /* определяем порядок следования флекс элемента */
	background: violet;  /* цвет заднего фона */ 
}
</style>
</head>
	<body>
		<p>order: -1;</p>
		<div class = "container">
			<div>A</div>
			<div>B</div>
			<div>C</div>
			<div>D</div>
			<div>E</div>
		</div>
		<p>order: 1;</p>
		<div class = "container2">
			<div>A</div>
			<div>B</div>
			<div>C</div>
			<div>D</div>
			<div>E</div>
		</div>
		<p>order: 2;</p>
		<div class = "container3">
			<div>A</div>
			<div>B</div>
			<div>C</div>
			<div>D</div>
			<div>E</div>
		</div>
	</body>
</html>

В этом примере мы разместили три блочных флекс контейнера, внутри них мы разместили по пять элементов <div>. С использованием псевдокласса :nth-of-type()css3 указали для каждого четвертого элемента в определенном контейнере следующие значения свойства ordercss3:

Результат примера:

Пример изменения следования элементов в колоннах.
Пример изменения следования элементов в колоннах.

В следующем примере мы рассмотрим как происходит изменение следования элементов внутри колонн:

<!DOCTYPE html>
<html>
<head>
	<title>Пример изменения следования элементов в колоннах</title>
<style> 
.container {
	display: flex;  /* элемент отображается как блочный флекс контейнер */
	flex-direction: column; /* флекс элементы отображаются вертикально как колонны (формируются сверху вниз) */
}
.container:hover {
	flex-direction: column-reverse; /* флекс элементы отображаются вертикально как колонны (формируются снизу вверх) */
}
div > div {
	height: 50px;  /* устанавливаем высоту блока */
	color: #fff;  /* цвет текста */
	margin: 1px;  /* внешние отступы со всех сторон */
	background: rgb(0,150,208);  /* цвет заднего фона */
} 
.container div:nth-of-type(5) { /* выбираем пятый <div> в  контейнере */ 
	order: -100;  /* определяем порядок следования флекс элемента */
	background: violet;  /* цвет заднего фона */
}
.container div:nth-of-type(1) { /* выбираем первый <div> в  контейнере */ 
	order: 100;  /* определяем порядок следования флекс элемента */
	background: forestgreen;  /* цвет заднего фона */
}
</style>
</head>
	<body>
		<div class = "container">
			<div>A</div>
			<div>B</div>
			<div>C</div>
			<div>D</div>
			<div>E</div>
		</div>
	</body>
</html>

В этом примере мы установили, что элементы внутри блочного флекс контейнера отображаются вертикально как колонны, формируясь сверху вниз (свойство flex-directioncss3 со значением column). В этом случае свойство ordercss3 будет определять порядок следования элементов сверху вниз (элементы с меньшим номером будут отображаться выше, а с большим соответственно ниже).

Для первого элемента <div> с помощью псевдокласса :nth-of-type()css3 мы установили значение свойства ordercss3 равное 100, что позволило сместить его в конец всех элементов, а пятому элементу указали значение свойства ordercss3 равное -100, что позволило сместить его влево перед всеми элементами.

Кроме того, мы указали, что при наведении на контейнер указателем мыши мы изменяем формирование колонны с сверху вниз на снизу вверх (свойство flex-directioncss3 со значением column-reverse). Обратите внимание, что в этом случае порядок следования элементов в колоннах изменяется на противоположный. Вы можете открыть пример в отдельном окне для демонстрации.

Результат примера:

Пример изменения следования элементов в колоннах.
Пример изменения следования элементов в колоннах

Вертикальное выравнивание флекс элемента

В предыдущей cтатье "Верстка по Flexbox. Часть 1." мы с Вами рассмотрели как можно произвести выравнивание всех элементов внутри флекс контейнера. Но как быть, если какой то флекс элемент необходимо выровнять по особенному? На помощь нам приходит свойство align-selfcss3, которое задает выравнивание отдельных элементов строки внутри флекс контейнера. Кроме того, это свойство переопределяет значение выравнивания, заданного для контейнера свойством align-itemscss3 конкретному элементу.


Обращаю Ваше внимание, что если для флекс элемента установлено свойство margin (внешние отступы) со значением auto, то свойство align-selfcss3 будет игнорировано.


Схематичное отображение работы свойства align-selfcss3 отображено на следующем изображении:

Схематичное отображение работы свойства align-self

Рис. 221 Схематичное отображение работы свойства align-self

Перейдем к рассмотрению примера:

<!DOCTYPE html>
<html>
<head>
	<title>Использование свойства align-self</title>
<style> 
.container {
	display: flex;  /* элемент отображается как блочный флекс контейнер */
	height: 250px;  /* устанавливаем высоту контейнера */
	background: rgba(0,150,208,.2); /* цвет заднего фона */
	align-items: center; /*	флекс элементы располагаются по центру контейнера (середина поперечной оси). */
}
.container > div {  /* устанавливаем стили для элементов <div>, вложенных в контейнер */
	width: 20%;  /* устанавливаем ширину блока */
	color: #fff;  /* цвет текста */
	margin: 0 5px;  /* внешние отступы */
	background: rgb(0,150,208);  /* цвет заднего фона */
	text-align: center; /* горизонтальное выравнивание текста по центру */
} 
.container div:nth-of-type(1) { /* выбираем первый <div> в  контейнере */ 
	align-self: auto;  /* флекс элемент наследует значение его родительского контейнера */
}
.container div:nth-of-type(2) { /* выбираем второй <div> в  контейнере */ 
	align-self: stretch;  /* флекс элемент растягивается по размеру строки флекс контейнера вдоль поперечной оси */
}
.container div:nth-of-type(3) { /* выбираем третий <div> в  контейнере */ 
	align-self: flex-start;  /* флекс элемент располагается в начале строки флекс контейнера (начало поперечной оси) */
}
.container div:nth-of-type(4) { /* выбираем четвертый <div> в  контейнере */ 
	align-self: flex-end;  /* флекс элемент располагается в конце строки флекс контейнера (конец поперечной оси) */
}
.container div:nth-of-type(5) { /* выбираем пятый <div> в  контейнере */ 
	align-self: baseline;  /* флекс элемент распологаются по его базовой линии строки флекс контейнера */
}
</style>
</head>
	<body>
		<div class = "container">
			<div>auto (наследует center)</div>
			<div>stretch</div>
			<div>flex-start</div>
			<div>flex-end</div>
			<div>baseline</div>
		</div>
	</body>
</html>

В этом примере мы создали блочный флекс контейнер, внутри которого мы разместили пять элементов <div> шириной 20% от родительского контейнера. С помощью свойства align-itemscss3 указали, что все флекс элементы располагаются по центру контейнера (середина поперечной оси).

С использованием псевдокласса :nth-of-type()css3 указали для каждого элемента свое значение свойства align-selfcss3.

Для первого элемента <div> мы установили значение auto (значение по умолчанию), что позволило унаследовать значение от родительского элемента, в данном случае это выполнено лишь для демонстрации, так как это не влияет на конечное отображение.

Для второго элемента <div> мы установили, что флекс элемент растягивается по размеру строки флекс контейнера вдоль поперечной оси. Если для контейнера не задано значение отличное от stretch, то именно это значение будет унаследовано.

Третий элемент располагается в начале строки флекс контейнера (начало поперечной оси), а четвертый располагается в конце строки флекс контейнера (конец поперечной оси).

Пятый флекс элемент располагается по его базовой линии строки флекс контейнера.

Результат примера:

Рис. 222 Пример использования свойства align-self.
Рис. 222 Пример использования свойства align-self

Увеличение относительной ширины флекс элемента

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

Определить на сколько элемент может увеличиться по отношению к остальным флекс элементам в одном контейнере доступно с помощью свойства flex-growcss3.


Обращаю Ваше внимание на то, что отрицательные значения свойства flex-growcss3 не допускаются. Значение по умолчанию 0 - элементы не будут увеличиваться.

Перейдем к рассмотрению примера:

<!DOCTYPE html>
<html>
<head>
	<title>Использование свойства flex-grow</title>
<style> 
.container,
.container2,
.container3 {
	display: flex;  /* элементы отображаются как блочные флекс контейнеры */
	height: 100px;  /* устанавливаем высоту для контейнеров */
}
div > div {
	color: #fff;  /* цвет текста */
	margin: 5px;  /* внешние отступы со всех сторон */
	background: rgb(0,150,208);  /* цвет заднего фона */
	font-size: 20px;  /* размер шрифта */
	text-align: center; /* горизонтальное выравнивание текста по центру */
} 
.container div:nth-of-type(1),
.container div:nth-of-type(3),
.container2 div:nth-of-type(1),
.container2 div:nth-of-type(3),
.container3 div:nth-of-type(1),
.container3 div:nth-of-type(3) {
	flex-grow: 1;  /* блок будет увеличен на 1 по отношению к остальным флекс элементам */
} 
.container div:nth-of-type(2) {
	flex-grow: 2;  /* блок будет увеличен на 2 по отношению к остальным флекс элементам */
} 
.container2 div:nth-of-type(2) {
	flex-grow: 3;  /* блок будет увеличен на 3 по отношению к остальным флекс элементам */
} 
.container3 div:nth-of-type(2) {
	flex-grow: 4;  /* блок будет увеличен на 4 по отношению к остальным флекс элементам */
} 
</style>
</head>
	<body>
		<div class = "container">
			<div>1</div>
			<div>2</div>
			<div>1</div>
		</div>
		<div class = "container2">
			<div>1</div>
			<div>3</div>
			<div>1</div>
		</div>
		<div class = "container3">
			<div>1</div>
			<div>4</div>
			<div>1</div>
		</div>
	</body>
</html>

В этом примере мы разместили три блочных флекс контейнера, внутри них мы разместили по три элемента <div>. С использованием псевдокласса :nth-of-type()css3 указали для каждого первого и третьего элемента в каждом контейнере, что блок будет увеличен на 1 по отношению к остальным флекс элементам. Для каждого второго элемента в контейнерах указали различные значения свойства flex-growcss3.

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

Результат примера:

Рис. 223 Пример использования свойства flex-grow.
Рис. 223 Пример использования свойства flex-grow

Размер флекс элемента по умолчанию

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

В отличии от свойства flex-growcss3 используются как абсолютные значения (px, em, pt и так далее), так и значения в процентах, а не относительные значения, при этом отрицательные значения не допускаются. Значением по умолчанию является значение auto (размер равен размеру флекс элемента). Если элемент не имеет заданного размера, то размер будет высчитываться в зависимости от содержания флекс элемента.

Это свойство чем то похоже, на свойство определяющее минимальную ширину элемента (min-width), но в отличии от него свойство flex-growcss3 не вызывает переполнение родительского элемента в том случае, если минимальный размер будет превышать размеры родительского элемента, а пропорционально уменьшает размер элемента. Другими словами это свойство определяет минимальный размер флекс элемента, который при необходимости может быть уменьшен, или увеличен.

Перейдем к рассмотрению примера:

<!DOCTYPE html>
<html>
<head>
	<title>Использование свойства flex-basis</title>
<style> 
.container,
.container2,
.container3 {
	display: flex;  /* элементы отображаются как блочные флекс контейнеры */
	height: 95px;  /* устанавливаем высоту для контейнеров */
	background: rgba(0,150,208,.3);  /* цвет заднего фона */
	margin-bottom: 5px;  /* внешние отступы снизу */
}
div > div {
	color: #fff;  /* цвет текста */
	margin: 5px;  /* внешние отступы со всех сторон */
	background: rgb(0,150,208);  /* цвет заднего фона */
	font-size: 20px;  /* размер шрифта */
	text-align: center; /* горизонтальное выравнивание текста по центру */
} 
.container div:nth-of-type(1),
.container div:nth-of-type(3),
.container2 div:nth-of-type(1),
.container2 div:nth-of-type(3),
.container3 div:nth-of-type(1),
.container3 div:nth-of-type(3) {
	flex-basis: auto;  /* размер будет высчитываться в зависимости от содержания элемента */
} 
.container div:nth-of-type(2) {
	flex-basis: 100px;  /* размер для флекс элемента по умолчанию составляет 100px */
} 
.container2 div:nth-of-type(2) {
	flex-basis: 200px;  /* размер для флекс элемента по умолчанию составляет 200px */
} 
.container3 div:nth-of-type(2) {
	flex-basis: 10000px;  /* размер для флекс элемента по умолчанию составляет 10000px */
} 
</style>
</head>
	<body>
		<div class = "container">
			<div>auto</div>
			<div>100px</div>
			<div>auto</div>
		</div>
		<div class = "container2">
			<div>auto</div>
			<div>200px</div>
			<div>auto</div>
		</div>
		<div class = "container3">
			<div>auto</div>
			<div>10 000px</div>
			<div>auto</div>
		</div>
	</body>
</html>

В этом примере мы разместили три блочных флекс контейнера, внутри них мы разместили по три элемента <div>. С использованием псевдокласса :nth-of-type()css3 указали для каждого первого и третьего элемента в каждом контейнере, что их размер будет высчитываться в зависимости от содержания элемента. Для каждого второго элемента в контейнерах указали различные значения свойства flex-basiscss3.

В первом контейнере указали для второго флекс элемента размер по умолчанию 100px, во втором контейнере 100px, а в третьем уже 10000px. Обратите внимание, что в третьем контейнере элемент не смотря на его размеры не вызвал переполнение, а подстроился под оставшееся в родительском контейнере пространство.

Результат примера:

Рис. 224 Пример использования свойства flex-basis.
Рис. 224 Пример использования свойства flex-basis

Уменьшение относительной ширины флекс элемента

Ранее мы с Вами рассмотрели как с помощью свойства flex-growcss3 указать относительную ширину для флекс элементов и определить на сколько элемент может увеличиться по отношению к остальным флекс элементам. В CSS доступно и другое поведение для флекс элементов, при котором флекс элемент будет сжиматься относительно остальных флекс элементов в контейнере (при недостатке свободного пространства). За эту возможность отвечает свойтво flex-shrinkcss3.

Значение, определяющее на сколько будет уменьшен блок по отношению к остальным флекс элементам в контейнере (при недостатке свободного пространства) задается по аналогии со свойством flex-growcss3, но при этом значением по умолчанию будет 1, а не 0. Отрицательные значения так же не допускаются (не валидны).


Свойство flex-shrinkcss3 со значением 0 определяет, что элемент не будет сжиматься, сохраняя при этом необходимую ширину элемента! Если вместе с этим значением указано минимальное значение ширины флекс элемента по умолчанию (свойство flex-basiscss3), то элемент не сможет уменьшиться меньше этого значения. Используйте эту возможность осмысленно, так как существует вероятность переполнения содержимого флекс контейнера. Этот момент мы рассмотрим в конце статьи


Перейдем к рассмотрению примера:

<!DOCTYPE html>
<html>
<head>
	<title>Использование свойства flex-shrink</title>
<style> 
.container,
.container2,
.container3 {
	display: flex;  /* элементы отображаются как блочные флекс контейнеры */
	width: 400px;  /* устанавливаем ширину для контейнеров */
	height: 95px;  /* устанавливаем высоту для контейнеров */
	background: rgba(0,150,208,.3);  /* цвет заднего фона */
	margin-bottom: 5px;  /* внешние отступы снизу */
}
div > div {
	color: #fff;  /* цвет текста */
	margin: 5px;  /* внешние отступы со всех сторон */
	background: rgb(0,150,208);  /* цвет заднего фона */
	font-size: 20px;  /* размер шрифта */
	text-align: center; /* горизонтальное выравнивание текста по центру */
	flex-basis: 200px;  /* размер для флекс элемента по умолчанию составляет 200px */
} 
.container div:nth-of-type(2) {
	flex-shrink: 2;  /* блок будет уменьшен на 2 по отношению к остальным флекс элементам (при недостатке пространства) */ 
} 
.container2 div:nth-of-type(2) {
	flex-shrink: 3;  /* блок будет уменьшен на 3 по отношению к остальным флекс элементам (при недостатке пространства) */ 
} 
.container3 div:nth-of-type(2) {
	flex-shrink: 4;  /* блок будет уменьшен на 4 по отношению к остальным флекс элементам (при недостатке пространства) */ 
} 
</style>
</head>
	<body>
		<div class = "container">
			<div>1</div>
			<div>2</div>
			<div>1</div>
		</div>
		<div class = "container2">
			<div>1</div>
			<div>3</div>
			<div>1</div>
		</div>
		<div class = "container3">
			<div>1</div>
			<div>4</div>
			<div>1</div>
		</div>
	</body>
</html>

В этом примере мы разместили три блочных флекс контейнера, внутри них мы разместили по три элемента <div>. Для контейнера мы задали ширину равную 400 пикселей, а для каждого вложенного флекс элемента с помощью свойства flex-basiscss3 указали размер по умолчанию равный 200px. Это было сделано для того, чтобы смоделировать ситуацию, при которой элемент у которого значение свойства flex-shrinkcss3 больше остальных сжимался.

С использованием псевдокласса :nth-of-type()css3 указали для каждого второго элемента в контейнерах различные значения свойства flex-shrinkcss3. В первом контейнере второй элемент при недостатке пространства будет уменьшен на 2 по отношению к остальным флекс элементам, во втором контейнере на 3, а в третьем уже на четыре и всё это проиходит автоматически, не прибегая с нашей стороны к каким-то усилиям.

Результат примера:

Рис. 225 Пример использования свойства flex-shrink.
Рис. 225 Пример использования свойства flex-shrink

Универсальное свойство flex

CSS свойство flexcss3 является короткой записью для свойств, которые позволяют определить размер для флекс элемента, установленный по умолчанию, указать на сколько элемент может увеличиться и уменьшиться по отношению к остальным флекс элементам в одном контейнере, а именно:

Обратите внимание на некоторые нюансы использования свойства flexcss3:

Перейдем к рассмотрению примера:

<!DOCTYPE html>
<html>
<head>
	<title>Использование свойства flex</title>
<style> 
* {
	margin: 0;  /* внешние отступы со всех сторон отсутствуют */
	color: #fff;  /* цвет текста */
}
.content {    
	display: flex;  /* элемент отображается как блочный флекс контейнер */
	height: calc(100vh - 200px);  /* высчитываем высоту для элемента */
	background: #999;  /* цвет заднего фона */
}
section {
	display: flex;  /* элемент отображается как блочный флекс контейнер */
}
header, footer {
	height: 100px;  /* устанавливаем высоту для элементов */
	background: #777;  /* цвет заднего фона */
}
aside {
	flex: 1;  /* указываем на сколько элемент может увеличиться по отношению к остальным флекс элементам (flex-grow) */
}
main {
	background: #aaa;  /* цвет заднего фона */
	flex: 5 0 450px;  /* grow shrink basis */
}
section > div {  
	background: #333;  /* цвет заднего фона */
	margin: 5px;  /* внешние отступы со всех сторон */
	flex: 1 1 100px;  /* grow shrink basis */
	height: 100px;  /* устанавливаем высоту для элементов */
} 
</style>
</head>
	<body>
		<header>header</header>
		<div class = "content">
			<aside>aside</aside>
			<main>main
				<section>
					<div>div</div>
					<div>div</div>
					<div>div</div>
					<div>div</div>
				</section>
			</main>
			<aside>aside</aside>
		</div>
		<footer>footer</footer>
	</body>
</html>

В этом примере мы:

Результат примера:

Рис. 226 Пример использования свойства flex.
Рис. 226 Пример использования свойства flex