Гибкие флексбоксы 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
Мой Паблик ВК
Заходите куда удобно вам и подписывайтесь! Еще раз спасибо за внимание!