Записи с меткой "Flexbox"
Руководство по Flexbox

Свойства для Родителя (flex контейнер)

display
.container {
display: flex; /* or inline-flex */
}
flex-direction

.container {
flex-direction: row | row-reverse | column | column-reverse;
}
-
row (по умолчанию): слева направо в ltr; справа налево в rtl
-
row-reverse справа налево ltr; слева направо в rtl
-
column: так же, как и rowно сверху вниз
-
column-reverse: то же самое, row-reverseно снизу вверх
flex-wrap

.container{
flex-wrap: nowrap | wrap | wrap-reverse;
}
-
nowrap (по умолчанию): все flex элементы будут в одной строке
-
wrap: flex-элементы будут перенесены на несколько строк сверху вниз.
-
wrap-reverse: flex-элементы будут перенесены на несколько строк снизу вверх.
flex-flow (Применяется к: родительскому элементу flex-контейнера)
flex-flow: <‘flex-direction’> || <‘flex-wrap’>
justify-content

.container {
justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly | start | end | left | right ... + safe | unsafe;
}
-
flex-start (по умолчанию): элементы сдвинуты в начало flex-direction направления.
-
flex-end: элементы сдвинуты ближе к концу flex направления.
-
start: элементы сдвинуты к началу writing-modeнаправления.
-
end: элементы сдвинуты в конце writing-modeнаправления.
-
left: элементы сдвинуты по направлению к левому краю контейнера, если это не имеет смысла flex-direction, тогда он ведет себя как start.
-
right: элементы сдвинуты по направлению к правому краю контейнера, если это не имеет смысла flex-direction, тогда он ведет себя как start.
-
center: элементы центрированы вдоль линии
-
space-between: элементы равномерно распределены по линии; первый элемент находится в начале строки, последний элемент в конце строки
-
space-around: элементы равномерно распределены по линии с одинаковым пространством вокруг них. Обратите внимание, что визуально пространства не равны, так как все элементы имеют одинаковое пространство с обеих сторон. Первый элемент будет иметь одну единицу пространства напротив края контейнера, но две единицы пространства между следующим элементом, потому что у следующего элемента есть свой собственный интервал, который применяется.
-
space-evenly: элементы распределяются таким образом, чтобы расстояние между любыми двумя элементами (и расстояние до краев) было одинаковым.
align-items

.container {
align-items: stretch | flex-start | flex-end | center | baseline | first baseline | last baseline | start | end | self-start | self-end + ... safe | unsafe;
}
-
stretch (по умолчанию): растягивать, чтобы заполнить контейнер (все еще соблюдаются min-width / max-width)
-
flex-start/ start/ self-start: элементы размещаются в начале поперечной оси. Разница между ними невелика и заключается в соблюдении flex-direction правил или writing-mode правил.
-
flex-end/ end/ self-end: элементы располагаются в конце поперечной оси. Разница опять-таки тонкая и заключается в соблюдении flex-direction или writing-mode правил.
-
center: элементы центрированы по поперечной оси
-
baseline: элементы выровнены, по их базовой линии
align-content

.container {
align-content: flex-start | flex-end | center | space-between | space-around | space-evenly | stretch | start | end | baseline | first baseline | last baseline + ... safe | unsafe;
}
-
flex-start/ start: элементы, сдвинуты в начало контейнера. Более поддерживаемый flex-startиспользует, flex-directionв то время как startиспользует writing-modeнаправление.
-
flex-end/ end: элементы, сдвинуты в конец контейнера. Более поддерживаемый flex-endиспользует flex-directionв то время как endиспользует writing-modeнаправление.
-
center: элементы выровнены по центру в контейнере
-
space-between: элементы равномерно распределены; первая строка находится в начале контейнера, а последняя — в конце
-
space-around: элементы равномерно распределены с равным пространством вокруг каждой строки
-
space-evenly: элементы распределены равномерно, вокруг них одинаковое пространство
-
stretch (по умолчанию): линии растягиваются, чтобы занять оставшееся пространство
Свойства для первых дочерних элементов(flex элементы)

order

.item {
order: <integer>; /* default is 0 */
}
flex-grow

.item {
flex-grow: <number>; /* default 0 */
}
flex-shrink
.item {
flex-shrink: <number>; /* default 1 */
}
flex-basis
.item {
flex-basis: <length> | auto; /* default auto */
}

flex
.item {
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}
align-self

.item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
Примеры
.parent {
display: flex;
height: 300px; /* Или что угодно */
}
.child {
width: 100px; /* Или что угодно */
height: 100px; /* Или что угодно */
margin: auto; /* Магия! */
}
.flex-container {
/* Сначала мы создаем flex контекст */
display: flex;
/* Затем мы определяем flex-direction и разрешаем элементам переходить на новые строки
* Запомните, что это то же самое что и:
* flex-direction: row;
* flex-wrap: wrap;
*/
flex-flow: row wrap;
/* Затем мы определяем, как распределяется оставшееся пространство */
justify-content: space-around;
}


/* Большие экраны */
.navigation {
display: flex;
flex-flow: row wrap;
/* Это выровняет элементы по конечной части линии на главной оси */
justify-content: flex-end;
}
/* Средние экраны */
@media all and (max-width: 800px) {
.navigation {
/* На экранах среднего размера мы центрируем элементы, равномерно распределяя пустое пространство вокруг элементов */
justify-content: space-around;
}
}
/* Маленькие экраны */
@media all and (max-width: 500px) {
.navigation {
/* На маленьких экранах мы больше не используем направление строки, а используем столбец */
flex-direction: column;
}
}
.wrapper {
display: flex;
flex-flow: row wrap;
}
/* Мы говорим, что все элементы имеют ширину 100%, через flex-base */
.wrapper > * {
flex: 1 100%;
}
/* Мы используем исходный порядок для первого мобильно варианта
* 1. header
* 2. article
* 3. aside 1
* 4. aside 2
* 5. footer
*/
/* Средние экраны */
@media all and (min-width: 600px) {
/* Мы говорим обеим боковым панелям встать в одну строку */
.aside { flex: 1 auto; }
}
/* Большие экраны */
@media all and (min-width: 800px) {
/* Мы инвертируем порядок первой боковой панели и основной и говорим главному элементу, чтобы он занимал вдвое большую ширину, чем две другие боковые панели
*/
.main { flex: 2 0px; }
.aside-1 { order: 1; }
.main { order: 2; }
.aside-2 { order: 3; }
.footer { order: 4; }
}



Префикс для Flexbox
@mixin flexbox() {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
@mixin flex($values) {
-webkit-box-flex: $values;
-moz-box-flex: $values;
-webkit-flex: $values;
-ms-flex: $values;
flex: $values;
}
@mixin order($val) {
-webkit-box-ordinal-group: $val;
-moz-box-ordinal-group: $val;
-ms-flex-order: $val;
-webkit-order: $val;
order: $val;
}
.wrapper {
@include flexbox();
}
.item {
@include flex(1 200px);
@include order(2);
}
CSS синтаксис
flex: flex-grow flex-shrink flex-basis | auto | none | initial | inherit;
Возможные значения
|
Значение
|
Описание
|
|---|---|
|
flex-grow
|
Коэффициент растяжения. Коэффициент увеличения ширины флекс-элемента относительно других флекс-элементов.
|
|
flex-shrink
|
Коэффициент сужения. Коэффициент уменьшения ширины флекс-элемента относительно других флекс-элементов.
|
|
flex-basis
|
Базовая ширина флекс-элемента.
|
|
auto
|
Эквивалентно "flex: 1 1 auto;".
|
|
none
|
Эквивалентно "flex: 0 0 auto;".
|
|
inherit
|
Значение наследуется от родительского элемента.
|
|
initial
|
Эквивалентно "flex: 0 1 auto;".
|
Пример использования
#main div {
-webkit-flex: 1; /* Safari 6.1+ */
-ms-flex: 1; /* IE 10 */
flex: 1;
}
Связь Grid позиционирования с другими методами позиционирования
CSS Grid Layout спроектирован таким образом, чтобы работать вместе с другими частями CSS и составлять с ними законченную систему создания макетов страниц. В рамках этого руководства, мы объясним, каким образом сочетать гриды с другими техниками, которыми Вы, возможно, уже пользуетесь в своей работе.
Grid и flexbox
Основное различие между CSS Grid Layout и CSS Flexbox Layout в том, что flexbox предназначен для позиционирования элементов в одном направлении, то есть, либо в строке, либо в колонке. Grid же был разработан для позиционирования элементов в двумерной системе, то есть, для одновременного позиционирования и в строке, и в колонке. Однако, в двух спецификациях есть некоторые общие черты, и если вы уже научились укрощать flexbox, вы увидите сходства, которые помогут вам разобраться и с Grid.
Одномерное vs Двумерное позиционирование
Простой пример поможет нам продемонстрировать разницу между одно- и двумерным позиционированием.
В пером примере мы воспользуемся flexbox для того, чтобы разместить несколько блоков. Предположим, что у нас есть пять дочерних элементов в контейнере, зададим им значения flex-свойств таким образом, чтобы их размер увеличивался и уменьшался, начиная с базового в 200px.
Также установим свойство flex-wrap в значение wrap . Это приведёт к тому, что если свободного пространства в нашем контейнере будет не хватать для размещения элемента в 200px, наши элементы спокойно перейдут на новую строку.
<div class="wrapper">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
</div>
.wrapper {
display: flex;
flex-wrap: wrap;
}
.wrapper > div {
flex: 1 1 200px;
}
На картинке вы видите, что два элемента перешли на новую строку. Эти элементы поделили свободное пространство между собой, а не выровнялись по элементам над ними. Происходит это потому, что каждая новая строка (или колонка, если мы работаем с колонками) становится новым flex-контейнером. А во flex-контейнере распределение свободного пространства действует в рамках всей строки.
Общий вопрос заключается в том, как заставить наши перебежавшие элементы выровняться по элементам сверху. Как раз в этом случае и нужен метод размещения элементов в двумерной системе: требуется выравнивание и по строке, и по колонке, а для этого на помощь спешит Grid.
Тот же макет, но с CSS гридами
В примере ниже мы создаём тот же самый макет, но используя гриды. На этот раз у нас три трека-колонки шириной в 1fr . И при этом нам не требуется задавать какие-либо свойства дочерним элементам, потому что они самостоятельно занимают по одной ячейке созданного грида. Как видите, наши элементы лежат в жёсткой сетке и выравниваются и по строке, и по колонке. Поскольку у нас пять элементов, в результате мы получаем пустую ячейку в конце второй строки.
<div class="wrapper">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
</div>
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
Если вы колеблетесь, что выбрать - flexbox или grid, задайте себе простой вопрос:
-
нужно управлять размещением элементов в строке или в колонке - используем flexbox
-
нужно управлять размещением элементов в строке и в колонке – используем grid
Что важнее: контент или макет?
В дополнение к различию между позиционированию в одном направлении и позиционированию в двух направлениях, существует ещё один способ решить, нужен ли вам макет, основанный на flexbox или макет, основанный на гридах. Flexbox работает исходя из размеров контента. Идеальный случай использования flexbox - когда у вас есть набор элементов, а вам нужно распределить их в контейнере равномерно. Вы позволяете размеру содержимого элементов решить, сколько пространства должен забрать каждый элемент. Если элементы переходят на новую строку, они забирают для себя пространство, исходя из своих размеров и того свободного места, которое есть в этой строке .
Грид работает, исходя из макета. Когда вы используете CSS Grid Layout, вы создаёте структуру и затем размещаете элементы именно в этой структуре или же позволяете правилам авто-размещения разместить элементы в грид-ячейках в соответствии с жёстко заданной сеткой. Конечно, существует возможность создавать треки, подстраивающиеся под размер контента, но при этом они также меняют саму структуру.
Поэтому, если вы используете flexbox и вдруг обнаруживаете, что ограничиваете эластичность элементов, возможно, вам нужно посмотреть в сторону CSS Grid Layout. Например, в том случае, если вы процентами подгоняете ширину flex-элемента, чтобы выровнять его по элементам в строке сверху. В такой ситуации гриды кажутся более оптимальным выбором.
Выравнивание блоков
Самой волнующей функциональностью flexbox для многих из нас была возможность впервые управлять выравниванием блоков. С помощью flexbox можно легко отцентрировать блок на странице. Флекс-элементы способны растягиваться на всю длину контейнера - значит, колонки равной высоты из мечты стали реальностью. Существовал целый ряд вещей, которые нам хотелось сделать очень давно, и для воплощения которых приходилось изобретать различные хаки.
Свойства выравнивания из спецификации flexbox были добавлены в новую спецификацию, названную Box Alignment Level 3. А это означает, что они могут использоваться и в других спецификациях, в том числе и в Grid Layout.
Дальше в нашем руководстве мы подробно рассмотрим выравнивание блоков Box Alignment и то, как оно работает в Grid Layout, а здесь давайте рассмотрим два простых примера, и сравним flexbox и гриды.
В первом примере, использующем flexbox, у нас есть контейнер с тремя элементами. Для блока-обёртки wrapper установлено свойство min-height, и оно задаёт высоту flex-контейнера. Мы установили свойство align-items flex-контейнера в значение flex-end , поэтому элементы выравниваются по концу flex-контейнера. Мы также установили значение свойства align-self для box1 таким образом, что оно перезапишет поведение по умолчанию и заставит наш блок растянутся на всю высоту контейнера. Для box2 свойство align-self установлено таким образом, что блок перепрыгнет в начало flex-контейнера.
<div class="wrapper">
<div class="box1">One</div>
<div class="box2">Two</div>
<div class="box3">Three</div>
</div>
.wrapper {
display: flex;
align-items: flex-end;
min-height: 200px;
}
.box1 {
align-self: stretch;
}
.box2 {
align-self: flex-start;
}
Тем временем в параллельной вселенной: выравнивание в CSS Гридах
Второй пример использует грид, чтобы создать тот же самый макет, и на этот раз мы рассмотрим то, как свойства выравнивания блоков применяются к гридам. Вместо flex-start и flex-end мы задаём start и end . В случае с макетом на гридах мы выравниваем grid-row элементы внутри их грид-области, в данном примере - это одна единственная грид-ячейка, но в целом грид-область может состоять из нескольких грид-ячеек.
<div class="wrapper">
<div class="box1">One</div>
<div class="box2">Two</div>
<div class="box3">Three</div>
</div>
.wrapper {
display: grid;
grid-template-columns: repeat(3,1fr);
align-items: end;
grid-auto-rows: 200px;
}.box1 {
align-self: stretch;
}
.box2 {
align-self: start;
}
Единица fr и flex-basis
Мы уже видели, как работает единица fr в случае пропорционального распределения доступного пространства между грид-треками в грид-контейнере. При комбинировании frс функцией minmax() мы получаем поведение, очень похожее на свойство flex в flexbox - и при этом по-прежнему можем создавать макет в двумерной системе.
Если вернуться к примеру, демонстрирующему различия между одно-и двумерным позиционированиями, можно увидеть, что существует также и различие в самом способе того, как две техники работают с отзывчивыми макетами. С макетом на flex, если мы уменьшаем или увеличиваем размер окна, flexbox аккуратно перераспределяет количество элементов в каждой строке в соответствии с доступным пространством. Так, если у нас достаточно места, чтобы разместить все пять наших элементов в одной строке, они и будут размещены в одной строке. Если же контейнер узкий, то в строке у нас будет место только для одного элемента.
В сравнении грид-версия всегда содержит три трека-колонки. Эти треки-колонки будут расширяться и сужаться, но их всегда будет три, раз мы запросили три при задании грида.
Автозаполнение грид-треков
Можно создать эффект, похожий на поведение flexbox, и при этом по-прежнему держать контент в жёсткой сетке из строк и колонок, если задать структуру треков, используя repeat-нотацию и свойства auto-fill и auto-fit.
В примере ниже мы используем ключевое слово auto-fill вместо целого числа в repeat-нотации и задаём структуру треков размером в 200 пикселей. Это значит, что грид создаст столько треков-колонок размером в 200 пикселей, сколько их может разместиться в контейнере.
<div class="wrapper">
<div>One</div>
<div>Two</div>
<div>Three</div>
</div>
.wrapper {
display: grid;
grid-template-columns: repeat(auto-fill, 200px);
}
Переменное количество треков
Давайте вспомним пример с flexbox, когда элементы, размер которых больше 200 пикселей, переходят на новую строку. Тот же самый эффект в гридах мы можем получить комбинируя auto-fill и функцию minmax(). В примере ниже мы создаём автозаполненные треки с помощью minmax. Мы хотим, чтобы треки были как минимум 200 пикселей в ширину, это наше минимальное значение, а для максимального зададим 1fr. В процессе, когда браузер вычисляет, сколько блоков в 200 пикселей может разместиться в контейнере - при этом учитывая грид-зазоры - он расценивает максимум 1fr как инструкцию распределить оставшееся свободное пространство между этими блоками.
<div class="wrapper">
<div>One</div>
<div>Two</div>
<div>Three</div>
</div>
.wrapper {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
Собственно, теперь у нас есть возможность создавать гриды с переменным количеством или с переменным размером треков и при этом по-прежнему держать элементы в жёсткой сетке из строк и колонок.
Гриды и абсолютно позиционированные элементы
Грид взаимодействует с абсолютно позиционированными элементами, что отнюдь не бесполезно, если вы хотите разместить элемент внутри грида или грид-области. В спецификации описано поведение грида и тогда, когда грид-контейнер является контейнерным блоком (containing block) и тогда, когда грид-контейнер - родительский элемент для абсолютно позиционированного элемента.
Грид-контейнер как контейнерный блок
Для того, чтобы превратить грид-контейнер в контейнерный блок вам нужно добавить ему свойство position со значением relative. Если после этого задать какому-нибудь грид-элементу position:absolute , грид-контейнер станет контейнерным блоком для данного элемента.
В примере ниже у нас есть блок-обёртка с четырьмя дочерними элементами. Третий элемент абсолютно позиционирован и одновременно размещён в гриде с помощью привязки к грид-линиям. У грид-контейнера position:relative , поэтому он становится контекстом позиционирования для нашего третьего элемента.
<div class="wrapper">
<div class="box1">One</div>
<div class="box2">Two</div>
<div class="box3">
Этот блок абсолютно позиционирован.
В нашем примере грид-контейнер является контейнерным блоком, поэтому значения сдвига абсолютного позиционирования отсчитываются от внешнего края той области, в которой размещён элемент.
</div>
<div class="box4">Four</div>
</div>
.wrapper {
display: grid;
grid-template-columns: repeat(4,1fr);
grid-auto-rows: 200px;
grid-gap: 20px;
position: relative;
}
.box3 {
grid-column-start: 2;
grid-column-end: 4;
grid-row-start: 1;
grid-row-end: 3;
position: absolute;
top: 40px;
left: 40px;
}
Вы видите, что наш элемент занимает область от колоночной грид-линии 2 до колоночной грид-линии 4 и начинается после строчной линии 1. С помощью свойств left и top мы сдвигаем его относительно этой области. В то же время, он изымается из потока так же, как и любой другой элемент с абсолютным позиционированием, поэтому правила авторазмещения теперь помещают другие элементы на его место. Абсолютное позиционирование нашего элемент также не приводит к появлению новой строки.
Попробуйте удалить position:absolute из правил для .box3 , и увидите, как он размещался бы без абсолютного позиционирования.
Грид-контейнер в качестве родительского элемента
Если у абсолютно позиционированного элемента в качестве родительского контейнера выступает грид, не создающий новый контекст позиционирования, наш элемент также вытаскивается из потока, как и в предыдущем примере. Но в этом случае контекстом позиционирования будет любой элемент, который как раз и создаёт этот контекст позиционирования. Словом, если в нашем примере мы уберём position:relative из блока-обёртки, контекстом позиционирования станет область просмотра, что хорошо видно на рисунке ниже.

Ещё раз: наш элемент больше не занимает пространство в грид-макете и не влияет на то, как располагаются другие элементы при авторазмещении.
А что если родительский элемент - это грид-область?
Если абсолютно позиционированный элемент находится в грид-области, вы можете создать контекст позиционирования из этой области. В примере ниже у нас тот же грид-макет, что и раньше, но теперь мы разместили элемент внутри .box3 .
Задаём .box3 свойство position в значении relative и затем перемещаем наш под-элемент с помощью свойств сдвига. В данном случае контекстом позиционирования является грид-область.
<div class="wrapper">
<div class="box1">One</div>
<div class="box2">Two</div>
<div class="box3">Three
<div class="abspos">
Этот блок абсолютно позиционирован. В данном примере контекстом позиционирования является грид-область, поэтому значения сдвига отсчитываются от внешних краёв грид-области.
</div>
</div>
<div class="box4">Four</div>
</div>
.wrapper {
display: grid;
grid-template-columns: repeat(4,1fr);
grid-auto-rows: 200px;
grid-gap: 20px;
}
.box3 {
grid-column-start: 2;
grid-column-end: 4;
grid-row-start: 1;
grid-row-end: 3;
position: relative;
}
.abspos {
position: absolute;
top: 40px;
left: 40px;
background-color: rgba(255,255,255,.5);
border: 1px solid rgba(0,0,0,0.5);
color: #000;
padding: 10px;
}
Грид и display:contents
Последнее, о чем нужно упомянуть, говоря о взаимодействии гридов с другими спецификациями, касающимися позиционирования элементов, - это взаимодействие между CSS Grid Layout и display:contents. Значение contents свойства display - новое свойство CSS, которое описывается в спецификации Display следующим образом:
“Сам элемент не генерирует никаких блоков (боксов), но его дочерние элементы и его псевдо-элементы по-прежнему генерируют блоки, в установленном порядке. Относительно генерации и позиционирования блоков элемент должен восприниматься так, как если бы он полностью замещался своими дочерними элементами и псевдо-элементами в дереве документа.”
Если вы пишете для элемента display:contents , блок (бокс), который он должен создать в дереве документа исчезает, а вот блоки его дочерних элементов и его псевдо-элементов переходят на один уровень вверх. А значит это то, что дочерние элементы грид-элемента могут сами стать грид-элементами. Звучит непонятно? Давайте разберёмся на простом примере. В разметке ниже у нас есть грид. Первый элемент этого грида настроен так, чтобы занимать все три трека-колонки. У него есть три вложенных элемента. Поскольку эти вложенные элементы не являются прямыми потомками грида, они не становятся частью грид-макета и отображаются, как обычные блоки.
<div class="wrapper">
<div class="box box1">
<div class="nested">a</div>
<div class="nested">b</div>
<div class="nested">c</div>
</div>
<div class="box box2">Two</div>
<div class="box box3">Three</div>
<div class="box box4">Four</div>
<div class="box box5">Five</div>
</div>
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(100px, auto);
}
.box1 {
grid-column-start: 1;
grid-column-end: 4;
}
Если мы теперь добавим правило display:contents для box1, блок этого бокса исчезнет, зато дочерние элементы станут грид-элементами и будут расположены в соответствии с правилами авторазмещения.
<div class="wrapper">
<div class="box box1">
<div class="nested">a</div>
<div class="nested">b</div>
<div class="nested">c</div>
</div>
<div class="box box2">Two</div>
<div class="box box3">Three</div>
<div class="box box4">Four</div>
<div class="box box5">Five</div>
</div>
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(100px, auto);
}
.box1 {
grid-column-start: 1;
grid-column-end: 4;
display: contents;
}
Таким образом мы можем заставить вложенные элементы вести себя, словно они часть грида (и в некотором смысле имитация того поведения, которое должны будут реализовать подгриды (subgrids), когда руки разработчиков браузеров до них доберутся). Точно так же можно использовать display:contents с flexbox, чтобы вложенные элементы становились flex-элементами.