Безусловно, это самый распространенный вопрос о flexbox, который мне задают. Помню как сам прибегал к поиску ответа на этот вопрос, когда еще только изучал flexbox. Проверяя свою историю поиска в Google, я обнаружил, что за последний год делал запросы по фразе "flex-basis vs width vs min-width" 4 раза. Talk about slacking! Сегодня я дам ответ на этот вопрос, и надеюсь, сэкономлю кому-то время на поиск этого ответа.
Это формула, которую необходимо запомнить:
content –> width –> flex-basis (ограничено помощью max|min-width)
Для опеределения размера flex элемента самым важным является итоговое значение flex-basis, которое связано со свойствами max-width и min-width.
Спецификация flexbox называет это "гипотетическим основным размером", но его проще представить как итоговое значение flex-basis.
Если значение для свойства flex-basis не указано, то элемент будет использовать значение свойства width. Если значение для свойства width не указано, то flex-basis будет высчитывать ширину исходя из контента элемента.
Давайте проиллюстрируем данную формулу. Создадим flex контейнер с шириной в 1000px:
container {
display: flex;
width: 1000px;
}
Создадим элементы, размером 200x200px:
item {
width: 200px;
height: 200px;
}
И добавим данные элементы в ранее созданный flex контйенер:
Во flex контейнере много места, и его элементы хорошо в него вписались.
В этом примере у flex элементов не выставлено значение свойства flex-basis, а значением по умолчанию является - auto, которое берет значение свойства width.
В данном случае, установка свойства width равнозначна установке свойства flex-basis.
Давайте посмотрим, что произойдет, если мы добавим нашим flex элементам опеределенное значение для flex-basis, если у них уже есть свойство width:
item {
width: 30px;
flex-basis: 250px;
}
Как видите, когда свойство flex-basis имеет конкретное значение, то свойство width просто игнорируется, поэтому мы можем его не указывать.
item {
flex-basis: 250px;
}
Окончательное значение свойства flex-basis для каждого элемента равняется 250px. На данный момент, у нас хватает места в контейнере, поэтому элементы в него прекрасно вписываются.
Вспомните формулу, по которой высчитывается значение flex-basis:
content –> width –> flex-basis (ограничено помощью max|min-width)
Важно только конечное свойство flex-basis. Лучше всего указывать именно его, вместо свойства width.
Окончательное значение свойства flex-basis ограничивается двумя свойствами: max-width и min-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;
}
Несмотря на то, что у наших элементов установлено свойство flex-basis со значением 100px, их ширина не может быть меньше 250px, так как это значение указано у свойства min-width. Поэтому, окончательное значение flex-basis в этом случае равняется 250px, и элементы прекрасно вписываются в контейнер:
Сейчас мы понимаем, что свойство width является так называемым "фолбэком" (значение из этого свойства берется в том случае, если свойство flex-basis не уставновлено, или имеет значение по умолчанию - auto), а свойства max-width и min-width ограничивают окончательное значение для свойства flex-basis. Так что же означает свойство flex-basis?
Вы, наверное, обратили внимание на то, что во всех наших иллюстрациях мы показывали размеры flex элементов прежде, чем вставить их во flex контейнер. Мы это делали для того, чтобы стало понятно - flex-basis это свойство, которое устанавливает размер flex элемента перед его размещением во flex контейнере. Это идеальный или гипотетический размер элементов. Но flex-basis не является гарантированным размером! Как только браузер помещает элементы во flex контейнер, все меняется. В некоторых наших примерах, вы видели, что flex элементы прекрасно вписывались во flex контейнер. Это происходило потому, что сумма окончательных значений свойств flex-basis всех flex элементвов была точной шириной нашего flex контейнера (1000px). Это здорово, если это происходит, но чаще всего во flex контейнере не хватает места для всех элементов, после того как значения flex-basis всех его элементов складываются.
Скажем, мы хотим вставить еще больше элементов со значением flex-basis: 200px
в наш flex контейнер:
Перед тем как перейти во flex контейнер, каждый из этих элементов получит ширину равную 200px, а в сумме это будет 1600px. Но у нашего контейнера доступно только 1000px. Когда места не хватает для всех элементов с определенным значением flex-basis, то элементы будут сжиматься, чтобы уместиться во flex контейнере
Все элементы изначально имели ширину в 200px, но так как во flex контейнере не хватало места, то они одинакого уменьшились до 125px, чтобы полностью уместиться в нем. За коэффициент сжатия отвечает свойство flex-shrink. Вы можете переопределять это свойство, делая некоторые элементы больше (с большими коэффцициентами) или меньше (с меньшими коэффициентами). Можно также запретить элементу сжиматься, установив свойство flex-shrink в значение 0.
Часто у нас остается пустое пространство, после того как у элементов будет установлено окончательное значение свойства flex-basis.
item {
flex-basis: 100px;
}
Мы можем поручить нашим flex элементам растягиваться, чтобы заполнить все доступное пространство flex контейнера. За это отвечает свойство flex-grow. По умолчанию оно имеет значение 0, т.е. запрещает расширяться нашим flex элементам. Давайте установим каждому элементу это свойство в значение 1, чтобы они одинакого расширились, заполнив свободное пространство своего flex контейнера:
item {
flex-basis: 100px;
flex-grow: 1;
}
Управление расширением и сжатием - огрномная часть спецификации flexbox, именно это делает flexbox великолепным инструментом в отзывчивом UI дизайне.
Надеюсь, теперь вы видите разницу между свойствами width и flex-basis, а также то, как свойства max-width и min-width влияют на окончательное значение flex-basis. Все вышеперечисленное также относится и к свойству height, когда у flex контейнера изменена основная ось направления flex элементов с помощью свойства flex-direction и его значений column и column-reverse.