В спецификации HTML представлены теги, которые являются изначально либо строчными (свойство display имеет значение inline), либо блочные (display: block). Однако с выходом стандарта CSS3 появилась возможность изменять отображение элемента на строчно-блочное (display: inline-block).

По сути строчно-блочные элементы являются чем-то средним между строчными и блочными. То есть они имеют свойства и тех, и других элементов, комбинируя их. Каким образом? - В тексте они ведут себя, как строчные элементы, т.е. занимают ровно столько места, сколько текста содержится в них (если не заданы ширина или отступы), однако при назначении свойств box-модели, интерпретируют их, как блочные элементы.

Лучше всего это можно продемонстрировать на примере. В файле ниже в двух колонках с одинаковым текстом выделены одни и те же словосочетания. Выделения находятся в элементах span с классом inline слева и inline-block справа. Для этих классов заданы общие правила:

.inline, .inline-block {
    margin: 7px;
    padding: 7px;
}

Но в левой колонке все span имеют свойство display: inline, которое назначено для них в спецификации по умолчанию. А для span в правой колонке задан display: inline-block

Можно заметить, что за счет внутренних отступов (padding) слева цветные выделения накладываются друг на друга, кое-где перекрывая текст, а это и некрасиво, и нечитабельно. Что касается внешних отступов (margin), то сверху и снизу для span в левой колонке они просто игнорируются, и только слева и справа отодвигают текст от соседнего.

В правой колонке ситуация несколько иная - здесь все элементы span визуально отделены от соседнего текста, причем margin-ы работает по всем 4-м сторонам, а padding не приводят к перекрыванию текста выше. Выделенные блоки с большим количеством текста выглядят именно как блочные элементы, а те, где текста мало вписываются в текст, но за счет margin-ов увеличивают высоту строки.

Сложно назвать оба вида форматирования красивыми, но из этого тестового упражнения можно сделать следующие выводы:

  1. строчным элементам с фоном не стоит задавать большие внутренние отступы (padding), иначе они перекрывают выше идущий текст. Максимально это должно быть 3px и при этом стоит увеличить высоту строки (line-height) для родительского элемента (абзаца или div-а, например);
  2. строчно-блочные элементы с фоном, размещенные в тексте, не должны содержать большие объемы текста, иначе они будут "вываливаться" из него наподобие цитат, или врезок. Лучше использовать этот тип отображения для элементов, которые предназначены для каких-либо оформительских целей, например, для буквиц, шрифтовых иконок, кнопок, ссылок и т.п.

Использование inline-block элементов для создания кнопок

Сделаем еще один небольшой сравнительный анализ. В примере ниже представлены ссылки, внешний вид которых с помощью css-стилей отображает их как кнопки. Но 2 из них имеют display: inline-block, одна - display: inline (по умолчанию заданный в спецификации для ссылки) и еще одна  - display: block. Над каждой кнопкой подписано, каким образом она была отформатирована.

При клике на каждую из ссылок-кнопок текст, написанный на ней будет увеличен. В результате и сама кнопки либо увеличится, либо останется неизменной.

Что касается кнопок с display: inline-block и display: inline, у которых размер был сформирован padding-ами, то при добавлении текста они просто расширяются. Оранжевая кнопка  Sale, у которой размер имеет фиксированную ширину и высоту, увеличивается за счет добавленного текста вниз, хотя ни фон, ни рамка на этот текст не распространяются. Кнопка-ссылка с display: block изначально занимает всю ширину родительского элемента, поэтому добавление текста не влияет на ее размер на больших экранах. А вот на маленьких в ней текст за счет фиксированной высоты тоже выходит за пределы фона вниз. Еще можно заметить, что для желтой кнопки с display: inline несколько иначе определяются отступы от заголовка сверху - она расположена чуть выше всех остальных кнопок, хотя margin ни для одной из них в свойствах задан не был. Форматирование кнопок определялось такими свойствами:

.readmore,
.sale,
.sale-block,
.inline {
    color: #000;
    text-decoration: none;
    border-radius: 7px;
    border: 3px solid;
}

.readmore {
    display: inline-block;
    padding: 10px 17px;
    background-color: #6efc68;
    border-color: #37ac32;
}
.inline {
    background-color: #ffff37;
    border-color: #ffc937;
    padding: 10px 17px;
}
.sale,
.sale-block {
    height: 35px;
    line-height: 35px;
    text-align: center;
}

.sale {
    display: inline-block;
    width: 135px;
    background-color: #f7692a;
    border-color: #c13c01;
}
.sale-block {
    display: block;
    background-color: #3ad9ff;
    border-color: #0a6d84;
}

Использование inline-block элементов для создания колонок

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

Например, у нас есть такая html-разметка: внутри родительского элемента с классом wrap есть 3 колонки с классами .col с заголовком и 3-мя абзацами. Можно воспользоваться аббревиатурой Emmet:

.wrap.col*3>h2{Some Title $}+p*3>lorem15

Нажимаем Tab и получаем разметку:

<div class="wrap">
    <h2>Колонки</h2>
    <div class="col">
        <h2>Some Title 1</h2>
        <p>Lorem ipsum dolor sit amet, consectetur ...</p>
        <p>Quia neque ut repellat ratione ullam...</p>
        <p>Dolore consequatur omnis ...</p>
    </div>
    <div class="col">
        <h2>Some Title 2</h2>
        <p>Lorem ipsum dolor sit amet, consectetur ...</p>
        <p>Quibusdam, consequatur animi, rem ...</p>
        <p>Nisi quibusdam dolore atque ...</p>
    </div>
    <div class="col">
        <h2>Some Title 3</h2>
        <p>Lorem ipsum dolor sit amet ...</p>
        <p>Ipsum magnam, nam consequatur ...</p>
        <p>Accusantium necessitatibus ...</p> 
    </div>
</div>

Для всех элементов добавим свойство box-sizing: border-box, чтобы ширина элементов не зависела от padding и border, а для родительского элемента .wrap зададим следующие максимальную ширину и внешние отступы:

* {    box-sizing: border-box;}
.wrap {
    max-width: 1200px;
    margin: auto;
}

Для 3-х колонок ширина их контейнера представляет собой 100%. Мы хотим, чтобы между колонками были отступы по 2%. Поскольку нам необходимы отступы только между первой и второй, а затем между второй и третьей, но не после 3-й колонки, то пространство контейнера следует разделить следующим образом: 100% - 4% margin = 96%. Далее 96%/3= 32% - получаем width каждой колонки. Затем используем это для свойств наших колонок с классом .col:

.col {
    display: inline-block;
    width: 32%;
    margin-right: 2%;
    margin-bottom: 20px;    
    padding: 0 15px;
    background-color: #fff;
}
.col:last-child {    margin-right: 0;}

Обязательно нужно отключить правый margin для последней колонки, что мы и сделали с помощью псевдокласса :last-child.

И вот, что мы получим в итоге:

Вуа-ля - и нет 3-х колонок, которые выстроились в одну линию. Вместо этого есть 2 колонки в одном ряду + одна в нижнем ряду. Совсем не то, что нужно. В чем же причина "сваливания" последней колоки?

Дело в том, что поскольку display: inline-block предполагает все-таки частично строчное размещение текста, то в конце каждой колонки у нас образуется еще один пробельный символ, в который превращаются все знаки в HTML (пробелы, табуляция, переносы слов), в каком бы количестве они не встречались в тексте. Именно этот пробельный символ, размер которого зависит от размера шрифта, и добавляет нам несколько пикселей между колонками, которые "выбивают" третью из них вниз. 

Чтобы этого избежать, имеет смысл воспользоваться функцией calc(), которая появилась в стандарте CSS3 и давно уже поддерживается современными браузерами. Важным моментом в ее использовании является установка пробелов ДО и ПОСЛЕ знака минус:

.col {
    display: inline-block;
    width: calc(32% - 3px);
    margin-right: 2%;
    margin-bottom: 20px;    
    padding: 0 15px;
    background-color: #fff;
}

Результат уже намного лучше:

Для того чтобы колонки с разным количеством текста не выбивались из одной линии, необходимо использовать свойство vertical-align чаще всего со значением top. Добавим его к нашим css-свойствам:

.col {
    display: inline-block;
    vertical-align: top;
    width: calc(32% - 3px);
    margin-right: 2%;
    margin-bottom: 20px;
    padding: 0 15px;
    background-color: #fff;
}

В результате получим колонки разной высоты, но выровненные по верхней линии:

Автор: Админ

3 комментария

  1. Если в блоке я напишу так:
    link

    ...

    и поставлю для блока text-align: center, то ссылка и список станут по центру, хотя ссылка - это inline-элемент, а список - блочный. Почему так?

    • Дело в том, что в любом блочном элементе (список в вашем примере), для которого задан text-align: center, текст будет выравниваться по центру. Именно это вы и видите. Если элемент, которому задан display: block, нетекстовый - картинка, например, то text-align: center для родительского элемента никакого влияния на вложенный элемент не окажет.
      Пробуйте сами: ссылка на codepen.io.

  2. Спасибо. Все очень понятно расписано

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *