Длинная ссылка в карточке выталкивает кнопку за край экрана? Разрешите текстовому флекс-элементу сжиматься через min-inline-size: 0 и добавьте переносы. Эти правила отвечают за разные части задачи: ширину блока и строки внутри него.
Получится строка с аватаром, именем и кнопкой. На узком экране имя и ссылка займут несколько строк, а кнопка останется видна. Для примера нужны HTML и CSS; JavaScript не понадобится. Основы Flexible Box Layout, или Flexbox, можно освежить в нашем руководстве по флексам.
Соберите строку с длинной ссылкой
Сохраните разметку в index.html, стили — в style.css рядом с ним. Откройте HTML-файл в браузере. Это учебная карточка: инициалы заменяют фотографию, кнопка показывает компоновку и не отправляет сообщение.
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Строка с длинным текстом</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<main>
<h1>Строка с длинным текстом</h1>
<article class="person">
<span class="person__avatar" aria-hidden="true">АП</span>
<div class="person__details">
<h2 class="person__name">Александра Петрова</h2>
<a class="person__link" href="https://example.com/portfolio/verylongfilenamewithoutspaces">
https://example.com/portfolio/verylongfilenamewithoutspaces
</a>
</div>
<button class="person__button" type="button">Написать</button>
</article>
<p>Учебная карточка. Кнопка показывает компоновку и не отправляет сообщение.</p>
</main>
</body>
</html>
Сначала воспроизведите ошибку. У текстового блока останется автоматический минимум ширины, а длинный адрес будет переноситься по правилу break-word:
/* Начальный вариант с переполнением — для диагностики. */
.person { display: flex; align-items: center; gap: 12px; }
.person__avatar { flex: 0 0 48px; }
.person__details { flex: 1 1 auto; }
.person__link { overflow-wrap: break-word; }
.person__button { flex: 0 0 auto; white-space: nowrap; }
Сузьте окно примерно до 320 пикселей. Адрес длиннее оставшегося места. Текстовый блок удерживает свою минимальную ширину, и кнопка оказывается снаружи. Ниже — полный исправленный style.css. Замените им начальный вариант.
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 16px;
font: 16px/1.5 Arial, sans-serif;
}
main {
max-inline-size: 760px;
margin-inline: auto;
}
h1 {
font-size: 24px;
}
.person {
display: flex;
align-items: center;
gap: 12px;
padding: 12px;
border: 1px solid #8a8a8a;
border-radius: 8px;
}
.person__avatar {
display: grid;
place-items: center;
flex: 0 0 48px;
block-size: 48px;
border-radius: 50%;
background: #e0ebff;
}
.person__details {
flex: 1 1 auto;
min-inline-size: 0;
}
.person__name {
margin: 0;
font-size: 18px;
overflow-wrap: anywhere;
}
.person__link {
overflow-wrap: anywhere;
}
.person__button {
flex: 0 0 auto;
padding: 8px;
font: inherit;
white-space: nowrap;
}
Проверьте карточку при ширине окна 320, 375 и 768 пикселей. Текст должен переноситься внутри блока, аватар оставаться круглым, кнопка — помещаться в рамку. Теперь можно выяснить, какая часть исправления за это отвечает.
Найдите элемент с автоматическим минимумом
В обычной горизонтальной строке флекс-элемент по умолчанию имеет min-width: auto. Для нашего текстового блока с overflow: visible этот минимум зависит от содержимого. В примере без заданной ширины и соотношения сторон его определяет min-content: ширина самой длинной части текста, которую браузер считает неделимой.
У ссылки такой частью может стать длинный фрагмент адреса. Точки переноса, которые добавляет overflow-wrap: break-word, при расчёте min-content не учитываются. Поэтому элемент сопротивляется сжатию ещё до того, как браузер начнёт раскладывать строки внутри него.
Это описание именно нашего случая. Автоматический минимум не всегда равен min-content: на него могут влиять размеры и соотношение сторон. При прокручиваемых значениях overflow правило тоже меняется. Точный порядок расчёта с учётом этих условий описан в разделе спецификации об автоматическом минимуме.
Перед следующим абзацем выберите, куда поставить min-inline-size: 0: на .person__details или на ссылку внутри него. Объясните выбор через связь выбранного элемента с родителем, у которого задан display: flex.
Правило нужно поставить на .person__details: он непосредственно участвует во флекс-строке. Если поставить правило только на ссылку внутри него, минимум родительского флекс-элемента останется прежним. Для проверки вернитесь к начальному варианту с break-word и поочерёдно добавьте нулевой минимум этим двум элементам. Кнопка поместится в строке после изменения .person__details.
Здесь min-inline-size соответствует min-width, поскольку текст идёт горизонтально. Логическое свойство описывает размер вдоль строки текста. Для вертикальной главной оси Flexbox нужно отдельно проверить, какой минимум мешает сжатию; эта статья разбирает горизонтальную строку.
Перенесите длинные строки внутри блока
Нулевой минимум разрешает блоку стать уже содержимого. Сам по себе он не создаёт новых мест для переноса: длинная строка всё ещё может выйти за край своего блока.
В готовом примере за перенос отвечает overflow-wrap: anywhere. Обычные слова браузер переносит привычным способом, а слишком длинный неделимый фрагмент может разбить в произвольном месте. Текст остаётся целиком доступен для чтения и копирования.
У anywhere и break-word есть существенное отличие: новые возможности переноса от anywhere учитываются при расчёте min-content. Поэтому в этой карточке anywhere способен убрать переполнение даже с автоматическим минимумом. Явный min-inline-size: 0 всё равно полезен: он задаёт поведение флекс-элемента независимо от того, какое правило переноса выбрано для вложенного текста. Различие значений разобрано в справке MDN по overflow-wrap.
Не добавляйте overflow: hidden на всю карточку ради исчезнувшей полосы прокрутки. С этим правилом часть текста или кнопка могут скрыться. Если по дизайну требуется одна строка с многоточием, это отдельное решение: нужно явно выбрать обрезку вместо переноса и сохранить доступ к полному содержимому.
Проверьте сжатие соседей
flex-shrink описывает участие элемента в распределении недостающего пространства. Минимальный размер ограничивает результат этого распределения. Поэтому увеличение flex-shrink не заставит текстовый блок пройти через его автоматический минимум.
В нашем примере .person__details может расти и сжиматься: это flex: 1 1 auto. У аватара flex: 0 0 48px, у кнопки — flex: 0 0 auto. Они сохраняют размер, а текст занимает остаток. Это подходит для короткой кнопки «Написать» и аватара шириной 48 пикселей.
Длинная надпись на кнопке может занять весь остаток сама. Тогда потребуется изменить компоновку, например разрешить строке переносить элементы или поставить кнопку ниже текста на узком экране. min-inline-size: 0 не создаёт дополнительного пространства.
Ещё одна деталь: flex-shrink: 2 не означает, что элемент всегда потеряет вдвое больше пикселей, чем сосед с flex-shrink: 1. При распределении учитывается произведение коэффициента сжатия на базовый размер элемента; затем действуют ограничения минимума и максимума. Сравнивать только коэффициенты недостаточно.
Проверьте вложенные флекс-строки
Если карточка сама лежит во флекс-строке, у неё появляется собственный автоматический минимум. Даже после настройки вложенного .person__details карточка может растягивать внешнюю строку. Проверьте цепочку родителей в инструментах разработчика.
Для строки .outer, в которой карточка делит место с соседним значком, добавьте такие правила к готовому примеру:
.outer { display: flex; gap: 8px; }
.outer > .person { flex: 1 1 auto; min-inline-size: 0; }
.outer > .badge { flex: 0 0 30px; }
Правило на .person относится к её участию во внешней строке. Правило на .person__details — к тексту во внутренней. Не расставляйте нулевой минимум по всем элементам страницы: найдите конкретных участников, которым нужно сжиматься.
| Что видно в карточке | Что проверить |
|---|---|
| Кнопка уехала за границу | Минимум непосредственного текстового флекс-элемента |
| Блок стал узким, но адрес торчит наружу | Перенос длинной строки и возможный white-space: nowrap |
| Вложенная карточка всё ещё растягивает родителя | Минимум карточки во внешней флекс-строке |
| Даже без текста не помещаются аватар и кнопка | Размеры соседей, промежутки и саму компоновку |
Усложните карточку и проверьте результат
Замените имя строкой без пробелов, например «Сверхдлинноеимябезпробеловдляпроверкипереполнения». Подсказка: перенос должен быть разрешён и у заголовка. При ширине 320 пикселей имя останется внутри текстового блока, а кнопка — внутри карточки.
Для самостоятельной вариации поместите карточку в .outer рядом со значком шириной 30 пикселей. Добавьте рамку внешнему контейнеру. При тех же трёх ширинах обе рамки должны вмещать свои элементы, а ссылка и имя — читаться целиком.
Если хотите системно потренировать такие решения, посмотрите курс «Адаптивная вёрстка» HTML Academy.
Какой элемент в вашей вложенной карточке участвует во внешней флекс-строке? Если убрать переносы, какое правило всё ещё разрешит текстовому блоку сжиматься и почему этого будет недостаточно для длинного адреса?