Разница между width и flex-basis
Это очень важный момент в вёрстке на flexbox и он никак не отменяет того, что эту разницу нужно знать, понимать и грамотно применять.
Перевод статьи The Difference Between Width and Flex Basis
👉Мой Твиттер — там много из мира фронтенда, да и вообще поговорим🖖. Подписывайтесь, будет интересно: ) ✈️
Пока что это самый популярный вопрос который меня спрашивали. На самом деле я и сам гуглил про эту штуку в начале понимания флексов. Там были такой запрос “flex-basis vs width vs min-width” и так 4 раза! Не хило. Но давайте разберемся с этим вопросом и возможно избавим вас от подобным запросов в будущем.
Формула flex-элементов
Вот она:
content → width → flex-basis (ограниченный max|min-width)
Для определения размера flex-элемента, flex-basis
ограничивается min-width
и max-width
. В общем, это всё что нужно.
Обратите внимание, что спека flexbox говорит о том, что это “потенциальный основной размер”, но куда проще рассматривать это как конечный flex-basis
.
Если flex-basis
не указан, то он опирается на свойство width
этого же элемента.
А если уже и width
не указан, то flex-basis
опирается ширину, посчитанную по контенту.
Давайте покажем как работает эта формула, вставив несколько flex-элементов во flex-контейнер шириной 1000px:
container{
display: flex;
width: 1000px;
}
Выставляем width
Давайте положим несколько 200px x 200px элементов, которые задают ширину нашему flex-контейнеру.
item{
width: 200px;
height: 200px;
}
У нашего flex-контейнера есть ещё немного места. Так что всё в него успешно помещается:
В этом примере, flex-basis
у элементов не был указан, так что по-дефолту он стоит flex-basis: auto
, что берет за основу ширину (200px).
Пока что, указание width
равно выставлению flex-basis
.
Выставляем flex-basis
Давайте посмотрим что случится, когда мы выставим flex-basis
этим элементам, у которых уже указан width
.
item{
width: 30px;
flex-basis: 250px;
}
Как вы видите, когда указан flex-basis
, width
наших боксов игнорируется, так что нам даже и не нужно его указывать:
item{
flex-basis: 250px;
}
Наш окончательный flex-basis
для каждого элемента равен 250px. И пока у нас достаточно места, чтобы их уместить, они отлично поместятся в flex-контейнере.
Помните формулу flex-элементов:
content → width → flex-basis (ограничивается max|min-width)
Единственное, что реально важно, это конечный flex-basis
. Лучшей практикой является использование просто flex-basis
, вместо width
и height
. Особенно учитывая Safari, который до сих пор имеет баг, в котором не применяется flex-shrink
на элементах, который используют height
вместо flex-basis
.
Flex-basis ограниченный max-width
Конечное значение flex-basis
ограничено min-width
и max-width
элемента. Смотрите, что происходит когда мы указываем max-width
ограничение нашим flex-элементам:
item{
flex-basis: 250px;
max-width: 100px;
}
Хоть и flex-basis
был выставлен 250px, он превышает указанный лимит max-width лимит в 100px. Так что, нашим окончательным flex-basis, в этом случае будет 100px и наши элементы будут располагаться в контейнере таким образом:
Теперь давайте выставим min-width
и посмотрим как оно ограничит наш flex-basis
в формировании размера:
item{
flex-basis: 100px;
min-width: 250px;
}
Хоть мы и указали 100px нашему flex-basis
, он не может быть меньше, чем ограничение в 250px, указанное в min-width
. Так что, наши элементы идеально поместятся в контейнер:
Так что же такое flex-basis?
Теперь мы понимаем, что width это fallback, когда flex-basis
отсутствует, а min-width
и max-width
это просто ограничения для формирования окончательного размера flex-basis
. Но что же такое flex-basis
?
Возможно, вы уже обратили внимание на то, что на всех изображениях, размер элементов указан перед тем как они попадут в контейнер. Мы так сделали, потому что это именно то, чем является flex-basis: размер flex-элементов перед тем, как они разместятся в контейнере. Это идеальный или предположительный размер элементов. Но flex-basis
это не гарантированный размер! Как только браузер поместит элементы в контейнер, всё поменяется. На некоторых примерах выше, вы видели то, что flex-элементы идеально подходят под контейнер, потому что общая сумма всех flex-basis
равна указанной ширине нашего контейнера (1000px). Хорошо, когда так, но зачастую у flex-контейнера нет достаточного места или у него появляется дополнительное место, после того, как добавятся все значения flex-basis
.
Когда недостаточно места
Предположим, что нам надо вставить ещё больше элементов с flex-basis: 200px
в наш контейнер:
Перед помещением в контейнер, каждый из них возьмет 200px или 1600px в сумме. Но наш контейнер всего-то 1000px. Когда нет достаточно места для всех элементов с полным flex-basis
(каждый по 200px), то они по-дефолту будут урезаны до такого состояния, пока не будут помещаться в контейнер.
Все элементы изначально в ширину 200px, но так как мы сократили пространство, они сократятся до показателя в 125px, то есть так, чтобы они ровно поместились в контейнер. Элементы нарезаются по-дефолтному значению flex-shrink
. Вы можете указать своё значение того, как сократятся элементы или вообще убрать эту возможность (0
).
Когда есть лишнее место
Частенько у нас есть лишнее место, после того, как все элементы с flex-basis
будут добавлены.
item{
flex-basis: 100px;
}
Мы можем указать то, как могут расшириться наши элементы, чтобы занять доступное место в flex-контейнере. Это именно то, что делает свойство flex-grow
. По-дефолту оно равно 0
, означая то, что элемент не увеличится. Давайте выставим каждому элементу flex-grow: 1
(все они одинаково увеличатся), чтобы заполнить оставшееся место:
item{
flex-basis: 100px;
flex-grow: 1;
}
Вообще, увеличение и сокращение элементов это значимая часть всей крутости flexbox и это то, что делает его великолепным для адаптивного UI дизайна. Игрушка Flexbox Zombies говорит о этих свойствах довольно детально. Ну а еще детальнее можно прочитать в этих статьях:
Как работает Flex-grow в CSS. Подробное руководство
Как работает flex-shrink в CSS. Подробное руководство
Width vs flex-basis
Надеемся, что теперь вы видите разницу между width
и flex-basis
и то как min-width
с max-width
влияют на конечный flex-basis
. Всё вышеупомянутое может работать как высотаheight
, когда flex-direction
выставлен на column
или на column-reverse
.
Если хотите узнать ещё больше о flexbox, то обязательно прочитайте Вёрстка на Flexbox в CSS. Полный справочник