Div в одну строку как span: display inline, inline-block и float

РазделJavaScript и CSSУровеньНовичок Чтение7 минОпубликовано ТегиCSSВёрсткаHTML

Блоки div по умолчанию выстраиваются сверху вниз. Когда их нужно поставить в строку, на выбор есть три приёма CSS, и у каждого свои особенности поведения и старых браузеров.

Главное. Div встаёт в строку, если сменить ему display на inline или inline-block либо сделать его плавающим. Для элементов с размерами выбирайте inline-block, для колонок в старой вёрстке float с clearfix.

Блочные и строчные элементы

Элемент div по умолчанию блочный: он занимает всю доступную ширину родителя и начинается с новой строки. Поэтому два div подряд всегда окажутся один под другим, даже если каждому задать маленькую ширину. Элемент span, наоборот, строчный: он течёт вместе с текстом и встаёт рядом с соседями.

Поведение задаётся не тегом, а CSS-свойством display, у div оно равно block, у span inline. Значит, div можно заставить вести себя как span, не меняя разметку. Это важно в Web Forms: элемент Panel рендерится в div, и переписать его на span нельзя, а вот добавить класс со стилем можно всегда.

display: inline и его ограничения

Самый прямой способ: display: inline. Блоки встанут в строку, как слова в предложении. Но строчный элемент игнорирует ширину и высоту, а вертикальные отступы margin не раздвигают соседние строки. Внутри него нельзя корректно разместить другие блочные элементы, например таблицу или вложенный div.

Поэтому inline подходит только для простых случаев: подпись, иконка, короткая метка рядом с полем. Для колонок, карточек и кнопок с фиксированным размером нужен другой режим.

display: inline-block

Значение inline-block сочетает оба мира: снаружи элемент ведёт себя как строчный и встаёт в линию с соседями, а внутри остаётся блоком, поэтому у него работают width, height, padding и margin. Блоки выравниваются по базовой линии текста, и это легко изменить свойством vertical-align: top.

Отдельная история связана с Internet Explorer 6 и 7. Они поддерживают inline-block только для изначально строчных элементов, а для div значение игнорируют. Помогает известный приём: включить у элемента hasLayout через zoom: 1 и выставить display: inline для старых IE с помощью хака со звёздочкой.

layout.cssCSS
/* Карточки в строку */
.card {
  display: inline-block;
  vertical-align: top;   /* выравнивание по верхнему краю */
  width: 220px;
  margin: 0 10px 10px 0;
  padding: 12px;
  border: 1px solid #ccc;
  /* IE 6 и 7: inline + hasLayout = inline-block */
  *display: inline;
  zoom: 1;
}
Между блоками inline-block появляется зазор шириной в пробел: это перевод строки в HTML между тегами. Его убирают, записывая закрывающий и открывающий теги вплотную или задавая родителю font-size: 0 с восстановлением размера у детей.

float: обтекание и его последствия

До широкой поддержки inline-block почти вся многоколоночная вёрстка строилась на float. Свойство float: left вынимает блок из обычного потока и прижимает к левому краю, а следующие элементы обтекают его справа. Два блока с float: left встанут рядом, а float: right прижмёт блок к правому краю.

Плавающие блоки не учитываются при расчёте высоты родителя. Если внутри контейнера только плавающие элементы, его высота станет нулевой, фон и рамка пропадут, а следующий контент заедет наверх. Это лечится «очисткой»: либо элементом с clear: both после колонок, либо классом clearfix у родителя.

layout.cssCSS
/* Две колонки на float */
.col-left  { float: left;  width: 30%; }
.col-right { float: right; width: 68%; }

/* Родитель растягивается по высоте колонок */
.clearfix:after {
  content: ".";
  display: block;
  height: 0;
  clear: both;
  visibility: hidden;
}
.clearfix { zoom: 1; } /* то же для IE 6 и 7 */

Пример: подпись и поле формы в одну строку

Типичная задача в формах ASP.NET: метка слева, поле справа, и так строка за строкой. Таблица для этого избыточна, а float с фиксированной шириной метки даёт ровную колонку. Каждая строка формы оборачивается в div с clearfix, чтобы следующие строки не наезжали на предыдущие.

Метка оформляется тегом label с атрибутом for, указывающим на ClientID поля. Клик по подписи ставит фокус в поле, а скринридер зачитывает подпись вместе с полем.

Profile.aspxASPX
<style>
  .row { margin-bottom: 8px; }
  .row label { float: left; width: 140px; padding-top: 3px; }
  .row .field { margin-left: 150px; }
</style>

<div class="row clearfix">
  <asp:Label runat="server" AssociatedControlID="txtName" Text="Имя" />
  <div class="field"><asp:TextBox ID="txtName" runat="server" /></div>
</div>
<div class="row clearfix">
  <asp:Label runat="server" AssociatedControlID="txtEmail" Text="E-mail" />
  <div class="field"><asp:TextBox ID="txtEmail" runat="server" /></div>
</div>

Как выбрать способ

Короткие фрагменты внутри текста ставьте через display: inline. Набор одинаковых карточек, кнопок или миниатюр, которые должны переноситься на новую строку при сужении окна, удобнее всего делать на inline-block. Колонки страницы и пары «подпись и поле» в старых проектах обычно сделаны на float, и переделывать их без необходимости не стоит.

Перед правкой legacy-вёрстки проверьте, на чём она построена. Добавление display: inline-block к блоку, который уже плавает, ничего не изменит, потому что float сам переводит элемент в блочный режим. Такие «правки, которые не работают» отнимают много времени.

  • inline: текстовые вставки, размеры не задаются;
  • inline-block: строка карточек с размерами, следите за зазором от пробелов;
  • float: колонки и обтекание, не забывайте очистку родителя.

Как это делают сегодня

Сегодня горизонтальные раскладки делают на flexbox (display: flex) и CSS Grid: они выравнивают блоки по высоте, не дают зазоров от пробелов, а расстояние задаётся свойством gap. Хаки для IE 6 и 7 и clearfix в новом коде не нужны, свойство display: flow-root решает задачу очистки float одной строкой. Float остаётся для своей исходной роли: обтекания картинки текстом.

Вопросы и ответы

Почему у div с display: inline не работает width?

Строчные элементы игнорируют ширину и высоту. Используйте display: inline-block, тогда блок встанет в строку и сохранит заданные размеры.

Откуда зазор между блоками inline-block?

Это пробельные символы между тегами в HTML, они отображаются как обычный пробел. Уберите их из разметки или задайте родителю font-size: 0, восстановив размер шрифта у дочерних блоков.

Почему фон контейнера пропал после float?

Плавающие дочерние элементы не учитываются в высоте родителя, и он схлопывается. Добавьте родителю clearfix, overflow: hidden или display: flow-root.

Читайте также