Когда дело доходит до выставления ширины блока, большинство привычно тянется к px, % или auto. Но в CSS есть отдельная группа значений, которые рассчитывают размер не по сетке и не по контейнеру, а по самому содержимому элемента. Их так и называют — intrinsic sizing keywords или «размеры по содержимому»: min-content, max-content и fit-content.

В работе они встречаются нечасто — не потому что бесполезны, а потому что мало кто помнит, чем именно отличаются. Разберём по очереди и увидим, в каких ситуациях именно эти три значения убирают необходимость городить вычисления через calc() или JavaScript.

Значение min-content

Браузер ставит элементу такую ширину, при которой содержимое ещё помещается без переполнения, но не уже. Для текста минимальная неуменьшаемая единица — самое длинное слово в блоке: его не разорвёшь, иначе получится не слово.

.label {
  width: min-content;
  background: #fef3c7;
  padding: 8px 12px;
}

Если внутри .label лежит фраза «Документация по API», ширина блока схлопнется до ширины слова «Документация» — самого длинного. Все остальные слова перенесутся на свои строки.

Тонкость в том, что «неразрывной единицей» для браузера может оказаться не только слово. Если внутри есть картинка фиксированной ширины, длинное URL-подобное слово или элемент с white-space: nowrap, минимальная ширина будет уже по этому объекту, и блок получится шире, чем кажется на глаз.

Значение max-content

Это полная противоположность. Элемент получает такую ширину, как если бы переноса строк не было вообще: всё содержимое выложено в одну строку, и блок ровно по нему.

.tag {
  width: max-content;
  background: #dbeafe;
  padding: 4px 10px;
  border-radius: 4px;
}

Полезно для тегов, бейджей, кнопок «по контенту» — когда нужно, чтобы элемент занимал ровно столько, сколько занимает его текст, без подсчёта в пикселях и без display: inline-block со всеми его побочными эффектами.

Главный риск: если содержимое окажется длиннее родителя, элемент выйдет за границы контейнера. max-content не оглядывается на родителя — он смотрит только на собственный контент.

Значение fit-content

Компромиссное значение: ведёт себя как max-content, пока контент помещается в родителя, и как min-content, как только перестаёт. Иначе говоря, элемент «тянется по контенту, но не больше контейнера».

.notice {
  width: fit-content;
  margin: 0 auto;
  padding: 12px 20px;
  background: #f0fdf4;
  border: 1px solid #86efac;
}

Это, пожалуй, самое практичное из трёх значений: получаем плотный по содержимому блок, который при этом гарантированно не вылезет за пределы родителя. Идеально для уведомлений, всплывающих меток, центрированных карточек неизвестной длины.

Функциональная форма fit-content()

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

.tooltip {
  width: fit-content(300px);
  padding: 8px 12px;
  background: #1f2937;
  color: #fff;
}

Для тултипов, информационных плашек, узких всплывашек — естественнее, чем связка max-width: 300px; width: max-content. В одну строку.

Где это реально пригождается

Большинство людей знакомятся с min-content и max-content именно через CSS Grid — потому что в треках сетки они работают особенно мощно.

В CSS Grid

Колонки и строки в Grid принимают эти ключевые слова напрямую и в составе функции minmax(). Классический рецепт «первая колонка по контенту, вторая занимает всё остальное»:

.layout {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 24px;
}

Ещё более практичный паттерн — колонка-резинка, которая не схлопывается уже своего содержимого:

.sidebar-layout {
  display: grid;
  grid-template-columns: minmax(min-content, 240px) 1fr;
}

Здесь сайдбар держится в районе 240px, но при необходимости может ужаться до ширины своего самого длинного элемента и не дальше. Без min-content в нижней границе сайдбар при узком экране начал бы рвать слова или вылезать на основной контент.

В Flexbox

В Flex эти же значения принимает flex-basis, а также width у flex-элементов:

.toolbar {
  display: flex;
  gap: 8px;
}
.toolbar .label {
  flex-basis: max-content;
}

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

В обычных блоках

Никакого Grid и Flex не нужно. Любой блочный элемент примет width: fit-content и будет вести себя как описано выше. Это, кстати, удобный способ центрировать блок неизвестной ширины через margin: 0 auto: fit-content уберёт лишнюю ширину, а margin центрирует то, что осталось.

На что не путать

Эти три значения часто конкурируют в голове с другими способами задать ширину. Чтобы не путаться:

  • auto — для блочных элементов это «занять всю доступную ширину родителя». Это поведение по умолчанию для div, section и т. д. Никакого отношения к содержимому не имеет.
  • 100% — ровно ширина родителя, без учёта box-sizing в полной мере и тоже без оглядки на контент.
  • 1fr в Grid — занимает доступное пространство трека, делит его поровну с другими fr-треками. Но fr-трек не учитывает минимальный размер контента: длинное слово может вылезти из 1fr-колонки. Поэтому в реальной вёрстке часто используют minmax(0, 1fr) или minmax(min-content, 1fr).

Эти размеры читают контейнер. min-content/max-content/fit-content читают контент. Это и есть та самая категория «intrinsic sizing», ради которой группу и придумали.

Поддержка браузерами

Поддержка браузерами
chrome
Chrome
66
firefox
Firefox
66
internet explorer
IE
 
edge
Edge
79
safari
Safari
15.1
opera
Opera
53

Это не «экспериментальная фича» и не «что-то для будущего», а уже привычная часть CSS — статус Baseline с января 2020 года.

Итог

Если запомнить одно правило, оно такое: auto и 100% думают про родителя, а min-content/max-content/fit-content — про содержимое. Когда ширину диктует именно контент (тег, бейдж, плашка-уведомление, колонка с заголовком переменной длины) — эти три значения убирают необходимость в магических числах и медиа-запросах. fit-content в большинстве задач достаточно одного, остальные два пригождаются точечно — чаще всего в Grid и Flex.

Полный интерактивный пример различий.