В спецификации HTML представлены теги, которые являются изначально либо строчными (свойство display имеет значение inline), либо блочные (display: block). Однако с выходом стандарта CSS3 появилась возможность изменять отображение элемента на строчно-блочное (display: inline-block).
По сути строчно-блочные элементы являются чем-то средним между строчными и блочными. То есть они имеют свойства и тех, и других элементов, комбинируя их. Каким образом? - В тексте они ведут себя, как строчные элементы, т.е. занимают ровно столько места, сколько текста содержится в них (если не заданы ширина или отступы), однако при назначении свойств box-модели, интерпретируют их, как блочные элементы.
Лучше всего это можно продемонстрировать на примере. В файле ниже в двух колонках с одинаковым текстом выделены одни и те же словосочетания. Выделения находятся в элементах span с классом inline
слева и inline-block
справа. Для этих классов заданы общие правила:
1 2 3 4 |
.inline, .inline-block { margin: 7px; padding: 7px; } |
Но в левой колонке все span имеют свойство display: inline
, которое назначено для них в спецификации по умолчанию. А для span
в правой колонке задан display: inline-block
.
Можно заметить, что за счет внутренних отступов (padding
) слева цветные выделения накладываются друг на друга, кое-где перекрывая текст, а это и некрасиво, и нечитабельно. Что касается внешних отступов (margin), то сверху и снизу для span
в левой колонке они просто игнорируются, и только слева и справа отодвигают текст от соседнего.
В правой колонке ситуация несколько иная - здесь все элементы span
визуально отделены от соседнего текста, причем margin-ы
работает по всем 4-м сторонам, а padding
не приводят к перекрыванию текста выше. Выделенные блоки с большим количеством текста выглядят именно как блочные элементы, а те, где текста мало вписываются в текст, но за счет margin-ов увеличивают высоту строки.
Сложно назвать оба вида форматирования красивыми, но из этого тестового упражнения можно сделать следующие выводы:
- строчным элементам с фоном не стоит задавать большие внутренние отступы (
padding
), иначе они перекрывают выше идущий текст. Максимально это должно быть 3px и при этом стоит увеличить высоту строки (line-height
) для родительского элемента (абзаца или div-а, например); - строчно-блочные элементы с фоном, размещенные в тексте, не должны содержать большие объемы текста, иначе они будут "вываливаться" из него наподобие цитат, или врезок. Лучше использовать этот тип отображения для элементов, которые предназначены для каких-либо оформительских целей, например, для буквиц, шрифтовых иконок, кнопок, ссылок и т.п.
Использование inline-block элементов для создания кнопок
Сделаем еще один небольшой сравнительный анализ. В примере ниже представлены ссылки, внешний вид которых с помощью css-стилей отображает их как кнопки. Но 2 из них имеют display: inline-block
, одна - display: inline
(по умолчанию заданный в спецификации для ссылки) и еще одна - display: block
. Над каждой кнопкой подписано, каким образом она была отформатирована.
При клике на каждую из ссылок-кнопок текст, написанный на ней будет увеличен. В результате и сама кнопки либо увеличится, либо останется неизменной.
Что касается кнопок с display: inline-block
и display: inline
, у которых размер был сформирован padding-ами, то при добавлении текста они просто расширяются. Оранжевая кнопка Sale, у которой размер имеет фиксированную ширину и высоту, увеличивается за счет добавленного текста вниз, хотя ни фон, ни рамка на этот текст не распространяются. Кнопка-ссылка с display: block
изначально занимает всю ширину родительского элемента, поэтому добавление текста не влияет на ее размер на больших экранах. А вот на маленьких в ней текст за счет фиксированной высоты тоже выходит за пределы фона вниз. Еще можно заметить, что для желтой кнопки с display: inline
несколько иначе определяются отступы от заголовка сверху - она расположена чуть выше всех остальных кнопок, хотя margin ни для одной из них в свойствах задан не был. Форматирование кнопок определялось такими свойствами:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
.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:
1 |
.wrap.col*3>h2{Some Title $}+p*3>lorem15 |
Нажимаем Tab и получаем разметку:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<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
зададим следующие максимальную ширину и внешние отступы:
1 2 3 4 5 |
* { box-sizing: border-box;} .wrap { max-width: 1200px; margin: auto; } |
Для 3-х колонок ширина их контейнера представляет собой 100%
. Мы хотим, чтобы между колонками были отступы по 2%. Поскольку нам необходимы отступы только между первой и второй, а затем между второй и третьей, но не после 3-й колонки, то пространство контейнера следует разделить следующим образом: 100% - 4% margin = 96%. Далее 96%/3= 32% - получаем width каждой колонки. Затем используем это для свойств наших колонок с классом .col
:
1 2 3 4 5 6 7 8 9 |
.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 и давно уже поддерживается современными браузерами. Важным моментом в ее использовании является установка пробелов ДО и ПОСЛЕ знака минус:
1 2 3 4 5 6 7 8 |
.col { display: inline-block; width: calc(32% - 3px); margin-right: 2%; margin-bottom: 20px; padding: 0 15px; background-color: #fff; } |
Результат уже намного лучше:
Для того чтобы колонки с разным количеством текста не выбивались из одной линии, необходимо использовать свойство vertical-align
чаще всего со значением top
. Добавим его к нашим css-свойствам:
1 2 3 4 5 6 7 8 9 |
.col { display: inline-block; vertical-align: top; width: calc(32% - 3px); margin-right: 2%; margin-bottom: 20px; padding: 0 15px; background-color: #fff; } |
В результате получим колонки разной высоты, но выровненные по верхней линии:
Если в блоке я напишу так:
link
...
и поставлю для блока text-align: center, то ссылка и список станут по центру, хотя ссылка - это inline-элемент, а список - блочный. Почему так?
Дело в том, что в любом блочном элементе (список в вашем примере), для которого задан
text-align: center
, текст будет выравниваться по центру. Именно это вы и видите. Если элемент, которому заданdisplay: block
, нетекстовый - картинка, например, тоtext-align: center
для родительского элемента никакого влияния на вложенный элемент не окажет.Пробуйте сами: ссылка на codepen.io.
Спасибо. Все очень понятно расписано