Каковы различия между flex-основе и шириной?

224

Были вопросы и статьи по этому поводу, но, насколько я могу судить, нет ничего убедительного. Лучшее резюме, которое я смог найти, это

flex-based позволяет указать начальный / начальный размер элемента, прежде чем что-либо еще будет вычислено. Это может быть процент или абсолютное значение.

... что само по себе мало говорит о поведении элементов с набором flex- base. С моим текущим знанием flexbox я не понимаю, почему это также не может описать ширину .

Я хотел бы знать, чем именно flex-base отличается от ширины на практике:

  • Если я заменю ширину на flex-base (и наоборот), что изменится визуально?
  • Что произойдет, если я установлю другое значение? Что произойдет, если они имеют одинаковое значение?
  • Существуют ли особые случаи, когда использование width или flex-based будет существенно отличаться от использования другого?
  • Как ширина и основание Flex отличаются при использовании в сочетании с другими стилями flexbox, такими как flex-wrap , flex-grow и flex-shrink ?
  • Есть ли другие существенные различия?

Изменить / уточнить : Этот вопрос был задан в другом формате в разделе Что такое наборы свойств flex-based? но я чувствовал, что было бы неплохо более прямое сравнение или обобщение различий flex-base и width (или height ).

jpeltoniemi
источник
Лучшая статья, рассказывающая о гибкой основе, гибком росте и
сжатии

Ответы:

339

Рассматривать flex-direction

Первое, что приходит на ум при чтении вашего вопроса - flex-basisэто не всегда применимо к width.

Когда flex-directionесть row, flex-basisконтролирует ширину.

Но когда flex-directionесть column, flex-basisконтролирует высоту.


Ключевые отличия

Вот некоторые важные различия между flex-basisи width/ height:

  • flex-basisприменяется только к гибким предметам. Flex-контейнеры (которые также не являются flex-элементами) будут игнорировать, flex-basisно могут использовать widthи height.

  • flex-basisработает только на главной оси. Например, если вы находитесь flex-direction: column, это widthсвойство будет необходимо для определения размера элементов Flex по горизонтали.

  • flex-basisне влияет на абсолютно позиционированные гибкие элементы. widthи heightсвойства будут необходимы. Абсолютно позиционированные флекс-элементы не участвуют в флекс-макете .

  • Используя flexсвойство, три свойства - flex-grow, flex-shrinkи flex-basis- может быть аккуратно объединены в одной декларации. Используя widthодно и то же правило, потребуется несколько строк кода.


Поведение браузера

С точки зрения того, как они отображаются, не должно быть никакой разницы между flex-basisи width, если не flex-basisявляется autoили content.

Из спецификации:

7.2.3. flex-basisнедвижимость

Для всех значений, кроме autoи content, flex-basisразрешается так же, как и widthв горизонтальных режимах записи.

Но влияние autoили contentможет быть минимальным или вообще ничего. Больше из спецификации:

auto

При указании в элементе flex autoключевое слово извлекает значение свойства основного размера в качестве используемого flex-basis. Если это значение само по себе auto, то используемое значение content.

content

Указывает на автоматическое изменение размера в зависимости от содержимого элемента flex.

Примечание. Это значение отсутствовало в первоначальном выпуске Flexible Box Layout, поэтому некоторые старые реализации не будут его поддерживать. Эквивалентный эффект может быть достигнут при использовании autoвместе с основным размером ( widthили height) из auto.

Так что, согласно спецификации, flex-basisи widthрешать одинаково, если не flex-basisявляется autoили content. В таких случаях flex-basisможет использоваться ширина содержимого (которую, вероятно, widthбудет использовать и свойство).


flex-shrinkфактор

Важно помнить начальные настройки гибкого контейнера. Некоторые из этих настроек включают в себя:

  • flex-direction: row - гибкие элементы будут выровнены по горизонтали
  • justify-content: flex-start - гибкие элементы будут складываться в начале линии на главной оси
  • align-items: stretch - гибкие элементы будут расширяться, чтобы охватить поперечный размер контейнера
  • flex-wrap: nowrap - гибкие предметы вынуждены оставаться в одной строке
  • flex-shrink: 1 - гибкий элемент может сжиматься

Обратите внимание на последний параметр.

Потому что гибкие предметы могут сокращаться по умолчанию (который предотвращает их от переполнения контейнера), указанный flex-basis/ width/ heightможет быть переопределен.

Например, flex-basis: 100pxили width: 100px, в сочетании с flex-shrink: 1, не обязательно будет 100px.

Чтобы отобразить указанную ширину и сохранить ее фиксированной, вам нужно отключить сжатие:

div {
   width: 100px;
   flex-shrink: 0;
}  

ИЛИ

div {
  flex-basis: 100px;
  flex-shrink: 0;
}

ИЛИ, как указано в спецификации:

flex: 0 0 100px;    /* don't grow, don't shrink, stay fixed at 100px */

7.2. Компоненты гибкости

Авторам рекомендуется контролировать гибкость, используя flexсокращение, а не напрямую с его свойствами, так как сокращение корректно сбрасывает любые неуказанные компоненты для обеспечения общего использования .


Ошибки браузера

В некоторых браузерах возникают проблемы с определением размера элементов Flex во вложенных контейнерах Flex.

flex-basisигнорируется во вложенном гибком контейнере. widthработает.

При использовании flex-basisконтейнер игнорирует размеры своих дочерних элементов, и дочерние элементы переполняют контейнер. Но со widthсвойством контейнер учитывает размеры своих дочерних элементов и соответственно расширяется.

Ссылки:

Примеры:


использование гибких элементов flex-basisи white-space: nowrapпереполнение inline-flexконтейнера. widthработает.

Похоже, что гибкий контейнер inline-flexне распознается flex-basisна дочернем white-space: nowrapэлементе при рендеринге брата (хотя это может быть просто элемент с неопределенной шириной). Контейнер не расширяется для размещения предметов.

Но когда widthсвойство используется вместо flex-basis, контейнер учитывает размеры своих дочерних элементов и соответственно расширяется. Это не проблема в IE11 и Edge.

Ссылки:

Пример:


flex-basisflex-grow) не работает над элементом таблицы

Ссылки:


flex-basisпроисходит сбой в Chrome и Firefox, когда дедушка-родительский элемент является усадочным элементом. Настройка отлично работает в Edge.

Как и в примере, представленном в приведенной выше ссылке, с position: absoluteиспользованием, floatи inline-blockтакже будет отображаться тот же некорректный вывод ( jsfiddle demo ).


Ошибки, влияющие на IE 10 и 11:

Майкл Бенджамин
источник
2
Как насчет min-width:100px;? Может ли быть опция отключения усадки?
Мори
1
@ Мори, да, flex-shrinkостанавливается на min-width. Эквивалентное гибкое правило будет flex: 1 0 100px.
Майкл Бенджамин
flex: 1 0 100pxприводит к тому же результату, но я не уверен, что вы подразумеваете под «эквивалентом».
Мори
Я имею в виду, почему мы не должны считать это равным flex: 0 0 100px, например?
Мори
2
@ Мори, потому что тогда оно просто равно ширине . Требуется компонент flex-grow: 1, чтобы элемент мог расти от минимальной ширины, установленной flex-base .
Майкл Бенджамин
33

В дополнение к превосходному резюме Michael_B стоит повторить следующее:

flex-based позволяет указать начальный / начальный размер элемента, прежде чем что-либо еще будет вычислено. Это может быть процент или абсолютное значение.

Важная часть здесь является начальной .

Само по себе это разрешает ширину / высоту до тех пор, пока не вступят в игру другие свойства роста / сжатия.

Так. ребенок с

.child {
 flex-basis:25%;
 flex-grow:1;
}

сначала он будет иметь ширину 25%, но затем сразу же увеличится настолько, насколько это возможно, пока не будут учтены другие элементы. Если их нет, он будет иметь ширину 100% / высоту.

Быстрая демонстрация:

Эксперименты с flex-grow, flex-shrinkи flex-basis (или сокращением flex :fg fs fb) ... могут привести к некоторым интересным результатам.

Paulie_D
источник
Я обнаружил, что, как правило, в гибком контексте они оба flex-basisи width / heightзадают начальный / начальный размер элемента. Например в flex-basis: 200pxосновном работает так же как flex-basis: auto; width: 200px;. Похоже, когда flex-basisне установлен, autoто просто переопределяет width / heightзначение. Единственное отличие, которое я вижу, заключается в способе обработки переполнения контента.
Каролис
5

Возможно, самый важный момент, чтобы добавить:

Что если браузер не поддерживает flex? В таком случае width/heightвступают во владение и их значения применяются.

Это очень хорошая идея - почти необходимая - для определения width/heightэлементов, даже если у вас тогда совершенно другое значение для flex-basis. Не забудьте проверить, отключив display:flexи увидев, что вы получаете.

Нит Тёмный Абсол
источник
2
Среди основных браузеров единственными, которые не поддерживают свойства flex, являются IE <10. caniuse.com/#search=flex
Майкл Бенджамин
1
@Michael_B Конечно, и, возможно, это только я, но я должен также поддерживать мобильные браузеры, вплоть до браузера Nintendo 3DS, который явно не поддерживает flex.
Niet the Dark Absol