Display inline flex: Мистический inline-flex и что он делает | by Stas Bagretsov

Мистический inline-flex и что он делает | by Stas Bagretsov

Это очень редко используемое свойство в CSS Flexbox и про него в принципе мало чего написано. Но это не беда. В этой статье вы узнаете о том, что же такое display:inline-flex и какие преимущества он даёт при вёрстке, а также поймете его отличия отdisplay: flex.

👉Мой Твиттер — там много из мира фронтенда, да и вообще поговорим🖖. Подписывайтесь, будет интересно: ) ✈️

Перевод двух статей:

I Used CSS Inline Flex For The First Time

И

display: flex vs display: inline-flex

Как фронт-энд разработчик, я регулярно использую свойство CSS display в своей ежедневной работе. Я могу использовать block, grid или flex, как его значения.

Во время работы над проектом мне был нужен flex-контейнер, который в тот же момент был бы ещё и инлайновым. Другими словами, мне нужно было, чтобы контент внутри контейнера был флексовым, но сам контейнер вёл бы себя как инлайновый элемент.

Хорошо, что я вспомнил о display: inline-flex. Никогда его до этого не использовал, но всегда видел его в DevTools браузера.

Итак, давайте посмотрим на дизайн, который мне нужно было сверстать:

У каждого бэджа есть своя уникальная иконка, отцентрированная внутри горизонтально и вертикально. Центрирование, как вы уже наверное поняли, происходит с помощью Flexbox и все бэджи стоят в ряд, так как к ним применено display: inline-flex.

HTML:

<div>
<div>
<svg>..</svg>
</div>
<div>
<svg>..</svg>
</div>
<!-- другие бэджи -->
</div>

Для уточнения, врапер .badges-list ничего не делает для инлайнового позиционирования элементов. Так происходит, потому что на его потомке .c-badge применяется inline-flex.

CSS:

.c-badge {
display: inline-flex;
justify-content: center;
align-items: center;
}

Ну и конечно же демка:

В чем тут разница?

Пример 1: display: flex

У трёх контейнеров с display: flex синий цвет, в них есть три потомка div’а, отмеченные красным цветом и имеющие flex: 1.

Каждый родительский контейнер находится на своей строке. А трое потомков занимают равную ширину.

$flexColor: #64B5F6;
$inlineColor: #F06292;.container--inline-flex,
.container--flex {
background-color: $flexColor;
margin-bottom: 10px; /* для эстетичности*/
}
.container--flex {
display: flex;
}

.flex-child {
flex: 1;
min-width: 50px;
min-height: 50px;
margin: 10px;
background-color: $inlineColor;
}.flex-color {
color: $flexColor;
}
.inline-color {
color: $inlineColor;
}/* Визуальный CSS */
body {
font-family: 'Open Sans', sans-serif;
}
code {
background-color: #EEEEEE;
padding: 1px 5px;
}

HTML:

<div>
<div></div>
<div></div>
<div></div>
</div>
<div>
<div></div>
<div></div>
<div></div>
</div>
<div>
<div></div>
<div></div>
<div></div>
</div>

Пример 2: display: inline-flex

К трем контейнерам в синем цвете применяем display: inline-flex, в них есть три потомка div’а, которые в красном цвете имеют flex:1 и min-width: 50px.

Каждый родительский контейнер стоит сразу за другим, потому что они могут уместиться в один ряд. Ширина родительского контейнера зависит от размера потомков, которым тут был выставлен min-width в 50px.

CSS, но уже с inline-flex:

.container--inline-flex {
display: inline-flex;
}

HTML:

<div>
<div></div>
<div></div>
<div></div>
</div>
<div>
<div></div>
<div></div>
<div></div>
</div>
<div>
<div></div>
<div></div>
<div></div>
</div>

Объясняем примеры

Элемент с display:flex очень схож с элементом, на котором стоит display: block, потому что он забирает сразу всю строку. Однако, в сравнении с представленными до этого свойствами позиционирования, его потомки могут быть размещены в контейнере куда более гибко и динамично, нежели это было возможно ранее.

Если мы изменим display: flex на display: inline-flex:

Родительский контейнер будет показываться инлайново.

К потомкам могут быть применены все flex-свойства, разницы с display: flex в этом плане совсем не будет.

В общем, это означает то, что если элементы потомки не слишком велики, то два контейнера с display: inline-flex могут идти бок о бок в одной строке.

У других display свойств тоже есть свои инлайновые близнецы:

У block есть inline-block

У table есть inline-table

И даже у grid есть inline-grid

Больше про CSS Flex и его свойства вы можете прочитать в статье — Вёрстка на Flexbox в CSS. Полный справочник

CSS-свойство display и контексты форматирования — CSS-LIVE

Я давно собирался написать эту статью, но на прошлой неделе W3C дал замечательный повод… впрочем, обо всём по порядку. Кстати, спецификации W3C зря считают скучными: порой они могут дать фору любому детективу. В хорошем детективе всё выясняется лишь на последней странице. Но бывало ли, чтобы ключевая деталь детектива ― например, что злодеев было не двое, а трое ― раскрывалась вообще не в тексте, а… в списке найденных опечаток, на отдельном листке, вклеенном в книгу?

Так вот, в спецификациях W3C бывает еще и не такое. Например, всем нам знакомая спецификация CSS2.1: уже три года как она в статусе рекомендации, по идее, никаких изменений в ней быть не должно. Как вы думаете, сколько в этой спецификации описано наших любимых контекстов форматирования: два ― инлайновый и блочный? А вот и нет: три! Через год после «совсем-совсем-окончательного» утверждения спецификации ее авторы внезапно поняли, что на самом деле в ней описан еще один, ни на что не похожий, контекст форматирования ― табличный. Но поскольку менять окончательно утвержденную спецификацию по правилам игры нельзя, то единственное, куда можно было внести изменение ― список замеченных ошибок (errata). Так что внимательно читайте спецификации, и не только основной текст, но и добавочные ссылки! Кстати, кто пройдет квест на внимательность в оглавлении этой самой спецификации и найдет ее «секретный уровень» с одной загадочной фразой?

Но хватит вступлений, пора переходить к нашей первой теме, и это…

Контексты форматирования в CSS

Итак, какие они вообще бывают, по состоянию на середину-конец 2014 года?

Из старых:

Инлайновый

Самый простой на первый взгляд, бездонный, если копнуть чуть глубже. Самый важный, поскольку ведает представлением того, что составляет основу веба ― текста и всего того, что дает этому тексту гордую приставку «гипер-»: картинок, ссылок, элементов форм, видео и прочих медиаобъектов…

Блочный

На первый взгляд еще проще инлайнового. Тоже самый важный, т.к. ведает размещением и оформлением блоков контента. В нем же «плавают» float-ы.

Табличный

Определяет поведение табличных элементов в их иерархии ― ячейки в строках, строки в группах, заголовки таблиц где-то рядом, всё это вместе в некой обертке особого типа и т. д. Недостающие по иерархии элементы заменяются анонимными боксами-«призраками» (чуть подробнее о них здесь).

И из новых:

Флексбоксовый

О флексбоксах и их непростой судьбе мы говорили уже давно, с тех пор появилось много хороших руководств по ним (1, 2, 3, 4) и многие успели опробовать их прелести. Одни особенности роднят их с блоками, другие (пропорциональное растягивание) ― с таблицами, третьи (многострочность) ― с инлайн-боксами. У флексбоксового контекста есть еще одна особенность, но о ней чуть позже.

Гридовый (сеточный)

Гриды (сеточная раскладка) ― еще один CSS-модуль, предназначенный специально для создания макетов, тоже с запутанной родословной и противоречивой репутацией. На момент написания статьи был не так популярен, как флексбоксы, поскольку был готов к использованию лишь в одном браузере (на удивленIE), но всё меняется. Одна особенность роднит его с предыдущим.

Контекст форматирования Ruby

Что такое «Ruby-аннотации», вы можете узнать из статьи о соотв. элементах HTML5. В CSS для них тоже есть свой модуль… и больше знать о нем пока нам, пожалуй, незачем (шутка: знания лишними не бывают).

Еще?

Есть ли еще контексты форматирования? Беглый поиск по разделу со спецификациями их не находит. Но, судя по детективно-табличной истории, даже сами авторы спецификаций могут до поры этого не знать!:) Возможно, именно вы сможете найти в какой-нибудь из затерянных спецификаций диковинного «зверя», о котором не знали сами члены W3C, так что удачной вам «охоты»!

Всё сразу одной таблицей (для наглядности)

КФДля чего нужен«Участники»Важные особенностиСсылки на стандарт
ИнлайновыйФорматирование текста и всего, что находится прямо в немЭлементы строки (текст, картинки, кнопки, инлайн-блоки, инлайн-таблицы и т.д.)Всё «воспринимается как текст», напр., пробелы в коде часто отображаются как символы. Сложные правила вертикального выравнивания.CSS1
CSS2.1
CSS Text 3
БлочныйОформление блоков текста (с отступами и врезками)Блочные боксы (в т.ч. анонимные), float-ы«Схлопывание» margin-ов, «проваливание» float-ов через верхние и нижние границы блоков, влияние float-ов в пределах контекста друг на друга. Не-блочные элементы неявно оборачиваются в анонимные блоки. Мало средств для выравнивания/центрирования по вертикали.CSS1
CSS2.1
ТабличныйПредставление табличных и «таблицеподобных» данных, изредка полезен и для раскладки блоковЯчейки, строки, группы строк (как thead/tbody/etc.) и всё такое, в т.ч. анонимныеИерархия табличной структуры (в строке могут быть только ячейки и т.п.), для недостающих элементов иерархии создаются анонимные обертки соотв. типа. Сложные и плохо документированные алгоритмы расчета размеровСписок ошибок (errata) к CSS2. 1
CSS Tables 3 (работа идет, но еле-еле)
Флексовый«Гибкая» раскладка и взаимное выравнивание блоков с контентом, в т.ч. для динамичных и адаптивных макетов и их частейФлекс-элементы (во флекс-контейнере)Меняет поведение непосредственных потомков элемента, задающего этот контекст. В частности, свойство float игнорируется. Создает анонимные флекс-обертки для текста, оказавшегося непосредственно в контейнере. CSS Flexbox 1
Для истории:
Flexbox 2011
Flexbox 2009
Гридовый (сеточный)Расположение блоков в соответствии с заданным «каркасом» страницы или интерфейсаГрид-элементы (в грид-контейнере)Практически полная независимость порядка отображения элементов от порядка в коде. Элементы могут влиять друг на друга сразу по двум направлениям. Создает анонимные грид-обертки для текста, оказавшегося непосредственно в контейнере.CSS Grid 1
RubyПодсказки для чтения текста иероглифамиИероглифы основного текста и ruby-подсказки к немуВряд ли встретится вам, если вы не будете верстать учебники китайского или японского… но кто знает!CSS Ruby 1

Контексты, но не форматирования

Слово «контекст» вообще часто звучит в веб-фронтендных разговорах, напр.

, про JS или Canvas. Но и в контексте (простите за каламбур) CSS его применение не ограничено контекстом (ой, опять…) контекстов форматирования, так что у многих с этим словом возникает путаница ― совсем как у меня в этой фразе. Например, контекст наложения (stacking context) ― ключевое понятие для понимания свойства z-index. У него много неочевидных нюансов, о которых написаны целые статьи (1, 2). Но к контекстам форматирования он отношения не имеет. Поэтому, услышав фразу типа «такое-то свойство создает контекст», на всякий случай уточняйте, о контексте чего идет речь!

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

Display, наш старый знакомый

Уж что-что, а это свойство знакомо каждому новичку! Мы каждый день используем его, чтобы показывать и скрывать элементы. Мы играючи меняем одно значение на другое, как по волшебству превращая вертикальные меню в горизонтальные и наоборот. Мы знаем, что смена display не влияет на парсинг элемента в DOM и не превращает один элемент в другой на самом деле, не скрывает контент от поисковиков, не влияет на семантику элемента (за редкими исключениями) ― словом, делает ровно то, что вытекает из его названия: меняет отображение.

А теперь померяемся эрудициями: сколько значений этого свойства вы можете назвать сходу? Хотя бы штук 16 (именно столько их было в CSS2.1) вспомнили?

А теперь запишем то, что вспомнили и нагуглили, вот в таком виде:

«Периодическая таблица» значений

display
  none
inline  
inline-blockblock 
inline-tabletabletable-row-group
table-header-group
table-footer-group
table-row
table-cell
table-column-group
table-column
table-caption
inline-flexflex 
inline-gridgrid 
ruby ruby-base
ruby-text
ruby-base-container
ruby-text-container
 list-item 
  run-in

Видно, что значения четко делятся минимум на два типа: с дефисом и без.

У некоторых свойств без дефиса есть «партнер» с дефисом, а то и куча их, причем дефис бывает и справа, и слева. Это не случайно.

Рассмотрим столбцы таблицы. В первом столбце все свойства, кроме ruby, начинаются с inline. И элементы с такими значениями display ведут себя как элементы строки ― пытаются встроиться в строку окружающего текста, сохраняют пробелы в коде вокруг себя, подчиняются свойству vertical-align, т.е. живут в инлайновом контексте форматирования, по его законам.

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

margin-ы схлопываются с соседями, и самое главное ― они диктуют своему окружению, чтобы оно тоже было блочным. Если рядом с элементом с таким display случайно окажется какой-то «голый» инлайновый контент, то строгий рендерер браузера тотчас же велит этому нарушителю «одеться» в анонимную блочную обертку (с инлайновым контекстом внутри), чтобы почтенному блоку не приходилось стыдиться такого соседства:). Может, логичнее было бы назвать эти значения «block-table», «block-flex» и т.д.? Впрочем, принцип и так ясен, запомнить легко.

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

table-cell, оказавшись внутри table-row, не просто ведет себя как ячейка, но и «превращает в ячейки» (точнее, вынуждает оборачиваться в анонимные table-cell’ы) своих соседей c «обычными» значениями display. А та же table-cell среди обычных блоков лишь тихо «завернется» в анонимные table-row и table, и будет вести себя как простая таблица из одной ячейки. Особняком стоит экзотический зверек run-in (тоже с непростой судьбой ― его следы в спецификациях тянутся еще с 1998 г., с CSS2.0, то исчезая, то появляясь вновь, при этом его никогда не поддерживал Firefox, а недавно его поддержку убрал Хром). По факту это инлайн, который иногда умеет «вбегать» внутрь… следующего за ним блока. Вряд ли вам часто доведется с ним сталкиваться (хотя оно здорово упростило бы решение задач типа этой, а также иногда используется для так называемых «заголовков в подбор»), но, по-моему, в третий столбец оно попало не зря.

Итого, три столбца поделили наши значения display по тому, как они влияют на соседей элемента:

  1. Участники инлайнового контекста (все, начинающиеся на inline, и примкнувший к ним ruby). Оказавшись среди текста, встраиваются в него.
  2. Участники блочного контекста (все значения без дефиса за вычетом none, inline и ruby, но с добавлением list-item). Оказавшись среди текста, разбивают его в анонимные блоки.
  3. Ни то ни другое. На соседей не влияет (none), либо поведение зависит от внешнего контекста (table-*, ruby-*) или каких-то других, но тоже внешних, условий (run-in).

А что мы видим в строках? Во-первых, бросаются в глаза пары вида «нечто» — «inline-нечто». Практически у каждого «снаружи-блочного» типа отображения есть его «снаружи-инлайновый» напарник! Элементы с display из этих пар ведут себя совершенно одинаково внутри ― задают один и тот же тип форматирования своему содержимому, одинаковым образом (при прочих равных) выстраивают своих потомков. Единственное исключение ― самый обычный

block, отличающийся от инлайн-блока нюансами наследования родительской ширины и поведения margin-ов с float-ами. К объяснению этого исключения мы вот-вот подойдем, а пока посмотрим, что связывает оставшиеся соседние по горизонтали клетки нашей таблицы. Мы сразу видим две группы вида «нечто» — «нечто-поменьше», причем второго может быть целая куча, оно может подразделяться на «нечто-еще-меньше» и т.д. Причем для тех значений, которые задают для своих потомков контексты форматирования с особыми правилами, и те в зависимости от этих правил могут вести себя по-разному… по причине чего и оказались у нас в третьем столбце:)

А вот у (inline-)flex и (inline-)grid таких «производных» значений нет. Помните, мы упоминали, что у флексбоксового и сеточного контекстов есть загадочная особенность? И вот в чем она: эти контексты форматирования влияют на отображение своих непосредственных участников напрямую. Кто бы ни попал в контейнер с display:flex ― блок, инлайн-блок или другой flex-контейнер ― флексовый контекст форматирования их всех уравняет. И выровняет (если у него заданы правила для выравнивания). Не разбирая, кто был строчным, кто блочным. Правда, только снаружи: внутри они останутся такими, какими были ― блочными, табличными, флексовыми и т.

д. «Магия» этих новых раскладочных контекстов сильна (попробуйте и убедитесь!), но на «внуков» элемента-контейнера она уже не распространяется.

Наконец, в нашей таблице остались пустые клетки. Например, те, которым могли бы соответствовать значения inline-list-item и (условно) block-ruby. Со вторым еще ладно: ruby-аннотации нужны для текста, а не для блоков, да и то изредка. Но перечисления и нумерации в самом тексте встречаются сплошь и рядом, так что первый вариант был бы не лишним, правда?

Display

плавающих и позиционированных элементов

Говоря о display, стоит вспомнить свойства float и position:absolute/fixed, которые умеют «переопределять» указанное значение display, часто вызывая путаницу. Алгоритм этого описан в спецификации CSS2.1 (к счастью, на этот раз в тексте, а не списке опечаток:). Какие закономерности, вдобавок к только что найденным, мы видим там?

Во-первых, очевидно, none «забарывает» всех, «обнуляя» прочие визуальные свойства (аналогия с умножением на ноль). Во-вторых, эти свойства начисто почти начисто (см. уточнение в комментариях) «срубают» частицу «inline-», если она была ― что тоже логично: и плавающие, и абсолютно позиционированные элементы вырваны из потока, а значит, лишены связи с текстом, в который могли бы встроиться, и «внешняя инлайновость» для них утратила смысл. В-третьих, элемент так же вырывается из «экзотических» контекстов вроде табличного, а значит, и особые табличные правила для него тоже теряют смысл. И что остается элементу, если он не может быть ни inline-чем-либо, ни частью таблицы? Только старый добрый block. Поэтому для плавающих блоков и абсолютно позиционированных элементов display можно и не задавать ― без него им не стать ничем, кроме блока.

Блок в блоке: исключительность в обычности

Уже дважды нам пришлось упомянуть, что самый скучный, казалось бы, display:block оказывался чем-то особенным. Пора присмотреться к нему поближе. Но сначала присмотримся поближе к остальным свойствам, которых мы только что рассортировали.

Например, все inline-*ruby). Они сами живут в инлайновом контексте, а внутри у них ― разные другие контексты форматирования. Та же история с table, flex и grid, только живут они в блочном. У table-* выстраивается вся «матрешка» табличной модели (в табличном контексте, если нужно ― через анонимные обертки), а внутри самой внутренней table-cell размещаются обычные блоки с текстом, т.е. контекст в ней блочный.

Получается, что почти все значения display являются своего рода «переходниками» между контекстами форматирования: сами находятся в одном, а внутри у них другой!

И только бедняга block (и еще list-item… но до него еще доберемся) ничем таким не выделяется. Он и снаружи блочный, и внутри блочный ― насквозь блочный. Сам живет в блочном контексте и продолжает этот же контекст внутрь себя, без перемен.

Вот почему таблицы (и их «запчасти»), инлайн-блоки, потомки флекс-контейнеров, а также «блоки поневоле» ― float-ы и абсолютно позиционированные ― создают блочный контекст форматирования автоматически. Собственно, у них-то и выбора нет, создавать или не создавать. А вот у обычного блока есть возможность «продолжить» существующий. Вот он по умолчанию и делает, как проще ― продолжает. И поэтому остается подвержен влиянию float-ов и cхлопывающихся margin-ов не только внутри себя, но и снаружи ― ведь форматирование блоков текста в одном блочном контексте идет по общим сквозным правилам, ведь CSS изначально создавался именно для оформления сплошных потоков текста. И никакие clear- и подобные -фиксы ничего не могли с этим поделать.

Так «типичность» значения block оказалась его исключительной особенностью. Хотя изначально «так и задумывалось», сегодня она часто мешает, и приходится «силой» заставлять его создавать отдельный контекст. Чаще всего через overflow, который тоже в какой-то мере выделяет (хоть и не вырывает) блок из потока и «обносит жестким забором» по периметру. И у всех способов свои издержки (хотя есть призрачная надежда на появление стандартного). Впрочем, с новыми механизмами раскладки ― теми же флексбоками ― необходимость «мучить» старичка block станет не такой частой. (Добавлено 10.02.2017: стандартное решение появилось!)

Один

display ― два бокса?

Значение list-item уникально умением создавать два бокса вместо одного: в дополнение к основному блочному ― еще и специальный бокс для маркера (если таковой задан в свойствах списка). Но вот что такое этот бокс маркера, куда его засунуть (кроме как внутрь текста) и вообще что с ним можно сделать ― спецификация рассказать «забыла». Поэтому отображение маркеров отдано на откуп браузерам и управлять им почти не удается. И годами нам то и дело приходилось вообще убирать эти маркеры и делать свои, либо фоном, либо псевдоэлементами ::before.

Но если бы этим маркером можно было удобно управлять, да использовать те же ::before/::after в дополнение к нему ― кто бы отказался? Да и возможность добавить какой-никакой бокс «на халяву» и к инлайновому элементу бы порой не помешала…

А теперь всем, кто дочитал до этого места ― огромный сюрприз от W3C!

Сюрприз вышел всего неделю назад, и называется эта спецификация CSS Display Module. 3-го уровня, т.к. расширяет определение свойства display из CSS2.1. Это еще первый черновик, но черновик интересный.

Во-первых, отдельных значений display в нем стало больше, чуть ли не три десятка. И среди них появился предсказанный нашей «периодической таблицей» inline-list-item. Более того, маркер списка стал полноценным псевдоэлементом ::marker ― и значит, мы сможем (если верить другой спецификации) управлять им с помощью всего CSS-арсенала, который у нас есть. Фактически, мы наконец получим второй ::before!

Но эта новость меркнет перед следующей. По новой спецификации, мы сможем управлять поведением элементов снаружи (относительно соседей) и внутри (относительно потомков) независимо ― с помощью отдельных свойств display-outside и display-inside соответственно. А наш «обычный display» превратился в сокращенную запись для этих свойств (и еще одного, display-list, как раз отвечающего за дополнительные маркеры для элементов списка).

(Добавлено 30.12.2015: предыдущий абзац описывает, как было дело в первом черновике, на момент публикации статьи. В текущей версии спецификации от отдельных свойств display-inside и display-outside отказались, но значение обычного display сделали составным, и смысл его половинок тот же, что у бывших отдельных свойств — поведение бокса снаружи и внутри. Так что общий принцип по-прежнему верен.)

А ведь это значит, что мы теперь сможем сами создавать любые «кирпичики» для наших страниц, не только соответствующие любой клетке «периодической таблицы», но и ранее вообще невиданные! Например, ячейки таблицы с флексбоксами внутри, минуя (анонимную) блочную обертку. Или тот же блочный ruby-контейнер (как говорится, «не для науки, а просто поглазеть»). Или упростить структуру вложенной таблицы, придав «наружной стороне» внутренней таблицы свойства ячейки внешней (по идее, она автоматом подхватит ее высоту, и у нас, фактически, наконец появится rowspan/colspan для CSS-таблиц похоже, с таблицами по актуальной спецификации всё-таки не получится, но вот в контексте гридов это будет можно). Конечно, не все комбинации имеют смысл (например, делать бокс с наружными свойствами «table-row» и не помещать его в табличный контекст толку мало ― он всё равно обернется в анонимные обертки и управлять им будет трудно), но решение множества задач верстки станет намного проще. А главное ― многие «странности» поведения элементов, у которых «вершки» в одном контексте форматирования, а «корешки» ― в другом, станут наконец понятны интуитивно.

Ну а каким внутреннему и наружному отображениям соответствует каждое из наших привычных однословных значений display, я думаю, вы теперь легко догадаетесь с помощью «периодической таблицы», не заглядывая в новую спецификацию:). Но лучше загляните ― наверняка вы найдете в ней еще немало сюрпризов.

Ведь спецификации CSS порой увлекательнее детективов!

P.S. Это тоже может быть интересно:

css — В чем разница между display:inline-flex и display:flex?

Я хотел бы добавить некоторые подробности о поведении программы чтения с экрана, потому что здесь есть некоторые сюрпризы.

Сначала предыстория. Некоторые программы чтения с экрана, такие как NVDA, обрабатывают display: block и display: inline-block по-разному (и они должны, как вы увидите позже).

Сравнение различных атрибутов отображения

отображение: блок

Дисплей : элемент блока всегда будет объявляться в отдельной «строке», что означает, что NVDA перестанет говорить после его содержимого, и пользователь вручную скажет NVDA объявить следующий элемент (обычно с помощью клавиши со стрелкой вниз ) .

 
Это первая строка
Это другая строка

Это заставит NVDA объявить Это первая строка , а затем Это еще одна строка .

Следующее дает тот же результат:

 Это первая строка
Это другая строка
 

display: inline-block

A display: inline-block Элемент будет объявлен вместе со всеми предшествующими и последующими другими строчными элементами ( display: inline и display: inline-block ).

 Это первая строка
Это другая строка
 

Это заставит программу чтения с экрана объявлять оба элемента одновременно: Это первая строка Это еще одна строка .

Как было сказано ранее, не имеет значения, является ли это элементом inline или inline-block ; следующий результат дает точно такой же результат:

 Это первая строка 
Это другая строка 
 

display: flex

Это работает точно так же, как display: block .

display: inline-flex

Удивительно, но этот также работает как display: block , не как display: inline-block !

display: grid / display: inline-grid

Я не проверял это, но я ожидаю того же, что и с flex / inline-flex здесь.

Почему это проблема?

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

Например, рассмотрим следующий заголовок на онлайн-платформе новостей:

 

Дождевые леса Им нужна наша любовь

Теперь вы хотите визуально стилизовать категорию ( Тропические леса ), сильно отличающуюся от «настоящего» названия («Им нужна наша любовь»), т. е. поместив каждую в отдельную строку, примерно так:

Если бы вы сделали категорию элементом display: block , тогда программа чтения с экрана объявила бы заголовок в двух отдельных строках, например: Тропические леса, уровень заголовка 2 , затем Им нужна наша любовь, уровень заголовка 2 . Это сбивает пользователя с толку: на странице два разных заголовка? Почему нет содержания для первого (вместо этого, кажется, сразу следует второй заголовок)?

Однако если вы сделаете категорию display: inline-block element, то программа чтения с экрана объявит заголовок сразу: Тропические леса Им нужна наша любовь, уровень заголовка 2 .

Печально, что display: inline-flex (и, возможно, inline-grid тоже) не имитирует поведение. Поэтому, если вы хотите предложить идеальную доступность, вы можете использовать встроенный блок в таких ситуациях.

html — Элемент с «display: inline-flex» имеет странное верхнее поле

С display: inline-flex вы имеете дело с элементами встроенного уровня.

Это активирует свойство вертикального выравнивания , которое применяется только к элементам встроенного уровня и элементам таблицы (источник).

Начальное значение vertical-align равно baseline . Это означает, что элементы встроенного уровня располагаются вертикально для достижения выравнивания базовой линии (текста).

базовый уровень

Базовая линия — это линия, на которой расположено большинство букв и ниже которой проходят выносные элементы.

Источник: Wikipedia.org

Это ваша текущая структура кода с добавленным вами текстом:

 .userImg {
  дисплей: встроенный гибкий;
  высота: 3см;
  ширина: 3em;
  фон: красный;
}

.nameOfUser {
  дисплей: встроенный гибкий;
  высота: 3см;
  ширина: 10см;
  фон: цвет морской волны;
} 
 <дел>
<дел>
   

Джексон Кросмас

Второй элемент смещается вниз, чтобы выровняться с текущей базовой линией первого элемента.

Теперь добавьте текст к первому элементу:

 .userImg {
  дисплей: встроенный гибкий;
  высота: 3см;
  ширина: 3em;
  фон: красный;
}

.nameOfUser {
  дисплей: встроенный гибкий;
  высота: 3см;
  ширина: 10см;
  фон: цвет морской волны;
} 
 
текст

Джексон Кросмас

Обратите внимание, как смещаются базовые линии для выравнивания.

Элементы по-прежнему не выровнены под прямым углом, потому что h4 имеет вертикальные поля по умолчанию. Если убрать поля:

 .userImg {
  дисплей: встроенный гибкий;
  высота: 3см;
  ширина: 3em;
  фон: красный;
}

.nameOfUser {
  дисплей: встроенный гибкий;
  высота: 3см;
  ширина: 10см;
  фон: цвет морской волны;
}

h4 {поле: 0; } 
 
текст

Джексон Кросмас


Вот два быстрых решения :

1. Переопределите значение по умолчанию vertical-align на любое другое значение.

 .userImg {
  дисплей: встроенный гибкий;
  высота: 3см;
  ширина: 3em;
  фон: красный;
}

.nameOfUser {
  дисплей: встроенный гибкий;
  высота: 3см;
  ширина: 10см;
  фон: цвет морской волны;
}

div { вертикальное выравнивание: сверху; } 
 

Джексон Кросмас

2. Сделайте родителем гибкий контейнер.

Это делает ваши элементы гибкими элементами, что деактивирует вертикальное выравнивание , поскольку гибкие элементы являются элементами уровня блока.