Копание в свойстве отображения: два значения отображения
Опубликовано: 2022-03-10display
, рабочей лошадкой свойства, которому не уделяется много внимания. Рэйчел Эндрю лучше выглядит в коротком сериале. Макет Flex или Grid начинается с объявления display: flex
или display: grid
. Эти методы макета являются значениями свойства display
CSS. Мы склонны не слишком много говорить об этом свойстве отдельно, вместо этого концентрируясь на значениях flex
или grid
, однако есть некоторые интересные вещи, которые нужно понять о display
и о том, как оно определяется, что значительно облегчит вашу жизнь при использовании. CSS для макета.
В этой статье, первой из короткой серии, я рассмотрю способ определения значений display
в спецификации уровня 3. Это изменение того, как мы определяли display
в более ранних версиях CSS. Хотя поначалу это может показаться необычным для тех из нас, кто много лет занимался CSS, я думаю, что эти изменения действительно помогают объяснить, что происходит, когда мы меняем значение display
для элемента.
Блочные и встроенные элементы
Одной из первых вещей, которым мы учим новичков в CSS, является концепция блочных и встроенных элементов. Объясним, что некоторые элементы на странице являются display: block
и из-за этого имеют определенные особенности. Они растягиваются в линейном направлении, занимая столько места, сколько им доступно. Они переходят на новую строку; мы можем задать им ширину, высоту, поля, а также отступы, и эти свойства оттолкнут от них другие элементы на странице.
Мы также знаем, что некоторые элементы являются display: inline
. Строчные элементы похожи на слова в предложении; они не переходят на новую строку, а вместо этого оставляют между собой символ пробела. Если вы добавите поля и отступы, это будет отображаться, но не будет отталкивать другие элементы.
Поведение блочных и встроенных элементов является фундаментальным для CSS, и тот факт, что правильно размеченный HTML-документ будет читабельным по умолчанию. Этот макет называется «блочным и встроенным макетом» или «нормальным потоком», потому что именно так элементы располагаются сами по себе, если мы не делаем с ними ничего другого.
Внутренние и внешние значения display
Мы понимаем блочные и встроенные элементы, но что произойдет, если мы сделаем элемент display: grid
? Это что-то совсем другое? Если мы посмотрим на компонент, для которого мы указали display: grid
, с точки зрения родительского элемента в макете он ведет себя как элемент block level
. Элемент будет растягиваться и занимать столько места во встроенном измерении, сколько доступно, он будет начинаться с новой строки. Он ведет себя точно так же, как элемент block
с точки зрения того, как он ведет себя вместе с остальной частью макета. Мы не сказали display: block
, хотя?
Оказывается, у нас есть. На уровне 3 спецификации Display значение display
определяется как два ключевых слова. Эти ключевые слова определяют внешнее значение отображения, которое будет inline
или block
и, следовательно, определяют, как элемент ведет себя в макете вместе с другими элементами. Они также определяют внутреннее значение элемента — или то, как ведут себя непосредственные дочерние элементы этого элемента.
Это означает, что когда вы говорите display: grid
, на самом деле вы говорите display: block grid
. Вы запрашиваете контейнер сетки на уровне блока. Элемент, который будет иметь все атрибуты блока — вы можете задать ему высоту и ширину, поля и отступы, и он будет растягиваться, чтобы заполнить контейнер. Однако дочерним элементам этого контейнера было присвоено внутреннее значение grid
, поэтому они становятся элементами сетки. То, как ведут себя эти элементы сетки, определено в спецификации CSS Grid: спецификация display
дает нам способ сообщить браузеру, что это метод макета, который мы хотим использовать.
Я думаю, что такое представление об display
невероятно полезно; это напрямую объясняет, что мы делаем с различными методами компоновки. Если бы вы указали display: inline flex
, чего бы вы ожидали? Надеюсь, блок, который ведет себя как встроенный элемент, с дочерними элементами, которые являются гибкими элементами.
Есть несколько других вещей, которые аккуратно объясняются этим новым взглядом на display
, и я рассмотрю некоторые из них в оставшейся части этой статьи.
Мы всегда возвращаемся к нормальному потоку
Размышляя об этих внутренних и внешних свойствах отображения, может быть полезно подумать о том, что произойдет, если мы вообще не возимся со значением отображения. Если вы напишете HTML-код и просмотрите его в браузере, вы получите блочный и встроенный макет или обычный поток. Элементы отображаются как block
или inline
элементы.
В приведенном ниже примере содержится некоторая разметка, которую я превратил в медиа-объект, сделав div
display: flex
(два прямых дочерних элемента) теперь гибкими элементами, поэтому изображение теперь находится в строке с содержимым. Однако, если вы видите в содержании, есть заголовок и абзац, которые снова отображаются в обычном порядке. Прямые дочерние элементы медиа-объекта стали гибкими элементами; их дочерние элементы возвращаются к нормальному потоку, если мы не изменим значение display на элементе flex. Flex-контейнер сам по себе представляет собой блочный блок, как вы можете видеть по тому факту, что граница простирается до края его родителя.
Если вы работаете с этим процессом, тот факт, что элементы на вашей странице будут располагаться с помощью этого приятного читаемого нормального макета потока, а не бороться с ним и пытаться разместить все, CSS намного проще. У вас также меньше шансов столкнуться с проблемами доступности, поскольку вы работаете с порядком документов, что и делает программа чтения с экрана или человек, пролистывающий документ.
Объяснение flow-root
и inline-block
Значение inline-block
также, вероятно, знакомо многим из нас, кто какое-то время занимался CSS. Это значение — способ получить некоторое поведение блока для inline
элемента. Например, элемент inline-block
может иметь ширину и высоту. Элемент с display: inline-block
также ведет себя интересным образом, поскольку он создает блокировку B для форматирования содержимого ( BFC ).
BFC делает некоторые полезные вещи с точки зрения макета, например, он содержит числа с плавающей запятой. Подробнее о контекстах блочного форматирования см. в моей предыдущей статье «Понимание макета CSS и контекста блочного форматирования». Поэтому, говоря display: inline-block
, вы получаете встроенный блок, который также устанавливает BFC.
Как вы обнаружите (если вы читали вышеупомянутую статью о контексте блочного форматирования), существует более новое значение display, которое также явно создает BFC. Это значение flow-root
. Это значение создает BFC на блоке, а не на встроенном элементе.
-
display: inline-block
дает вам BFC на встроенном поле. -
display: flow-root
дает вам BFC на блок-боксе.
Теперь вы, вероятно, думаете, что все это немного сбивает с толку: почему здесь два совершенно разных ключевых слова и что случилось с синтаксисом с двумя значениями, о котором мы говорили ранее? Это аккуратно ведет к следующему моменту, который мне нужно объяснить относительно display
, т. е. к тому факту, что у CSS есть история, с которой нам нужно иметь дело в терминах свойства display
.
Устаревшие значения отображения
Спецификация CSS2 детализировала следующие значения свойства display
:
-
inline
-
block
-
inline-block
-
list-item
-
none
-
table
-
inline-table
Также были определены различные внутренние свойства таблицы, такие как table-cell
, которые мы не рассматриваем в этой статье.
Затем мы добавили к ним некоторые значения для отображения, чтобы поддерживать flex и сетку:
-
grid
-
inline-grid
-
flex
-
inline-flex
Примечание . Спецификация также определяет ruby
и inline-ruby
для поддержки Ruby Text, о чем вы можете прочитать в спецификации Ruby.
Это все отдельные значения свойства display
, определенные до того, как спецификация была обновлена для объяснения CSS Layout таким образом. Что очень важно в CSS, так это тот факт, что мы не ломаем сеть; мы не можем просто что-то изменить . Мы не можем внезапно решить, что все должны использовать этот новый синтаксис с двумя значениями, и поэтому каждый когда-либо созданный веб-сайт, использующий синтаксис с одним значением, сломается, если разработчик не вернется и не исправит его!
Размышляя об этой проблеме, вам может понравиться этот список ошибок в дизайне CSS, которые во многих случаях являются меньшими ошибками, чем вещи, которые были разработаны без хрустального шара, чтобы заглянуть в будущее! Однако дело в том, что мы не можем сломать сеть, поэтому у нас сложилась ситуация, когда прямо сейчас браузеры поддерживают набор одиночных значений для отображения, а спецификация переходит на два значения для отображения.
Способ обойти это — указать устаревшие и короткие значения для отображения, которые включают все эти отдельные значения. Это означает, что сопоставление может быть определено между отдельными значениями и двумя новыми значениями ключевых слов. Что дает нам следующую таблицу значений:
Одно значение | Значения двух ключевых слов | Описание |
---|---|---|
block | block flow | Блочная коробка с нормальным потоком внутри |
flow-root | block flow-root | Блок-бокс, определяющий BFC |
inline | inline flow | Встроенная коробка с нормальным потоком внутри |
inline-block | inline flow-root | Встроенный блок, определяющий BFC |
list-item | block flow list-item | Блок-бокс с нормальным внутренним потоком и дополнительным маркерным блоком |
flex | block flex | Блок-бокс с внутренней гибкой компоновкой |
inline-flex | inline flex | Встроенный блок с внутренней гибкой компоновкой |
grid | block grid | Блок-бокс с внутренней сеткой |
inline-grid | inline grid | Встроенный блок с внутренней сеткой |
table | block table | Блок-бокс с внутренней компоновкой стола |
inline-table | inline table | Встроенный блок с внутренней компоновкой таблицы |
Чтобы объяснить, как это работает, мы можем подумать о грид-контейнере. В мире двух значений мы бы создали контейнер сетки на уровне блока с:
.container { display: block grid; }
Однако устаревшее ключевое слово означает, что следующее делает то же самое:
.container { display: grid; }
Если вместо этого нам нужен встроенный грид-контейнер, в мире двух значений мы будем использовать:
.container { display: inline grid; }
И если использовать устаревшие значения:
.container { display: inline-grid; }
Теперь мы можем вернуться к тому, с чего начался этот разговор, и посмотреть на display: inline-block
. Глядя на таблицу, вы можете видеть, что это определяется в мире двух значений как display: inline flow-root
. Теперь он соответствует display: flow-root
, что в мире с двумя значениями было бы display: block flow-root
. Небольшая уборка и разъяснение того, как эти вещи определяются. Рефакторинг CSS, если хотите.
Поддержка браузерами синтаксиса с двумя значениями
Пока что браузеры не поддерживают синтаксис с двумя значениями для свойства display
. Ошибку реализации для Firefox можно найти здесь. Реализация — когда это произойдет — по существу будет включать псевдонимы устаревших значений для версий с двумя значениями. Поэтому, скорее всего, пройдет немало времени, прежде чем вы действительно сможете использовать эти версии с двумя значениями в своем коде. Однако суть данной статьи не в этом. Вместо этого я думаю, что рассмотрение значений отображения в свете двухзначной модели помогает объяснить многое из того, что происходит.
Когда вы определяете макет для блока в CSS, вы определяете, что происходит с этим блоком с точки зрения того , как он ведет себя по отношению ко всем другим блокам в макете . Вы также определяете, как ведут себя дочерние элементы этого блока. Вы можете думать таким образом задолго до того, как сможете явно объявить значения как две отдельные вещи, поскольку устаревшие ключевые слова сопоставляются с этими значениями, и это поможет вам понять, что происходит, когда вы меняете значение display
.