flex-shrink: сжатие

flex-shrink задаёт коэффициент сжатия flex-элемента: насколько он уменьшится относительно других элементов, когда суммарный размер всех элементов превышает размер контейнера.

Зачем нужно

По умолчанию flex-shrink: 1 у всех элементов — браузер автоматически сжимает их, чтобы вместить в контейнер. Но иногда нужно защитить конкретный элемент от сжатия (логотип, иконка, фиксированная кнопка). flex-shrink: 0 гарантирует сохранение размера.

Где используется

  • Логотип в навбаре не должен уменьшаться
  • Аватар пользователя фиксированного размера
  • Иконки в ряду кнопок сохраняют форму

Синтаксис

.item {
  flex-shrink: 1; /* по умолчанию — сжимается */
  flex-shrink: 0; /* не сжимается */
  flex-shrink: 2; /* сжимается вдвое сильнее, чем элемент с flex-shrink: 1 */
}

Примеры

Защита элемента от сжатия

.navbar {
  display: flex;
  align-items: center;
  gap: 16px;
}
.logo {
  width: 120px;
  flex-shrink: 0; /* логотип всегда 120px */
}
.nav-links {
  flex: 1; /* остальное место — ссылки */
}
<nav class="navbar">
  <img class="logo" src="logo.svg">
  <div class="nav-links">
    <a href="/">Главная</a>
    <a href="/about">О нас</a>
  </div>
</nav>

Пропорциональное сжатие

.container {
  display: flex;
  width: 400px; /* допустим, элементы суммарно занимают 600px */
}
/* Дефицит = 200px */
.item-a {
  flex-basis: 300px;
  flex-shrink: 1; /* усядет на 100px → станет 200px */
}
.item-b {
  flex-basis: 300px;
  flex-shrink: 1; /* усядет на 100px → станет 200px */
}

Разные коэффициенты сжатия

.item-a { flex-shrink: 1; } /* сжимается "нормально" */
.item-b { flex-shrink: 3; } /* сжимается втрое сильнее */
/* При дефиците 400px: item-a потеряет 100px, item-b — 300px */

Как работает расчёт (упрощённо)

Сжатие пропорционально произведению flex-shrink × flex-basis. Элемент с большим basis и большим shrink сожмётся сильнее.

flex-shrink: 0 + overflow

Если все элементы имеют flex-shrink: 0, они не сжимаются и контейнер может переполниться:

.container {
  display: flex;
  overflow-x: auto; /* добавить скролл при переполнении */
}
.item {
  flex-shrink: 0;
  width: 300px;
}

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

  1. Ожидание, что flex-shrink: 0 + flex-basis не позволят элементу стать меньшеmin-width всё равно может ограничить минимум; но без flex-shrink: 0 элемент будет сжиматься ниже basis
  2. flex-shrink применён к контейнеру — это свойство только для flex-элементов
  3. flex-shrink: 0 у всех элементов — контейнер переполняется, нужен overflow: auto или flex-wrap: wrap

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

Ресурсы