
Div в одну строку как span: display inline, inline-block и float
Блоки div по умолчанию выстраиваются сверху вниз. Когда их нужно поставить в строку, на выбор есть три приёма CSS, и у каждого свои особенности поведения и старых браузеров.
Блочные и строчные элементы
Элемент 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 с помощью хака со звёздочкой.
/* Карточки в строку */
.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;
}float: обтекание и его последствия
До широкой поддержки inline-block почти вся многоколоночная вёрстка строилась на float. Свойство float: left вынимает блок из обычного потока и прижимает к левому краю, а следующие элементы обтекают его справа. Два блока с float: left встанут рядом, а float: right прижмёт блок к правому краю.
Плавающие блоки не учитываются при расчёте высоты родителя. Если внутри контейнера только плавающие элементы, его высота станет нулевой, фон и рамка пропадут, а следующий контент заедет наверх. Это лечится «очисткой»: либо элементом с clear: both после колонок, либо классом clearfix у родителя.
/* Две колонки на 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 поля. Клик по подписи ставит фокус в поле, а скринридер зачитывает подпись вместе с полем.
<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: колонки и обтекание, не забывайте очистку родителя.
Как это делают сегодня
Вопросы и ответы
Почему у div с display: inline не работает width?
Строчные элементы игнорируют ширину и высоту. Используйте display: inline-block, тогда блок встанет в строку и сохранит заданные размеры.
Откуда зазор между блоками inline-block?
Это пробельные символы между тегами в HTML, они отображаются как обычный пробел. Уберите их из разметки или задайте родителю font-size: 0, восстановив размер шрифта у дочерних блоков.
Почему фон контейнера пропал после float?
Плавающие дочерние элементы не учитываются в высоте родителя, и он схлопывается. Добавьте родителю clearfix, overflow: hidden или display: flow-root.