Как Flexbox рассчитывает размеры

Flexbox рассчитывает размеры элементов через алгоритм flex-алгоритма: сначала устанавливается flex-basis, затем свободное место распределяется через flex-grow, а при нехватке места — элементы сжимаются через flex-shrink.

Зачем нужно

Понимание алгоритма расчёта объясняет, почему элементы неожиданно вырастают, сжимаются или имеют разные размеры при одинаковых настройках. Без этого трудно предсказать поведение Flexbox в нестандартных ситуациях.

Шаги алгоритма

1. Определение flex-basis

Начальный размер элемента до распределения пространства:

.item {
  flex-basis: auto;    /* по умолчанию: размер по содержимому (или width) */
  flex-basis: 200px;   /* фиксированный базовый размер */
  flex-basis: 0;       /* игнорировать содержимое, делить с нуля */
}

2. Распределение свободного места — flex-grow

Если в контейнере есть свободное место, оно делится между элементами пропорционально flex-grow:

/* Контейнер 900px, три элемента с basis 0 */
.a { flex-grow: 1; } /* получит 300px */
.b { flex-grow: 2; } /* получит 600px */
.c { flex-grow: 0; } /* не растёт */

3. Сжатие при нехватке места — flex-shrink

Если элементы не помещаются, они сжимаются пропорционально flex-shrink:

/* flex-shrink: 1 — сжимается (по умолчанию) */
/* flex-shrink: 0 — не сжимается */
.fixed { flex-shrink: 0; } /* размер сохраняется */

Shorthand flex

.item {
  flex: 1;          /* flex-grow: 1, flex-shrink: 1, flex-basis: 0% */
  flex: auto;       /* flex-grow: 1, flex-shrink: 1, flex-basis: auto */
  flex: none;       /* flex-grow: 0, flex-shrink: 0, flex-basis: auto */
  flex: 0 0 200px;  /* grow shrink basis — фиксированный 200px */
}

Пример: базовый расчёт

.container {
  display: flex;
  width: 600px;
}

.a { flex: 1; flex-basis: 0; }  /* 200px */
.b { flex: 2; flex-basis: 0; }  /* 400px */
/* Свободное место: 600px / (1+2) * 1 = 200px, * 2 = 400px */
<div class="container">
  <div class="a">A</div>
  <div class="b">B</div>
</div>

Ограничения: min-width и max-width

Итоговый размер не может быть меньше min-width (по умолчанию auto) и больше max-width:

.item {
  flex: 1;
  min-width: 0;    /* разрешить сжатие ниже auto */
  max-width: 400px; /* не шире 400px даже при flex-grow */
}

Частые ошибки

  1. flex: 1 vs flex: 1 1 autoflex: 1 устанавливает flex-basis: 0%, не auto; элементы с контентом могут вести себя иначе.
  2. Непонимание flex-basis: auto — при auto за основу берётся width элемента (или размер контента), а не ноль.
  3. flex-shrink при flex-basis: 0 — если базовый размер 0, flex-shrink не имеет смысла — сжиматься некуда.

Связанные темы

Ресурсы