Флексбокс — это первый CSS-механизм, предназначенный для построения сеток и создания сложных раскладок блоков.
Другие механизмы, с помощью которых мы раньше строили сетки, задумывались совсем не для этого: плавающие блоки нужны для создания блоков, которые обтекает текст, а таблицы используются для разметки табличных данных.
Для активации этого нового механизма необходимо элементу свойство display: flex;
. После этого происходит два события:
- Элемент с
display: flex;
превращается во «флекс-контейнер» и внутри него начинает происходить вся магия гибкой раскладки. - Непосредственные потомки этого элемента превращаются во «флекс-элементы» и начинают играть по новым правилам.
Первое, что вы заметите после активации, это то, что блоки растянутся на всю высоту контейнера и самое важное внутри флексбокса можно делать элементы одинаковой высоты!
Заметьте, что флекс-элементами внутри флекс-контейнера становятся только прямые потомки, элементы первого уровня вложенности.
Вспомните, как ведёт себя обычный поток документа. Блоки и текст располагаются слева направо и сверху вниз.
В привычной блочной модели направления «лево», «право», «верх» и «низ» неизменны. Но внутри флекс-контейнера эти понятия могут изменяться, потому что там можно изменять обычное направление потока.
Вместо направлений «лево» и «право» во флексбоксе используется понятие «главная ось». Поток флекс-элементов «течёт» вдоль главной оси от её начала к её концу.
По умолчанию главная ось направлена слева направо, но её можно разворачивать во всех направлениях с помощью свойства flex-direction, которое задаётся для флекс-контейнера. Значения свойства:
- row — значение по умолчанию, главная ось направлена слево направо.
- column — главная ось направлена сверху вниз.
- row-reverse — главная ось направлена справа налево.
- column-reverse — главная ось направлена снизу вверх.
Флекс-элементы всегда располагаются вдоль главной оси, независимо от её направления.
Вместо направлений «верх» и «низ» во флексбоксе используется понятие «поперечная ось». Вдоль этой оси рассчитывается высота элементов и работают «вертикальные» выравнивания.
Поперечная ось всегда перпендикулярна главной оси и поворачивается вместе с ней:
- Если главная ось направлена горизонтально, то поперечная ось смотрит вниз.
- Если главная ось направлена вертикально, то поперечная ось смотрит направо.
Это не совсем логичное поведение, к которому надо привыкнуть. Получается, что поперечная ось никогда не смотрит вверх или влево. А свойства для поворота поперечной оси нет.
Вместо «горизонтального» выравнивания во флексбоксе используется свойство для распределения элементов вдоль главной оси — justify-content. Это свойство задаётся для флекс-контейнера.
Его значением по умолчанию является flex-start. При этом значении элементы располагаются у начала главной оси. Оно же является и значением по умолчанию.
Чтобы элементы располагались по центру главной оси, нужно задать для justify-contentзначение center.
А значение flex-end расположит элементы в конце главной оси.
Обратите внимание, что justify-content: flex-end не меняет порядок элементов, как это происходит при изменении направления оси flex-direction: row-reverse. Элементы просто прижимаются к концу главной оси.
У флексбокса есть чем-то похожие значения justify-content, которые равномерно распределяют флекс-элементы вдоль главной оси: space-between — расстояния между соседними элементами одинаковые, между элементами и краями флекс-контейнера отступов нет. space-around — расстояния между соседними элементами одинаковые, между элементами и краями флекс-контейнера есть отступ, равный половине расстояния между соседними элементами.
Вместо «вертикального» выравнивания во флексбоксе используется свойство для выравнивания элементов вдоль поперечной оси — align-items. Это свойство задаётся для флекс-контейнера.
Его значением по умолчанию является stretch. Именно благодаря этому значению флекс-элементы и растягиваются на всю «высоту» флекс-контейнера. Если флекс-элементам задана высота, то растягиваться они не будут.
Чтобы элементы выровнялись по центру поперечной оси, нужно задать для align-itemsзначение center.
Чтобы расположить флекс-элементы в начале или в конце поперечной оси, нужно использовать значения flex-start и flex-end для свойства align-items.
Ещё одно значение свойства align-items — это baseline. Если задать его контейнеру, то флекс-элементы будут выравниваться по базовой линии текста в них. Эта воображаемая линия проходит по нижней части букв.
Если выровнять флекс-элементы по базовой линии, то они выстроятся так, чтобы текст в них был как бы на «одной строке».
Распределение элементов по главной оси задаётся для всего флекс-контейнера и на все флекс-элементы действует одинаково. Задать какому-то элементу отличное от других распределение по главной оси нельзя. И это вполне логично, ведь тогда элементы будут «сталкиваться» друг с другом.
C поперечной осью всё проще. Можно сказать, что у каждого элемента она своя, и можно задавать им разное поперечное выравнивание. Для этого используется свойство align-self, которое задаётся для самих флекс-элементов, а не для флекс-контейнера.
У свойства align-self те же самые значения, что и у align-items. Аналогично align-items для отдельного флекс-элемента можно задать и выравнивание по базовой линии с помощью align-self со значением baseline.
Что будет, если флекс-элементов в контейнере станет больше, чем может уместиться в один ряд?
- Они будут сжиматься до минимально возможной ширины.
- Даже если им задать ширину явно, механизм флексбокса может её уменьшить.
- Если они перестанут помещаться в контейнер и после уменьшения, то они выйдут за его пределы, но продолжат располагаться в один ряд.
Это чем-то похоже на поведение ячеек в таблице.
Такое поведение можно изменить свойством флекс-контейнера flex-wrap. По умолчанию оно имеет значение nowrap, то есть перенос флекс-элементов на новую строку запрещён.
Значение wrap разрешает перенос флекс-элементов на новую строку, если они не помещаются в контейнер.
Если перенос флекс-элементов разрешён, то ряды элементов располагаются вдоль поперечной оси. Первый ряд располагается в начале поперечной оси, а последний в конце. Но так работает только значение wrap.
Если для flex-wrap задать значение wrap-reverse, то элементы будут переноситься, а ряды будут располагаться в обратном порядке: первый в конце поперечной оси, а последний в начале.
Вспомним свойство justify-content, которое управляет распределением флекс-элементов вдоль главной оси.
Есть очень похожее свойство align-content, которое управляет выравниванием рядов флекс-элементов вдоль поперечной оси. У этих свойств почти одинаковые значения:
- flex-start,
- flex-end,
- center,
- space-between,
- space-around,
- и stretch, которое есть только у align-content и является значением по умолчанию.
Свойство align-content связано и со свойством align-items, которое управляет выравниванием флекс-элементов вдоль поперечной оси.
В чём разница между align-content и align-items, когда работает одно, а когда работает другое? Вот ответы:
- Если есть только один ряд флекс-элементов, то работает align-items.
- Если есть несколько рядов, то работает align-content.
- Подчеркнём, что align-content влияет на ряды, а не на отдельные элементы.
В последней версии спецификации это поведение изменилось: теперь правильно, когда align-content выравнивает элементы в многострочном флекс-контейнере, даже если строка в контейнере единственная. Это изменение на момент окончания 2015 года применено только в браузерах Safari и Edge.
Ранее мы говорили, что как только во флекс-контейнере появляется несколько рядов элементов, вместо align-items начинает действовать свойство align-content.
В этом случае align-items не отключается полностью, а может влиять на отображение флекс-элементов в рядах.
Это происходит, когда мы используем для align-content значение по умолчанию — stretch. Оно растягивает ряды флекс-элементов, при этом оставшееся свободное место между ними делится поровну.
Отображение строк при align-content: stretch зависит от значения align-items:
- Если у align-items задано значение stretch, то элементы в строках растягиваются на всю высоту своей строки.
- Если значение отлично от stretch, то элементы в строках ужимаются под своё содержимое и выравниваются в строках в зависимости от значения align-items.
Значение align-items влияет на отображение рядов во флекс-контейнере, если у align-content задано значение stretch. В этом мы убедились в прошлом задании.
Есть ли похожее влияние на остальные значения align-content? Нет.
Убедимся в этом на примере значения center, которое располагает ряды в середине поперечной оси так, что:
- отступов между соседними рядами нет (но отступы самих элементов сохраняются),
- расстояние между первым рядом и краем флекс-контейнера равно расстоянию между последним рядом и другим краем.
Остальные четыре значения свойства align-content аналогичны значениям свойства justify-content, отличается только ось:
- flex-start располагает ряды в начале поперечной оси.
- flex-end располагает ряды в конце поперечной оси.
- space-between равномерно распределяет ряды вдоль поперечной оси, расстояния между соседними рядами одинаковые, отступов у краёв нет.
- space-around равномерно распределяет ряды вдоль поперечной оси, расстояния между соседними рядами одинаковые, отступы у краёв равны половине расстояния между соседними рядами.
Напоследок небольшое резюме.
Свойство align-content — «гибридное». Мы переводим его как «выравнивание», но оно больше похоже на «распределение», justify-content, от которого оно позаимствовало два значения space-between и space-around.
Близость с «распределением» подчёркивает и отсутствие значения baseline — всё-таки свойство работает с рядами, а не с отдельными элементами.
От «выравниваний» же, align-items и align-self, это свойство получило значение по умолчанию stretch и возможность «растягивать» ряды по высоте.
И ещё одно свойство, которое мы рассмотрим, — это order, порядковый номер флекс-элемента.
Это очень полезное свойство, так как с его помощью можно менять порядок следования флекс-элементов в потоке, не меняя HTML-код. По умолчанию порядковый номер флекс-элементов равен 0, а сортировка элементов производится по возрастанию номера.Порядковый номер задаётся целым числом, положительным или отрицательным.
Флекс-элемент внутри флекс-контейнера можно также сделать флекс-контейнером.
Он будет одновременно вести себя и как флекс-элемент, то есть подчиняться правилам распределения и выравнивания своего родителя, и как самостоятельный флекс-контейнер. При этом его вложенные элементы первого уровня будут следовать только его флекс-правилам.
Применение такого типа верстки:
Самый насущный вопрос, который можно легко и изящно решить с помощью флексбокса, — как отцентровать элемент по вертикали и горизонтали так, чтобы центровка сохранялась при изменении размеров элемента или контейнера.
Ответ прост: задать контейнеру раскладку флексбокса, а дочернему флекс-элементу margin: auto. В этом случае флекс-элемент уменьшит свой размер под содержимое и отцентруется по вертикали и горизонтали.
Стоит обратить внимание на интересный момент. Если центруемых флекс-элементов в контейнере будет несколько, то отступы между ними будут равномерными. То есть будет происходить распределение элементов внутри флекс-контейнера чем-то похожее на justify-content: space-around.
“Гибкое меню”
Флексбокс полезен при создании блоков с дочерними элементами динамической длины. Хороший пример — меню. Часто встречаются дизайны, в которых пункты равномерно распределены по блоку меню. Первый пункт примыкает к левой части блока меню, а последний — к правой, причём с небольшими внутренними отступами. Эту задачу можно попытаться решить, задав фиксированные отступы и ширину пунктам меню. Но такой способ не подойдёт, если количество пунктов меню или подписи внутри них будут изменяться.
И тут на помощь приходит флексбокс. Зададим меню раскладку флексбокса, пункты станут флекс-элементами. С помощью свойства распределения элементов justify-content
добьёмся нужного результата.
Интересного эффекта можно достичь, если скомбинировать флексбокс и трюк с селектором :checked ~
.
Приём заключается в следующем: с помощью селектора по выделению чекбокса можно управлять порядком флекс-элементов, изменяя направление главной оси с помощью flex-direction
. Лучше всего эффект работает, когда направление главной оси меняется с «сверху вниз» на «снизу вверх».
При этом флекс-контейнер должен находиться в разметке на одном уровне с чекбоксом.
Таким образом реализуется сортировка на CSS, без использования JavaScript.
Ещё одна часто встречающаяся задача — реализовать раскладку с блоками одинаковой высоты.
Надо учитывать, что содержимое блоков может быть разным и их высота может меняться.
В обычной блочной модели есть фундаментальный недостаток — соседние блоки ничего не знают друг о друге, поэтому их высоты нельзя «связать». Получается, что все «стандартные» варианты для решения этой задачи не работают:
- float или inline-block не могут «связывать» высоты соседних блоков;
- таблицы и CSS-таблицы позволяют делать ячейки одинаковой высоты, но появляются ограничения, связанные с расположением элементов в строках;
- минимальная высота не подходит, так как какой-то из блоков всегда может стать выше остальных;
- конечно, можно задать всем блокам фиксированную высоту, но это решение совсем не универсальное.
А с помощью флексбоксов эта проблема решается легко и изящно, ведь флекс-элементы по умолчанию растягиваются на всю высоту контейнера.
Например:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
.columns { display:flex; flex-wrap:wrap; } .columns section { float: left; width: 140px; } <div class="columns"> <section> <h2>Дело №1</h2> <p>Проснуться, сделать зарядку.</p> </section> <section> <h2>Дело №2</h2> <p>Совершить экспедицию на кухню, полакомиться рыбкой и икрой из холодильника.</p> </section> <section> <h2>Дело №3</h2> <p>Передохнуть от тяжких трудов, поспать.</p> </section> <section> <h2>Дело №4</h2> <p>Навести беспорядок, покусать человека за пятки, сбросить с полки цветочный горшок.</p> </section> <section> <h2>Дело №5</h2> <p>Выкрасть сметану из холодильника.</p> </section> <section> <h2>Дело №6</h2> <p>Выяснить отношения с соседским котом.</p> </section> </div> |
Флекс и блочная модель
Ширина, высота, внутренние отступы и рамки для флекс-контейнеров и флекс-элементов работают как обычно: общий размер элементов складывается из этих компонентов. Это поведение так же можно менять с помощью свойства box-sizing.
Есть и несколько важных отличий:
- флекс-элементы, в отличие от блочных элементов, не растягиваются на всю ширину контейнера по умолчанию;
- на флекс-элементы не действует свойство float.
Свойство margin, таит много сюрпризов:
- внешние отступы не схлопываются, ни по горизонтали, ни по вертикали;
- внешние отступы не выпадают, ни из флекс-контейнера, ни из флекс-элементов;
- значение auto получило премию журнала Форбс в номинации «Самое влиятельное значение CSS-свойства внутри флекс-контейнера».
Всё дело в механизме распределения свободного места. Если внутри флекс-контейнера есть свободное место, то оно перераспределяется так:
- находятся элементы, у которых есть внешние отступы со значением auto;
- всё свободное место в соответствующих направлениях отдаётся таким отступам (то есть задаётся определённый размер отступа в пикселях);
- если элементов с автоматическими отступами на одном направлении несколько, то место между ними перераспределяется поровну;
- только после этого запускаются механизмы выравнивания.
Поэтому margin: auto; влияет на положение флекс-элементов на обеих осях, а также «ломает» механизмы выравнивания, ведь выравнивание происходит, когда есть свободное место. Но если всё свободное место «перетекло» в автоматический отступ, то и выравнивать нечего. Эти особенности можно использовать во благо. Например, с помощью автоматических отступов вы можете управлять расположением элементов вдоль главной оси.
Кроме того, мы убедились, что такие отступы «ломают» свойство justify-content.
Автоматический margin влияет и на выравнивание флекс-элементов вдоль поперечной оси.
Если у флекс-элемента отступ сверху или снизу автоматический, то на него не влияют, ни align-items, ни align-self. Такой элемент прижмётся либо к верху контейнера, либо к низу.
А если задать автоматические отступы с противоположных сторон, то элемент разместится по центру флекс-контейнера, так как свободное место «впитается» отступами поровну.
Дело в том, что «старые нефлексовые» свойства, такие как отступы или размеры, ничего не знают про направление осей. Они «мыслят по-старому», понятиями «верх» и «низ», «право» и «лево».
Поэтому когда главная ось направлена слева направо, горизонтальные отступы перемещают флекс-элементы вдоль главной оси. Но если направить главную ось сверху вниз, то те же отступы начнут работать вдоль поперечной оси. То же относится и к вертикальным отступам.
На примере отступов видно, что «старые» свойства внутри флекс-контейнера ведут себя достаточно глупо. Ширина и высота тоже не умеют реагировать на поворот главной оси. Поэтому ввели понятия главный размер или main size и поперечный размер или cross size.
Если главная ось направлена горизонтально, то главный размер — это ширина, свойство width, а поперечный размер — это высота, свойство height. Если главная ось направлена вертикально, то всё наоборот.
А хотелось бы иметь «умное» свойство для задания размера флекс-элементов, которое знает про главную ось и «поворачивается» вместе с ней.
И такое свойство есть — это flex-basis. Оно задаёт базовый размер флекс-элемента или размер вдоль главной оси.
Если flex-basis не задан или его значение равно auto, то базовый размер берётся из width или height.
Свойство flex-basis принимает те же значения, что и width или height.
Свойство flex-basis «сильнее» свойств width и height, и если у флекс-элемента заданы все три свойства, то flex-basis переопределит либо ширину, либо высоту в зависимости от направления главной оси
На самом деле, базовый размер — это не просто размер элемента вдоль главной оси, это начальный или исходный размер вдоль главной оси.
Почему так важны эти начальный или исходный? И снова всё дело в механизме перераспределения свободного места во флексбоксе.
Если внутри флекс-контейнера по главной оси остаётся свободное место, то мы можем попросить флекс-элемент, чтобы он увеличился и занял это место. Это делается с помощью свойства flex-grow, которое можно назвать «коэффициентом флекс-жадности» флекс-элемента.
Свойство flex-grow принимает неотрицательные числовые значения, его значение по умолчанию — 0.
Если значение flex-grow равно нулю, то флекс-элемент «не претендует» на оставшееся свободное место во флекс-контейнере и не будет увеличиваться, чтобы занять это место.
Если значение flex-grow больше нуля, то флекс-элемент будет увеличиваться, «захватывая» оставшееся свободное место.
Получается, что базовый размер — это исходный размер флекс-элементов до применения flex-grow.
Если сразу у нескольких флекс-элементов значение flex-grow больше нуля, то они будут делить свободное место между собой.
Свободное место будет добавляться флекс-элементам пропорционально значениям их «коэффициента жадности».
Расчёт итогового размера с flex-grow
1 шаг. Рассчитываем свободное место во флекс-контейнере:
1 |
Свободное место = Ширина контейнера - Сумма базовых размеров элементов |
2 шаг. Считаем размер минимальной доли свободного места:
1 |
Доля свободного места = Свободное место / Сумма flex-grow всех элементов |
3 шаг. Базовый размер каждого флекс-элемента увеличиваем на размер минимальной доли свободного места умноженной на значение flex-grow
этого элемента:
1 |
Итоговый размер = Базовый размер + (Доля свободного места * flex-grow) |
Но если задать флекс-элементам нулевой базовый размер, свободное место будет занимать всю ширину флекс-контейнера, и коэффициенты жадности будут другими.
Использовать flex-basis: 0 и flex-grow для точного управления относительными размерами не стоит. Лучше использовать базовый размер в процентах.
Тонкость. На размер оставшегося свободного места влияет не только flex-basis, но и рамки, и отступы. Если flex-basis явно задано нулевое значение, то min-width на размер свободного места влиять не будет, так как ограничения размеров к флекс-элементам применяются уже после перераспределения свободного места.
Если сумма базовых размеров флекс-элементов больше, чем размер флекс-контейнера, то возникает отрицательное пространство.
Механизм перераспределения работает не только для свободного места, но и для отрицательного пространства. Флекс-элементы умеют распределять отрицательное пространство между собой и сжиматься.
За уменьшение флекс-элементов отвечает свойство flex-shrink, которое можно назвать «коффициентом сжатия».
Свойство flex-shrink принимает неотрицательные числовые значения, его значение по умолчанию — 1.
Если значение flex-shrink больше нуля, то флекс-элемент будет уменьшаться, «впитывая» часть отрицательного пространства, если оно существует.
Если значение flex-shrink равно нулю, то флекс-элемент уменьшаться не будет.
Флекс-элементы стараются быть максимально «гибкими» и не выпадать из своего контейнера, поэтому у flex-shrink значение по умолчанию равно 1. Но если задавать нулевые значения для коэффициента сжатия, то выпадения элементов добиться можно.
Свойство flex-shrink очень похоже на свойство flex-grow. Оно задаёт пропорции, в которых флекс-элементы «впитывают» отрицательное пространство.
Чем больше значение коэффициента сжатия у элемента, тем больше отрицательного пространства он «впитает» и тем сильнее сожмётся.
Когда базовые размеры флекс-элементов одинаковы, пропорции сжатия элементов считаются так же, как пропорции увеличения. Если базовые размеры флекс-элементов отличаются, то механизм усложняется.
Расчёт итогового размера с flex-shrink [12/28]
Ниже описан механизм расчёта размеров элементов, когда места в контейнере не хватает:
1 шаг. Рассчитываем отрицательное пространство (ОП) во флекс-контейнере:
1 |
ОП = Ширина контейнера - Сумма базовых размеров элементов |
2 шаг. Находим сумму произведений базовых размеров (СПБР) элементов на их коэффициенты сжатия:
1 |
СПБР = (Базовый размер<sub>1</sub> * flex-shrink<sub>1</sub>) + (Базовый размер<sub>2</sub> * flex-shrink<sub>2</sub>) + … + (Базовый размер<sub>n</sub> * flex-shrink<sub>n</sub>) |
3 шаг. Для каждого элемента считаем «нормированный коэффициент сжатия» (НКС), для чего произведение базового размера элемента на его коэффициент сжатия делим на СПБР:
1 |
НКС = (Базовый размер * flex-shrink) / СПБР |
4 шаг. Базовый размер элемента уменьшаем на часть ОП пропорциональную НКС элемента:
1 |
Итоговый размер = Базовый размер - (НКС * ОП) |
Получается, что доля отрицательного пространства, которую «впитает» элемент, зависит от двух факторов:
- соотношения коэффициента сжатия элемента с коэффициентами других элементов,
- соотношения базового размера элемента с базовыми размерами других элементов.
Именно поэтому в формулах присутствуют нормировки.
Есть несколько тонкостей, касающихся сжатия флекс-элементов:
- элементы сжимаются в пределах своих базовых размеров, внутренние отступы и рамки не сжимаются;
- «ограничительные» свойства, такие как
min-width
, применяются к элементам после этапа перераспределения свободного места или отрицательного пространства.
И эти тонкости могут приводить к неожиданным эффектам, когда элементы выпадают из флекс-контейнера.
Обобщенное свойство
С помощью сокращённого свойства flex
можно одновременно задать коэффициенты растягивания, сжатия и базовый размер флекс-элемента.
Свойство flex
состоит из трёх компонентов, которые пишутся через пробел в следующем порядке: flex-grow
, flex-shrink
и flex-basis
. В примере ниже два правила аналогичны:
1 2 3 4 5 6 7 8 9 |
.flex-item { flex: 1 2 300px; } .flex-item { flex-grow: 1; flex-shrink: 2; flex-basis: 300px; } |
Ещё у свойства flex
есть особые значения: initial
, auto
, none
. Также второй и третий компоненты необязательны. Ниже показаны различные значения свойства и их расшифровки.
1 2 3 4 5 |
flex: initial; -> flex: 0 1 auto; flex: auto; -> flex: 1 1 auto; flex: none; -> flex: 0 0 auto; flex: 1 0; -> flex: 1 0 0%; flex: 1; -> flex: 1 1 0%; |
В некоторых браузерах неполные или особенные значения свойства flex интерпретируются с ошибками. Поэтому лучше задавать все три компоненты в значении этого свойства.
flex-wrap: nowrap;.
А как будут растягиваться и сжиматься элементы в многострочном контейнере, с flex-wrap: wrap;?
В таком контейнере свойство flex-shrink будет работать как обычно, но необходимость в нём будет возникать намного реже. Ведь при нехватке места в строке флекс-элементы будут переноситься на новую строку.
Но если появятся флекс-элементы, базовый размер которых больше размера флекс-контейнера, то такие элементы будут сжиматься и занимать целую строку. Наверное, это единственный случай, когда flex-shrink делает что-то полезное в многострочном контейнере.
В отличие от flex-shrink, свойство flex-grow в многострочном флекс-контейнере срабатывает намного чаще и пользы приносит намного больше.
В каждой строке такого контейнера может быть свободное место и механизм перераспределения этого места работает построчно.
Поэтому возможность «растянуть» флекс-элементы, чтобы строки заполнялись по ширине полностью, будет возникать достаточно часто.
flex-basis: 100% и flex-wrap
Познакомимся с интересным эффектом, который возникает при использовании базовых размеров в процентах.
Если задать базовый размер флекс-элемента 100% и при этом включить перенос элементов на новую строку, то элементы расположатся столбцом, хотя главная ось контейнера будет по-прежнему направлена слева направо.
Заголовок с описанием на флексбоксах
Мы рассмотрели теоретическую часть и приступаем к практической части этого курса. Давайте разберём на реальных элементах интерфейсов, в каких случаях бывает уместно использовать флексбокс.
Довольно распространённый ход в интерфейсе — блок с заголовком и небольшим уточняющим подзаголовком на одной строке. Заголовок находится в начале строки, а подзаголовок прижат к правому краю.
Если текст заголовка или подзаголовка сильно увеличится, то вёрстка не должна ломаться — тексты просто должны расположиться друг под другом.
Сверстать элемент с таким гибким поведением с помощью float
или display: table
не получится. Ведь нужно, чтоб блоки подписей одновременно и занимали свободное пространство, и чтобы их размеры зависели от текстового содержания, и чтобы в случае переполнения сетка перестраивалась.
Здесь нам поможет только флексбокс с flex-grow
.
Ещё один случай, когда может пригодиться флексбокс — поля ввода с динамической шириной. Требования к ним такие:
- На одной строке с полем могут находиться другие элементы: кнопки, ссылки, подписи.
- Размер дополнительных элементов не определён, он зависит от их содержимого.
- При этом поле должно растягиваться на всё оставшееся в родительском контейнере место.
- И изменять ширину при изменении размеров контейнера.
Решить эту задачу можно только при помощи флексбокса. Превратим контейнер поля ввода во флекс-контейнер, все элементы внутри него превратятся во флекс-элементы, базовый размер которых будет зависеть от их содержания — flex-basis: auto;
. И останется только задать ненулевой коэффициент растягивания полям ввода.
В широком контейнере всё будет работать отлично. Проблемы могут появиться в слишком узких контейнерах: по умолчанию поля ввода не будут сжиматься после определённой ширины, что приведёт к выпаданию текста из остальных элементов.
Чтобы справиться с этими проблемами, надо задать всем элементам кроме полей ввода нулевой коэффициент сжатия, а самим полям ввода явно прописать минимальную ширину.
Пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
.cards { display: flex; width: 1000px; margin: 0 auto; flex-wrap:wrap; } .card { display: flex; flex-basis:300px; flex-grow:1; margin: 10px; padding: 20px; flex-direction: column; } .card-meta { display: flex; } .card-category { flex-grow: 1; } .card-content { display: flex; flex-direction: column; flex-grow: 1; } .card-img { width: 100%; } .card-button { margin-top:auto; } /* Декоративные обводки */ .card > * { outline: 2px solid rgba(0, 128, 0, 0.3); outline-offset: 1px; } .card-content > * { outline: 2px solid rgba(0, 0, 0, 0.5); outline-offset: -3px; } <section class="cards"> <article class="card"> <h1 class="card-heading">2D-трансформации</h1> <div class="card-meta"> <div class="card-category"> <span class="card-icon icon-tag">Категория: </span> <span>HTML, CSS</span> </div> <div class="card-duration"> <span class="card-icon icon-time">Время прохождения: </span> <span>2 часа</span> </div> </div> <div class="card-content"> <figure class="card-figure"> <img src="img/course-2.png" alt="Кекс" class="card-img"> <figcaption> <p>Будем крутить, наклонять, перемещать, уменьшать и увеличивать объекты, а также взрывать их фаерболами, телепортироваться и использовать телекинез.</p> </figcaption> </figure> <button class="card-button">Пройти курс</button> </div> </article> <article class="card"> <h1 class="card-heading">Анимация</h1> <div class="card-meta"> <div class="card-category"> <span class="card-icon icon-tag">Категория: </span> <span>HTML, CSS</span> </div> <div class="card-duration"> <span class="card-icon icon-time">Время прохождения: </span> <span>2 часа</span> </div> </div> <div class="card-content"> <figure class="card-figure"> <img src="img/course-4.png" alt="Кекс" class="card-img"> <figcaption> <p>В курсе рассмотрены основы анимации на CSS.</p> </figcaption> </figure> <button class="card-button">Пройти курс</button> </div> </article> </section> |