Гибкие флексбоксы flex — Тренажёр HTML Academy
В предыдущей статье мы начали верстать сетки с помощью плавающих элементов float
, но это уже достаточно устаревшая методика, да и сам float
изначально задумывался не для этого.
В этой статье мы погрузимся в изучение свойств, которые были разработаны специально для создания сеток и сложных раскладок боксов, без костылей, распорок и других неприятных нюансов. Поговорим, наконец, о флексах flex
!
Флексбокс
Чтобы контейнеру задать свойства «гибких контейнеров» или просто «флексбоксов», достаточно указать его тип display: flex;
.
Сразу после этого бокс к которому было применено это свойство становится «флекс-контейнером», а его прямые потомки, то бишь дочерние элементы, становятся «флекс-элементами» или «флекс-итемами» (flex-item).
Сам по себе флекс-контейнер внешне никак не меняется, зато флекс-итемы максимально ужимаются по ширине и выстраиваются в одну строку, а их высота растягивается на всю высоту флекс-контейнера.
Это происходит потому, что во флекс-контейнере тоже меняется направление потока. Я когда писал про логику float
как-то не задумывался, что во флексах, в общем-то ситуация похожая.
Причем, направлением потока можно управлять не только влево или вправо, а разворачивать и поворачивать. Поэтому во флекс-контейнерах принято говорить не о направлении потока, а о главной и поперечной осях.
Управляет направлением этих осей свойство flex-direction
, которое имеет четыре простых значения:
row
— по умолчанию, «в строку», то есть главная ось направлена слева направо и флекс-итемы располагаются вдоль неё;column
— «в столбец», главная ось направлена сверху вниз, но при этом работают все гибкие правила для флекс-итемов;row-reverse
иcolumn-reverse
— оба свойства просто разворачивают ось соответственно, справа налево и снизу вверх.
Выравнивание флекс-элементов
За выравнивание флекс-итемов вдоль главной оси флексбокса отвечает свойство justify-content
и имеет оно аж шесть значений, три стандартных и понятных:
flex-start
— значение по умолчанию, итемы прижаты к началу главной оси;flex-end
— итемы прижаты к концу главной оси;center
— итемы расположены по центру контейнера вдоль главной оси.
И три значения, которые не прижимают, а распределяют итемы:
space-between
— равномерно распределяет итемы вдоль всей главной оси, без отступов от краёв флекс-контейнера;space-around
— равномерно распределяет итемы вдоль главной оси, с отступом от края флекс-контейнера равным половине отступа между флекс-итемами;space-evenly
— равномерно распределяет итемы вдоль оси с равными отступами от краёв контейнера и между собой.
Будет, наверное, проще показать, чем пытаться объяснять все словами. Правда, в тренажёре у итемов есть еще внешние отступы margin
, которые могут немного ввести в заблуждение. Поэтому я добавил поверх еще поля:
Вдоль поперечной оси тоже можно выравнивать итемы с помощью свойства align-items
— у него пять значений:
stretch
— по умолчанию, растягивает флекс-итем вдоль поперечной оси, если не задан конкретный размер;flex-start
— прижимает итемы к началу поперечной оси, при этом размер итема вдоль поперечной оси ужимается до размера контента;flex-end
— прижимает к концу поперечной оси;center
— выравнивает по центру вдоль поперечной оси;baseline
— выравнивание итемов по базовой линии текста.
Выравнивание вдоль поперечной оси можно задать не только всем итемам, но и отдельно взятому, с помощью свойства align-self
. В этом случае свойство применяется уже не к контейнеру, а к самому флекс-итему. Свойство align-self
имеет такие же значения что и align-items
.
Итак, с одной строкой флекс-итемов разобрались.
Перенос и выравнивание строк во флексбоксе
Сколько флекс итемов можно поместиться на одной строке? Все сразу. По умолчанию во флекс-контейнере нет переноса строки — все элементы будут сжиматься и влезать в один ряд, а когда сжиматься уже некуда — контент элементов начнет вылезать из флекс-контейнера.
Не очень приятная особенность, но к счастью, переносом строки можно управлять с помощью свойства flex-wrap
! Оно имеет три значения:
nowrap
— по умолчанию, флекс-элементы не переносятся;wrap
— разрешает перенос элементов на новую строку, бокс флекс-итема начинает учитываться и перенос осуществляется если очередной бокс не умещается в строку;wrap-reverse
— перенос будет осуществляться в обратную сторону, то есть вверх, не поместившийся в строку элемент переместится выше, а строка сместиться вниз.
При включении переноса строки flex-wrap
во флекс-контейнере начинает работать еще одно интересное свойство — align-content
управление выравниванием строк.
Оно очень похоже на свойство justify-content
и имеет почти такие же значения, включая значения распределения, например, space-between
и подобные ему. Но имеет еще одно — stretch
значение по умолчанию.
Только в случае align-content
выравниваются не флекс-элементы вдоль главной оси, а строки элементов вдоль поперечной оси.
Важно понимать еще отличие align-items
, отвечающего за выравнивание элементов на строке вдоль поперечной оси, от align-content
, отвечающего за выравнивание строк в контейнере вдоль поперечной оси.
Опять же, проще будет показать на примере, иначе можно запутаться:
Важно еще заметить, что значение по умолчанию stretch
работает только если оно задано обоим свойствам align-items
и align-content
. Иначе, если в одном из них задано отличное от stretch
значение, то у второго оно игнорируется.
При этом, если оба свойства отличны от значения по умолчанию stretch
, то свойство align-content
имеет приоритет над align-items
, даже если оно указано выше в коде.
Ещё в этой части тренажёра рассмотрено свойство order
отвечающий за порядковый номер флекс-итема. Свойства указывается именно элементу и с его помощью можно изменить его расположение.
Например задав значение -1
можно вывести элемент вперёд остальных, даже если он расположен после всех.
С положением и выравниванием элементов разобрались, переходим к размерам!
Блочная модель во флексбоксах
Флекс-контейнер сам по себе не изменяется и для него работает стандартная блочная модель. Для флекс-итемов же есть свои нюансы.
Им можно задать размеры width
и height
, рамку border
и внутренние отступы padding
, которые будут работать так же по стандартной блочной модели. К ним тоже можно применить свойство box-sizing
для изменения расчёта размера бокса с учётом отступов.
С внешними отступами margin
уже начинаются отличия:
margin
не «схлопываются» ни горизонтально, ни вертикально;margin
не «выпадают» из флекс-контейнера и из флекс-итема;- значение
margin: auto;
работает во всех направлениях, включая по вертикали, при этом имеет приоритет над свойствами распределения флекс-элементовjustify-content
,align-items
иalign-self
;
Но самый важный нюанс флексбоксов — стандартные, «нефлексовые» свойства размеров и отступов не понимают направления осей. Для margin-left
существует только одно направление — лево, отступ заданный через это свойство будет всегда слева, неважно куда направлена главная ось флекс-контейнера.
Аналогично, ширина width
будет только горизонтальным размером указанного элемента, неважно что указано в свойстве flex-direction
. Это с одной стороны логично, с другой стороны усложняет работу с флексбоксами.
Немного упрощает это дело ряд свойств придуманных специально для работы с флекс-итемами. Первый такой — flex-basis
, который задаёт элементу его базовый размер вдоль главной оси флекс-контейнера.
Свойство flex-basis
, в рамках флекс-контейнера, имеет приоритет над стандартными свойствами width
и height
и переопределит одно из них в зависимости от направления главной оси.
Почему размер базовый? Остальные два рассмотренных в тренажёре свойства — это модификаторы этого базового размера. Им посвящена значительная часть уроков, так как с ними много нюансов.
Коэффициенты расширения и сжатия
Первым модификатором базового размера рассмотрим коэффициент расширения или растягивания flex-grow
. По умолчанию имеет значение 0
, то есть «не расширяется». Любое другое положительно значение определяет пропорцию свободного пространства, которое займет указанный элемент.
Например, если мы имеем два элемента во флекс-контейнере, с одинаковыми базовыми размерами flex-basis
, то вот что получится с разными flex-grow
:
Это простейший пример — flex-grow
пытается занять максимальное количество свободного пространства. Поэтому если значения расширения равны, то оба элемента займут одинаковое пространство. Если же flex-grow
задан только одному флекс-итему, то он займет всё свободное пространство и прижмёт второй элемент.
Важно заметить — занимается именно свободное, то есть не занятое базовыми размерами flex-basis
пространство. Поэтому его тоже нужно учитывать в формуле расчёта:
Выглядит страшно, но, на самом деле, всё достаточно просто. Для упрощения формулы часто используется прием «нулевого» базового размера flex-basis
и свойства min-width
или min-height
:
flex-basis: 0%; min-width: 50px;
Таким образом расчет будет сильно упрощён и по сути прямо пропорционален значению flex-grow
. Дело в том, что ограничительные свойства типа min/max применяются и проверяются уже после перераспределения свободного места.
Второй на очереди коэффициент сжатия flex-shrink
— он похож на коэффициент расширения, но работает в обратную сторону. По умолчанию имеет значение 1
, то есть все флекс-элементы пропорционально сжимаются, чтобы уместиться на одной строке.
Если же задать коэффициент сжатия flex-shrink: 0;
, то флекс-итем не будет сжиматься и будет иметь фиксированный размер flex-basis
независимо от оставшегося свободного места.
Если сумма всех flex-basis
итемов в контейнере будет превышать его размер и при этом коэффициент сжатия всех элементов будет равен 0
, то возникнет выпадение из контейнера. Или, как его назвали в тренажёрах, отрицательное пространство — область на которую выпал элемент или элементы.
Это, на мой взгляд, ну очень гипотетическая ситуация, но на её примере в тренажёре объясняется расчёт итогового размера элемента при сжатии. Предположим, что у нас значительно выпали элементы и нам нужно найти коэффициенты сжатия для них:
Когда я увидел это в тренажёре я, мягко говоря, впечатлился. Здесь уже не упростишь — считай как есть, причем в итоге поиск одного коэффициента зависит от подстановки других. Оно находится достаточно быстро, но это, честно говоря, какой-то идиотизм.
Я могу только нафантазировать такую ситуацию, но скорее всего, в реальности эти подсчеты пригодятся один раз на тысячу. Хотя, понимать как работает сжатие флекс-итемов полезно и интересно.
Все эти три свойства объединяет в себе сокращенное свойство flex
, правда, порядок значений не тот в котором мы их рассмотрели.
Порядок следующий — flex-grow
, flex-shrink
и flex-basis
:
.item { flex-grow: 0; flex-shrink: 1; flex-basis: 50px; } /* эквивалент */ .item { flex: 0 1 50px; }
Испытания
Испытаний очень много — шесть штук. Плюс, должен сказать, что параллельно в уроках тоже было много практики, часть уроков в обеих частях про Флексбоксы были как такие мини-испытания.
Эти части одни из самых объемных в плане практики.
Перейдем к самим Испытаниям. Первые три на понимание свойств распределения и выравнивания флекс-итемов. Сначала крайне простой однострочный флексбокс:
Второе испытание закрепляет свойство направления оси flex-direction
и свойство порядкового номера флекс итема order
:
Третье испытание лютое комбо из многострочного флексбокса и селекторов, вспоминаем прошлый блок:
Далее три испытания на базовый размер flex-basis
, понимание отступов и блочной модели и модификаторы flex-grow
и flex-shrink
. Четвёртое испытание опять на подбор циферок, нужно подвести флекс-итемы используя только margin
:
Пятое испытание на понимание модификаторов flex-grow
и flex-shrink
:
И последнее шестое тоже на модификаторы, но в случае многострочного флекс-контейнера flex-wrap: wrap;
:
Пожалуй, разделю еще на одну статью — о гридах поговорим в следующий раз. Флексы оказались темой еще более серьёзной и большой! Особенно впечатлили формулы модификаторов, но и сам подход гибкой раскладки достаточно трудноусваиваемый.
Это было неожиданно тяжело! Не в плане обучения, а в плане статей. Дело в том, что повествование в тренажёрах не ложится нормально на статью. Где-то половину, а то и больше, времени от написания статьи я её, в общем-то, не пишу, а сижу и пытаюсь придумать как понятнее написать то, что показано в тренажёре.
Просто копировать текст из конспектов бессмысленно, я же для себя стараюсь, для усвоения материала. Но это мои проблема, а вам спасибо большое за внимание!
Ссылки на предыдущие статьи по HTML Academy:
Знакомство с Веб-разработкой
Знакомство с HTML и CSS
Знакомство с JavaScript
Знакомство с PHP
Таблицы и подробно о формах
Наследование, каскады и селекторы
Блочная модель, поток и сетка на float
Гибкие флексбоксы display: flex <- Вы здесь
Удобные сетки на гридах display: grid
Пропуск блока «Погружение»
Позиционирование и двумерные трансформации
Теневое искусство и линейные градиенты
CSS-фильтры и Кекстаграм
Мастерские
Продвинутые Мастерские
...
Остальные статьи можно посмотреть у меня на главной странице блога.
Также мои соц. сетки, которые я продолжаю вести:
Мой Twitter
Мой Telegram
Мой Паблик ВК
Заходите куда удобно вам и подписывайтесь! Еще раз спасибо за внимание!