Разница между width и flex-basis

Stas Bagretsov
6 min readApr 10, 2019

Это очень важный момент в вёрстке на 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. Полный справочник

--

--

Stas Bagretsov

Надеюсь верую вовеки не придет ко мне позорное благоразумие. webdev/sports/books