Flex grow что это
Полное руководство по свойствам размеров Flexbox
Дата публикации: 2019-02-18
От автора: изменение размеров Flexbox позволяет создавать гибкие макеты, которые полностью адаптируются к экрану. Если вы все настроите правильно, вам не придется полагаться на медиа-запросы для поддержки разных экранов, окон просмотра и ориентаций.
В этом руководстве я покажу вам, как использовать свойства Flexbox для изменения размеров: flex-grow, flex-shrink, flex-basis и flex.
Заполнение свободного пространства
Одним из наиболее сложных аспектов написания CSS является выяснение того, как распределить свободное пространство, которое остается на экране после заполнения страницы контентом. При некоторых размерах окна просмотра вы обнаружите, что места осталось слишком много, и вы хотите заполнить его чем-нибудь. При других размерах окна просмотра вы можете обнаружить, что места недостаточно, и макет так или иначе нарушается.
Свойства размеров Flexbox позволяют принимать решения в трех видах сценариев:
flex-grow: как должны вести себя flex-элементы при избытке свободного пространства (как они должны растягиваться).
Практический курс по верстке адаптивного сайта с нуля!
Изучите курс и узнайте, как верстать современные сайты на HTML5 и CSS3
flex-shrink: как должны вести себя гибкие элементы при нехватке свободного места (как они должны сжиматься).
На большинстве сайтов с направлением письма слева направо чаще всего для flex-direction используется row, что означает, что вы можете выделить свободное пространство слева направо. Это также является значением flex-direction по умолчанию, поэтому я буду использовать его в следующих примерах.
1. Положительное свободное пространство: flex-grow
Исследование CSS-свойства flex
В этом материале я хочу поговорить о сокращённом свойстве flex и о тех свойствах, значения которых устанавливают с его помощью. Я собираюсь рассказать о том, когда и почему можно пользоваться этими свойствами, приведу практические примеры.
Свойство flex-grow
CSS-свойство flex-grow используется для настройки так называемого «коэффициента роста» элементов (flex grow factor), что позволяет этим элементам растягиваться, занимая доступное пространство. В качестве значений этого свойства можно использовать только целые числа. Рассмотрим пример.
Вверху свойство flex-grow не применяется. Внизу применяется flex-grow: 1
Возможно, тут у вас возникнет вопрос о том, как именно между flex-элементами распределяется свободное пространство. Это — хороший вопрос. Скоро я на него отвечу.
Свойство flex-grow не используется
Для того чтобы понять то, как вычисляется ширина flex-элементов, взгляните на формулы, показанные ниже. Я нашёл эти формулы в материале Саманты Минг (за что её благодарю!).
Нахождение ширины элемента
Итак, тут используется такая формула:
Разберём эту формулу:
Разные значения flex-grow, задаваемые для разных элементов
Нахождение ширины элемента в ситуации, когда разным элементам заданы разные значения flex-grow
Можно ли использовать 0 в качестве значения flex-grow?
Последствия установки свойства flex-grow в значение 0
Использование flex-grow не приводит к тому, что элементы становятся одинаковыми
Существует распространённое заблуждение, в соответствии с которым использование flex-grow позволяет сделать так, чтобы соответствующие элементы имели бы одинаковую ширину. Это — ошибка. Смысл использования flex-grow заключается в распределении доступного пространства между элементами. Как вы могли видеть, анализируя вышеприведённые формулы, итоговая ширина flex-элементов вычисляется на основе их исходной ширины (то есть той, которую они имели до применения flex-grow ).
Свойство flex-shrink
Центральному элементу назначено свойство flex-shrink: 1
Вот стили к этому примеру:
Браузер сделает ширину элемента item-2 равной 300px при выполнении следующих условий:
Ширина элемента с текстом Is не уменьшается до тех пор, пока на экране достаточно места для его вывода
Как видите, элемент не сжимается, сохраняя ширину в 300px до тех пор, пока ему хватает места.
Свойство flex-basis
Применим к элементу item-1 из нашего примера следующие стили:
Использование свойства flex-basis: 50%
Вот соответствующие стили:
Результат использования свойства flex-basis: 100%;
Сокращённое свойство flex
В данном контексте мне хотелось бы обратить ваше внимание на одну важную деталь. Речь идёт о flex-элементах с абсолютными и относительными размерами. И, кстати, это не имеет отношения к CSS-позиционированию. Это относится к модели flexbox.
Flex-элементы с относительными размерами
Здесь размер flex-элементов основан на их содержимом. В результате элементы, в которых больше содержимого, будут больше.
Элемент, в котором больше содержимого, будет больше
Flex-элементы с абсолютными размерами
Элементы имеют одинаковый размер
Особенности свойства flex, которые мне нравятся
Само название свойства flex намекает на то, что оно умеет гибко работать с передаваемыми ему значениями. Это наделяет его некоторыми особенностями, которые кажутся мне привлекательными. Рассмотрим несколько примеров.
▍Одно значение без единиц измерения
▍Два значения без единиц измерения
Взглянем на следующий стиль:
▍Одно значение, представляющее собой некий размер
Поговорим о том, как будет «расшифрован» следующий стиль:
▍Использование значения 0 без указания единиц измерения
Ноль без указания единиц измерения, перед которым нет двух значений коэффициентов гибкости, должен интерпретироваться как значение коэффициента гибкости. Для того чтобы избежать неправильной интерпретации или ошибочного объявления свойства, авторы должны, задавая нулевое значение flex-basis, использовать единицы измерения, или ставить перед этим значением два значения, относящиеся к коэффициентам гибкости.
То есть, чтобы избежать неоднозначностей, вышеприведённый код стоит переписать так:
Пользуйтесь сокращённым свойством flex
Авторам рекомендуется управлять гибкими элементами, используя сокращённое свойство flex, а не применяя напрямую полные имена свойств, так как при применении сокращённого свойства производится корректный сброс неуказанных значений к состоянию, соответствующему распространённым способам их использования.
Сценарии использования и практические примеры
▍Аватары пользователей
Аватар, при настройке которого использовано свойство flex
Модель flexbox часто используется для оформления компонентов страниц, имеющих отношение к пользователям. Например, это касается аватара пользователя и соответствующей подписи, которые должны находиться на одной строке.
▍Заголовок элемента
Предположим, нам надо оформить заголовок некоего элемента. Этот заголовок должен занять всё доступное ему пространство. Решить эту задачу можно с помощью свойства flex: 1 :
▍Поле ввода для подготовки сообщения
Подобные поля часто встречаются в приложениях для обмена сообщениями, вроде тех, что есть в Facebook и Twitter. Такое поле должно занимать всё доступное ему пространство. При этом кнопка для отправки сообщения должна иметь фиксированную ширину. Вот как это выглядит в CSS:
Надо отметить, что некоторым способам использования свойства flex не уделяется достаточно внимания в публикациях, посвящённых этому свойству. Давайте это исправим.
▍Выравнивание нижних элементов, находящихся на разных карточках
Цель — выровнять обе даты по красной линии
Предположим, что перед нами — макет, сформированный средствами CSS Grid, в котором имеются две колонки. Проблема тут в том, что даты, выводимые в конце текстового содержимого карточек, не выровнены. А нам нужно, чтобы они находились бы на одной линии, показанной на предыдущем рисунке.
Для решения этой задачи можно воспользоваться моделью flexbox.
Использование разных значений для коэффициентов гибкости
▍Панели управления
Набор элементов управления
На подготовку этого примера меня вдохновил дизайн Facebook (значки я тоже взял оттуда). На панели управления (элемент actions в следующем коде) имеется четыре элемента. Последний (элемент actions__item.user ) имеет ширину, которая меньше, чем ширина других элементов. Сформировать подобную панель управления можно так:
▍Анимация, в ходе которой элемент растягивается
Элемент растягивается при наведении на него указателя мыши
Flex-элементы можно анимировать при наведении на них указателя мыши. Этот приём может оказаться крайне полезным. Вот соответствующий CSS-код:
Здесь можно найти видео, демонстрирующее всё это в действии.
▍Увеличение размера активной карточки
Увеличение размера активной карточки
▍Что делать, если содержимое контейнера больше самого контейнера?
Элементы не помещаются в контейнер
Некоторое время тому назад мне пришло письмо от одного из моих читателей, который рассказал мне о возникшей у него проблеме и попросил помочь с её решением. Суть этой проблемы представлена на предыдущем рисунке. Здесь есть пара изображений, которые должны находиться в пределах элемента-контейнера, но размер этих изображений больше размеров контейнера.
Попробуем такой стиль:
Но даже при использовании свойства flex: 1 изображения в контейнер не помещаются. Обратимся к спецификации CSS:
Flex-элементы, по умолчанию, не уменьшаются в размерах до величин, меньших, чем размеры их содержимого (длина самого длинного слова или элемента с фиксированным размером). Для того чтобы это изменить, нужно воспользоваться свойствами min-width или min-height.
В нашем случае проблема заключается в том, что изображения слишком велики и модель flexbox не уменьшает их до таких размеров, чтобы они поместились бы в контейнер. Исправить это можно так:
Подробности смотрите в этой моей статье.
Итоги
Здесь я рассказал вам о свойстве flex и о том, как им пользоваться. Надеюсь, вы узнали из этого материала что-то новое и полезное.
Пользуетесь ли вы CSS-свойством flex в своих проектах?
Как работает Flex-grow в CSS. Подробное руководство
Jan 18, 2018 · 8 min read
Но я нашел статью `flex-grow` is weird. Or is it?, которая максимально ясно показывает то, как работает flex-grow и то, как он рассчитывается. Ниже будет её перевод на русский язык.
👉 Мой Тв и ттер — там много из мира фронтенда, да и вообще поговорим🖖. Подписывайтесь, будет интересно: ) ✈️
Как flex-grow НЕ работает
Я думал, что все flex элементы с flex-grow с параметром 1 будут иметь одинаковую ширину. А если один из элементов будет иметь flex-grow с параметром 2, то этот элемент будет в два раза больше чем другие в этой группе.
Как вы видите, в этой демке все работает просто идеально, но это так не работает в реальной жизни, даже если бы мы использовали тот же самый CSS код. Оказывается, что проблема была не в самом с CSS, а в контенте, вернее в его недостатке. Демка, которую я сделал — она работает, да, но только потому что там использовались два пустых элемента, созданные для тестирования и в итоге оказавшиеся слишком простыми для того, чтобы показать все важные моменты этого свойства.
Как Flex-grow работает на самом деле
Только что я объяснил как flex-grow не работает, но я показал вам демо, которое на самом деле не делает то, что по моим утверждениям это не делает. Далее в статье я вам объясню причину этого.
Чтобы прояснить ситуацию, позвольте показать вам еще один Pen. В нём такие же установки, как и в первом, но на этот раз секция и боковые элементы не пустые. Теперь соотношение больше не 2:1 и элемент с flex-grow выставленным на один больше, чем элемент с flex-grow на 2.
#Объяснение
Если мы применим display:flex для родительского элемента и ничего больше не поменяем, то дочерние элементы встанут горизонтально, не смотря ни на что. Если будет недостаточно места, то они сократятся в размере. С другой стороны, если будет слишком много места, то они не будут расти, потому что Flexbox хочет, чтобы мы определили насколько им нужно вырасти. Таким образом, прежде чем указывать браузеру каким по ширине должен быть элемент, flex-grow определяет как оставшееся место распределяется среди flex элементов и насколько велика доля каждого из них.
Или другими словами:
Flex контейнер распределяет свободное место своим элементам, пропорционально их flex-grow фактору, чтобы заполнить контейнеры или урезать их, пропорционально их flex-shrink фактору, для того того, чтобы пресечь переполнение контейнера.
#Демонстрация
Эту концепцию гораздо проще понять, если мы её визуализируем.
Во-первых мы выставим display свойство для нашего родительского элемента на flex и сделав это наши дочерние элементы станут flex-элементами и будут горизонтально расставлены друг за другом.
Наконец-то у нас есть количество распределяющихся частей. Каждый элемент получает соответствующее количество частей, основываясь на его flex-grow значении.
#Считаем
Теории и визуальные представления это хорошо, но давайте по пачкаем руки и сделаем математические вычисления для примера выше.
Для наших расчетов понадобится четыре числа: ширина родителя, изначальная ширина секции и бокового элемента и общее количество flex-grow значений, которые мы будем использовать. Итак, у нас получается:
Ширина секции: 99px
Ширина бокового элемента: 623px
Общее количество flex-grow значений: 3
1. Во первых нам надо рассчитать оставшееся место. Это довольно легко, мы возьмем ширину родителя и вычтем общую ширину изначальных дочерних элементов.
2. Далее нам нужно определить размер каждого значения flex-grow
Теперь, когда у нас есть оставшееся место, нам нужно определить на сколько частей мы хотим его разделить. Очень важно понимать, что мы не делим оставшееся место на количество элементов, а делим на общее количество flex-grow значений. В нашем случае это будет 3 ( flex-grow:2 + flex-grow:1 )
3. Наконец-то разрезанное оставшееся место будет распределено между всеми элементами
Основываясь на их flex-grow значениях секция получит 2 куска (2*59.33), а боковая сторона получит 1 кусок (1*59.33). Эти числа добавляются к изначальной ширине каждого элемента.
99 + (2 * 59,33) = 217,66 (
218px) | Изначальная ширина секции + (значение flex-grow для секции * размер одного flex-grow )
623 + (1* 59.33) = 682.33 (
682px) | Изначальная ширина боковой стороны + (значение flex-grow боковой стороны * размер одного flex-grow )
Теперь вообще легко, правда?
Отлично, но почему сработало первое демо?
У нас есть формула, теперь давайте разберемся почему мы получили нужные результаты в первой демке, даже не понимая как мы это делаем.
Ширина бокового элемента: 0px
Общее количество flex-grow значений: 3
1. Рассчитываем оставшееся место.
2. Определяем размер каждого значения flex-grow
3. Распределяем нарезанное свободное место
Если ширина каждого элемента равна нулю, то оставшееся место равняется настоящей ширине родительского элемента и поэтому все выглядит так, будто flex-grow разделяет ширину элемента на равные пропорциональные части.
flex-grow и flex-basis
Давайте быстренько повторим: flex-grow берет оставшееся место и делит его на общее количество flex-grow значений. Полученный показатель умножается на соответствующее каждой части значение flex-grow и полученный результат добавляется каждому дочернему элементу с его изначальной шириной.
Я адаптировал наш предыдущий пример, добавив flex-basis для каждого элемента. Вот он. Давайте посмотрим, как это происходит.
1. Рассчитываем оставшееся место
2. Определяем ширину элемента flex-grow
3. Распределяем оставшееся место
Небольшой оффтоп для завершенности дела, вам не нужно использовать исключительно пиксельные значения и надеяться на лучшее, проценты работают так же хорошо.
Работа с box-моделью
Несколько полезных примеров
И так, достаточно математики. Давайте посмотрим несколько примеров того, как вы можете эффективно применить flex-grow в своих проектах.
#Скажи нет width: [x]%
Так как оставшееся место распределяется автоматически, нам не нужно думать о значениях ширины, если мы хотим, чтобы наши дочерние элементы заполняли весь родительский элемент.
#Святой грааль трех колоночного “жидкого” макета с шириной в пикселях
Смеси фиксированных и флюидных широт в column шаблонах возможны с флоатами, но это и не понятно и просто не гибкое решение. Конечно с помощью Flexbox и немного flex-grow и flex-basis магии это становится вполне возможным.
#Заполняем оставшееся место любым элементом
Если вы, к примеру, имеете поле ввода прямо за лейблом и хотите, чтобы это поле занимало все оставшееся место, вам больше не нужны убоговатые хаки в верстке. Смотрите.
Прислушиваемся к спецификациям
Следуя спецификации, нам стоит использовать flex сокращения, а не flex-grow напрямую.
Но будьте аккуратны! Если вы просто будете использовать flex:1; некоторые из примеров выше не будут работать, потому что значения выставленные для всеобщего удобства не равны дефолтным значениям и это мешает нашим целям.
Если вы хотите использовать flex в нашем случае, то вам нужно определять его параметры вот так:
Заключение
Flex-grow сложный и запутанный? Всё совсем не так плохо, как кажется. Нам нужно просто понять как он работает и что он делает. Если у элемента flex-grow выставлен на 3, это не означает того, что он будет в три раза больше чем элемент у которого flex-grow стоит с параметром 1. Это будет означать то, что он получит в три раза больше пикселей к изначальной ширине, чем другой элемент.
Я выучил свой урок, тестируя flex-grow с двумя пустыми элементами, которые дали мне совершенно другое понимание того, что это свойство делает и это само собой привело меня к неверным заключениям. Вам нужно проверять новые фишки в среде, которая максимально приближена к реальности, тогда вы получите максимально реалистичное понимание того, как это работает и себя ведет.
2.23. CSS flexbox
CSS flexbox (Flexible Box Layout Module) — модуль макета гибкого контейнера — представляет собой способ компоновки элементов, в основе лежит идея оси.
Flexbox состоит из гибкого контейнера (flex container) и гибких элементов (flex items). Гибкие элементы могут выстраиваться в строку или столбик, а оставшееся свободное пространство распределяется между ними различными способами.
Модуль flexbox позволяет решать следующие задачи:
Flexbox решает специфические задачи — создание одномерных макетов, например, навигационной панели, так как flex-элементы можно размещать только по одной из осей.
Список текущих проблем модуля и кросс-браузерных решений для них вы можете прочитать в статье Philip Walton Flexbugs.
Что такое flexbox
Поддержка браузерами
1. Основные понятия
Для описания модуля Flexbox используется определенный набор терминов. Значение flex-flow и режим записи определяют соответствие этих терминов физическим направлениям: верх / право / низ / лево, осям: вертикальная / горизонтальная и размерам: ширина / высота.
Главная ось (main axis) — ось, вдоль которой выкладываются flex-элементы. Она простирается в основном измерении.
Main start и main end — линии, которые определяют начальную и конечную стороны flex-контейнера, относительно которых выкладываются flex-элементы (начиная с main start по направлению к main end).
Основной размер (main size) — ширина или высота flex-контейнера или flex-элементов, в зависимости от того, что из них находится в основном измерении, определяют основной размер flex-контейнера или flex-элемента.
Поперечная ось (cross axis) — ось, перпендикулярная главной оси. Она простирается в поперечном измерении.
Cross start и cross end — линии, которые определяют начальную и конечную стороны поперечной оси, относительно которых выкладываются flex-элементы.
Поперечный размер (cross size) — ширина или высота flex-контейнера или flex-элементов, в зависимости от того, что находится в поперечном измерении, являются их поперечным размером.
Рис. 2. Режим строки и колонки
2. Flex-контейнер
Модель flexbox-разметки связана с определенным значением CSS-свойства display родительского html-элемента, содержащего внутри себя дочерние блоки. Для управления элементами с помощью этой модели нужно установить свойство display следующим образом:
После установки данных значений свойства каждый дочерний элемент автоматически становится flex-элементом, выстраиваясь в один ряд (вдоль главной оси). При этом блочные и строчные дочерние элементы ведут себя одинаково, т.е. ширина блоков равна ширине их содержимого с учетом внутренних полей и рамок элемента.
Рис. 3. Выравнивание элементов в модели flexbox
Если родительский блок содержит текст или изображения без оберток, они становятся анонимными flex-элементами. Текст выравнивается по верхнему краю блока-контейнера, а высота изображения становится равной высоте блока, т.е. оно деформируется.
3. Flex-элементы
Flex-элементы — блоки, представляющие содержимое flex-контейнера в потоке. Flex-контейнер устанавливает новый контекст форматирования для своего содержимого, который обуславливает следующие особенности:
4. Порядок отображения flex-элементов и ориентация
Содержимое flex-контейнера можно разложить в любом направлении и в любом порядке (переупорядочение flex-элементов внутри контейнера влияет только на визуальный рендеринг).
4.1. Направление главной оси: flex-direction
Свойство относится к flex-контейнеру. Управляет направлением главной оси, вдоль которой укладываются flex-элементы, в соответствии с текущим режимом записи. Не наследуется.
flex-direction | |
---|---|
Значения: | |
row | Значение по умолчанию, слева направо (в rtl справа налево). Flex-элементы выкладываются в строку. Начало (main-start) и конец (main-end) направления главной оси соответствуют началу (inline-start) и концу (inline-end) оси строки (inline-axis). |
row-reverse | Направление справа налево (в rtl слева направо). Flex-элементы выкладываются в строку относительно правого края контейнера (в rtl — левого). |
column | Направление сверху вниз. Flex-элементы выкладываются в колонку. |
column-reverse | Колонка с элементами в обратном порядке, снизу вверх. |
initial | Устанавливает значение свойства в значение по умолчанию. |
inherit | Наследует значение свойства от родительского элемента. |
Рис. 4. Свойство flex-direction для left-to-right языков
4.2. Управление многострочностью flex-контейнера: flex-wrap
Свойство определяет, будет ли flex-контейнер однострочным или многострочным, а также задает направление поперечной оси, определяющее направление укладки новых линий flex-контейнера.
По умолчанию flex-элементы укладываются в одну строку, вдоль главной оси. При переполнении они будут выходить за пределы ограничивающей рамки flex-контейнера. Свойство не наследуется.
flex-wrap | |
---|---|
Значения: | |
nowrap | Значение по умолчанию. Flex-элементы не переносятся, а располагаются в одну линию слева направо (в rtl справа налево). |
wrap | Flex-элементы переносятся, располагаясь в несколько горизонтальных рядов (если не помещаются в один ряд) в направлении слева направо (в rtl справа налево). |
wrap-reverse | Flex-элементы переносятся на новые линии, располагаясь в обратном порядке слева-направо, при этом перенос происходит снизу вверх. |
initial | Устанавливает значение свойства в значение по умолчанию. |
inherit | Наследует значение свойства от родительского элемента. |
Рис. 5. Управление многострочностью с помощью свойства flex-wrap для LTR-языков
4.3. Краткая запись направления и многострочности: flex-flow
4.4. Порядок отображения flex-элементов: order
Свойство определяет порядок, в котором flex-элементы отображаются и располагаются внутри flex-контейнера. Применяется к flex-элементам. Свойство не наследуется.
Рис. 6. Порядок отображения flex-элементов
5. Гибкость flex-элементов
Flex-элемент будет полностью «негибок», если его значения flex-grow и flex-shrink равны нулю, и «гибкий» в противном случае.
5.1. Задание гибких размеров одним свойством: flex
W3C рекомендует использовать сокращённую запись, так как она правильно сбрасывает любые неуказанные компоненты, чтобы подстроиться под типичное использование.
5.2. Коэффициент роста: flex-grow
Свойство определяет коэффициент роста одного flex-элемента относительно других flex-элементов в flex-контейнере при распределении положительного свободного пространства. Если сумма значений flex-grow flex-элементов в строке меньше 1, они занимают менее 100% свободного пространства. Свойство не наследуется.
5.3. Коэффициент сжатия: flex-shrink
5.4. Базовый размер: flex-basis
flex-basis | |
---|---|
Значения: | |
auto | Значение по умолчанию. Элемент получает базовый размер, соответствующий размеру его содержимого (если он не задан явно). |
content | Определяет базовый размер в зависимости от содержимого flex-элемента. |
длина | Базовый размер определяется так же, как для ширины и высоты. Задается в единицах длины. |
initial | Устанавливает значение свойства в значение по умолчанию. |
inherit | Наследует значение свойства от родительского элемента. |
6. Выравнивание
6.1. Выравнивание по главной оси: justify-content
6.2. Выравнивание по поперечной оси: align-items и align-self
6.2.1. Align-items
Свойство выравнивает flex-элементы, в том числе и анонимные flex-элементы по поперечной оси. Не наследуется.