Мистический 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>Пример 2: display: inline-flex
<div></div>
<div></div>
<div></div>
</div>
<div>
<div></div>
<div></div>
<div></div>
</div>
<div>
<div></div>
<div></div>
<div></div>
</div>
К трем контейнерам в синем цвете применяем 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-block | block | |
inline-table | table | table-row-group |
table-header-group | ||
table-footer-group | ||
table-row | ||
table-cell | ||
table-column-group | ||
table-column | ||
table-caption | ||
inline-flex | flex | |
inline-grid | grid | |
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-row
, не просто ведет себя как ячейка, но и «превращает в ячейки» (точнее, вынуждает оборачиваться в анонимные table-cell
’ы) своих соседей c «обычными» значениями display
. А та же table-cell
среди обычных блоков лишь тихо «завернется» в анонимные table-row и table, и будет вести себя как простая таблица из одной ячейки. Особняком стоит экзотический зверек run-in
(тоже с непростой судьбой ― его следы в спецификациях тянутся еще с 1998 г., с CSS2.0, то исчезая, то появляясь вновь, при этом его никогда не поддерживал Firefox, а недавно его поддержку убрал Хром). По факту это инлайн, который иногда умеет «вбегать» внутрь… следующего за ним блока. Вряд ли вам часто доведется с ним сталкиваться (хотя оно здорово упростило бы решение задач типа этой, а также иногда используется для так называемых «заголовков в подбор»), но, по-моему, в третий столбец оно попало не зря.
Итого, три столбца поделили наши значения display
по тому, как они влияют на соседей элемента:
- Участники инлайнового контекста (все, начинающиеся на
inline
, и примкнувший к нимruby
). Оказавшись среди текста, встраиваются в него. - Участники блочного контекста (все значения без дефиса за вычетом
none
,inline
иruby
, но с добавлениемlist-item
). Оказавшись среди текста, разбивают его в анонимные блоки. - Ни то ни другое. На соседей не влияет (
none
), либо поведение зависит от внешнего контекста (table-*
,ruby-*
) или каких-то других, но тоже внешних, условий (run-in
).
А что мы видим в строках? Во-первых, бросаются в глаза пары вида «нечто» — «inline-нечто». Практически у каждого «снаружи-блочного» типа отображения есть его «снаружи-инлайновый» напарник! Элементы с display из этих пар ведут себя совершенно одинаково внутри ― задают один и тот же тип форматирования своему содержимому, одинаковым образом (при прочих равных) выстраивают своих потомков. Единственное исключение ― самый обычный
, отличающийся от инлайн-блока нюансами наследования родительской ширины и поведения 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. Сделайте родителем гибкий контейнер.
Это делает ваши элементы гибкими элементами, что деактивирует
вертикальное выравнивание
, поскольку гибкие элементы являются элементами уровня блока.