Копание в свойствах отображения: генерация блоков
Опубликовано: 2022-03-10display
в CSS, на этот раз Рэйчел Эндрю рассматривает значения, управляющие генерацией блока, для тех случаев, когда вы вообще не хотите генерировать блок. Это вторая из короткой серии статей о свойстве display
в CSS. Вы можете прочитать первую статью из этой серии на странице «Две ценности отображения». Спецификация display
очень полезна для понимания, поскольку она лежит в основе всех имеющихся у нас методов компоновки.
Хотя многие значения display
имеют собственную спецификацию, многие термины и идеи подробно описаны в display
. Это означает, что понимание этой спецификации поможет вам понять спецификации, которые в основном детализируют значения display
. В этой статье я рассмотрю значения генерации блоков display
— none
и contents
.
Все в коробке
В CSS все создает блоки. Веб-страница, по сути, представляет собой набор блочных и встроенных блоков, в чем вы очень хорошо разберетесь, если откроете DevTools в своем любимом браузере и начнете выбирать элементы на странице. Вы можете видеть поля, из которых состоит макет, и то, как применяются их поля, отступы и границы.
Генерация блоков управления
Значения none
и contents
для display
определяют, должны ли поля появляться вообще. Если у вас есть элементы в вашей разметке и вы не хотите, чтобы они генерировали блок в CSS, вам нужно каким-то образом подавить создание блока. Есть две возможные вещи, которые вы, возможно, захотите сделать. Которые:
- Предотвратить создание блока и всех его дочерних элементов.
- Предотвратить создание блока, но по-прежнему отображать дочерние элементы.
Мы можем рассмотреть каждый из этих сценариев по очереди.
дисплей: нет
Значение none
для display
— это то, как мы предотвращаем создание блока и всех дочерних элементов этого блока. Он действует так, как будто элемента вообще не было. Поэтому это полезно в ситуациях, когда вы намерены полностью скрыть этот контент, возможно, потому, что он будет раскрыт позже после активации ссылки.
Если у меня есть пример с абзацем, неупорядоченным списком и еще одним абзацем, вы можете видеть, что элементы отображаются в обычном порядке. У ul
есть фон и граница, а также некоторые отступы.
Если я добавлю display: none
к ul
, он исчезнет с визуального отображения, забрав с собой дочерние ul
, а также фон и границу.
Если вы используете display: none
, это скрывает содержимое от всех пользователей веб-сайта. Сюда входят пользователи программ чтения с экрана. Поэтому вы должны использовать это только в том случае, если вы хотите, чтобы коробка и все, что внутри нее, было полностью скрыто от всех.
Бывают ситуации, когда вам может понадобиться добавить дополнительную информацию для пользователей вспомогательных технологий, таких как программы чтения с экрана, но скрыть ее для других пользователей; в таких случаях нужно использовать другую технику. Несколько замечательных предложений сделал Скотт О'Хара в своей статье «Inclusively Hidden».
Таким образом, использование display: none
довольно просто. Используйте его в ситуации, когда вы хотите, чтобы блок и его содержимое исчезли с экрана, из дерева ящиков и из дерева специальных возможностей (как будто их никогда и не было).
дисплей: содержимое
Для второго сценария нам нужно взглянуть на гораздо более новое значение display. Значение display: contents
удалит поле, к которому оно применяется, из дерева блоков так же, как и display: none
, но оставит дочерние элементы на месте. Это приводит к некоторому полезному поведению с точки зрения вещей, которые мы затем можем делать в наших макетах. Давайте рассмотрим простой пример, а затем изучим его дальше.
Я использую тот же пример, что и раньше, но на этот раз я использовал display: contents
для ul
. Элементы списка теперь видны, однако они не имеют фона и границ и ведут себя так, как будто вы добавили элементы li
на страницу без включения ul
.
Причина, по которой удаление блока и сохранение дочерних элементов полезно, заключается в том, как ведут себя другие значения display
. Когда мы изменяем значение display
, мы делаем это для блока и прямых дочерних элементов этого блока, как я описал в прошлой статье. Если я добавлю display: flex
к правилам CSS для элемента, этот элемент станет блоком уровня блока, а прямые дочерние элементы станут flex-элементами. Дочерние элементы этих гибких элементов возвращаются к нормальному потоку (они не являются частью гибкого макета).
Вы можете увидеть это поведение в следующем примере. Здесь у меня есть содержащий элемент, настроенный для отображения flex, у него есть четыре прямых дочерних элемента, три элемента div и ul
. ul
имеет два элемента списка. Все прямые дочерние элементы участвуют в гибком макете и размещаются как гибкие элементы. Элементы списка не являются прямыми дочерними элементами и поэтому отображаются как элементы списка внутри поля ul
.
Если мы возьмем этот пример и добавим display: contents
к ul
, поле будет удалено из визуального отображения, и теперь дочерние элементы будут участвовать в гибком макете. Вы можете видеть, что они не становятся прямыми детьми. Они не выбираются прямым дочерним универсальным селектором ( .wrapper > *
) так же, как элементы div и ul
, и сохраняют заданный им фон. Все, что произошло, это то, что поле, содержащее ul
, было удалено, все остальное продолжается как обычно.
Это может иметь очень полезные последствия, если мы рассматриваем элементы в HTML, которые важны для доступности и семантических данных, но которые создают дополнительное поле, которое может помешать нам размещать содержимое с помощью гибкого макета или сетки.
Это не «сброс» CSS
Вы могли заметить, что одним из побочных эффектов использования display: contents
является удаление полей и отступов элемента. Это потому, что они связаны с блоком, частью блочной модели CSS. Это может натолкнуть вас на мысль, что display: contents
— это хороший способ быстро избавиться от отступов и полей элемента.
Это использование, которое Адриан Роселли заметил в дикой природе; он был достаточно обеспокоен, чтобы написать подробный пост, объясняющий проблемы, связанные с этим — « display: contents
не является сбросом CSS». Некоторые из вопросов, которые он поднимает, связаны с досадной проблемой доступности в браузерах, в настоящее время поддерживающих display:content, которые мы обсудим ниже. Однако даже после того, как эти проблемы будут решены, удаление элемента из дерева блоков просто для того, чтобы избавиться от полей и отступов, несколько экстремально.
По крайней мере, это было бы проблематично для будущего обслуживания сайта, будущий разработчик мог бы задаться вопросом, почему они, кажется, не могут ничего применить к этой загадочной коробке - упуская из виду тот факт, что она была удалена! Если вам нужно, чтобы margin и padding были равны 0
, сделайте себе одолжение и установите их на 0
проверенным временем способом. Зарезервируйте использование display: contents
для тех особых случаев, когда вы действительно хотите убрать коробку.
Также стоит отметить разницу между display: contents
и подсеткой CSS Grid Layout. Где display: contents
полностью удаляет блок, фон и границу с дисплея, делая элемент сетки подсеткой, сохраняя любой стиль блока для этого элемента и просто пропуская размер дорожки, чтобы вложенные элементы могли использовать ту же сетку. Узнайте больше в моей статье «CSS Grid Level 2: Here Comes Subgrid».
Проблемы доступности и отображения: содержание
Серьезная проблема в настоящее время делает display: contents
бесполезным для того, для чего оно было бы наиболее полезным. Очевидные случаи для display: contents
— это те случаи, когда требуются дополнительные поля для добавления разметки, которая делает ваш контент более понятным для тех, кто использует программы чтения с экрана или другие вспомогательные устройства.
Элемент ul
нашего списка в первом display: contents
CodePen — прекрасный пример. Вы можете получить тот же визуальный результат, сгладив разметку и вообще не используя список. Однако, если содержимое семантически представляет собой список, который лучше всего понимается и считывается программой чтения с экрана как список, его следует разметить как один.
Если затем вы хотите, чтобы дочерние элементы были частью макета flex или grid, как если бы поля ul
не было, вы должны иметь возможность использовать display: contents
, чтобы волшебным образом убрать поле и сделать его таким — но оставить семантика на месте. В спецификации сказано, что так и должно быть,
«Свойствоdisplay
не влияет на семантику элемента: они определяются языком документа и не зависят от CSS. Помимо значения none, которое также влияет на звуковой/речевой вывод и интерактивность элемента и его потомков, свойствоdisplay
влияет только на визуальный макет: его цель — предоставить разработчикам свободу изменять поведение макета элемента, не затрагивая лежащий в его основе. семантика документа».
Как мы уже обсуждали, значение none
скрывает элемент от средств чтения с экрана, однако другие значения display
предназначены исключительно для того, чтобы позволить нам изменить то, как что-то отображается визуально . Они не должны затрагивать семантику документа.
По этой причине многие из нас неожиданно осознали, что display: contents
на самом деле было удалением элемента из дерева специальных возможностей в двух браузерах (Chrome и Firefox), которые его реализовали. Поэтому изменив семантику документа, сделав так, чтобы программа чтения с экрана не знала, что список был списком, после того как ul
был удален с помощью display: contents
. Это ошибка браузера, причем серьезная.
В прошлом году Хидде де Врис описал эту проблему в своем посте «Более доступная разметка с помощью display:contents
» и услужливо поднял проблемы с различными браузерами, чтобы повысить осведомленность и заставить их работать над исправлением. Firefox частично устранил проблему, хотя проблемы с некоторыми элементами, такими как кнопка, все еще существуют. Над проблемой активно работают в Chrome. Также есть проблема с WebKit. Я бы посоветовал вам отметить эти ошибки звездочкой, если у вас есть варианты использования display: content, на которые могут повлиять проблемы.
До тех пор, пока эти проблемы не будут устранены, а версии браузеров, в которых обнаружена проблема, не перестанут использоваться, вам нужно быть очень осторожным при использовании display:contents во всем, что передает семантическую информацию и требует доступа к вспомогательным технологиям. Как утверждает Адриан Роселли,
«Пожалуйста, используйте Display: Content только в том случае, если вы собираетесь тестировать вспомогательные технологии и можете подтвердить, что результаты работают для пользователей».
Есть места, где вы можете без опаски использовать display: contents
. Один из них — если вам нужно добавить дополнительную разметку для создания запасных вариантов для вашей сетки гибких макетов в старых браузерах. Браузеры, которые поддерживают display: contents
, также поддерживают сетку и флексбокс, поэтому вы можете display: contents
без добавления избыточных элементов div
. В приведенном ниже примере я создал сетку с плавающей запятой, дополненную обертками строк.
Затем я использую display: contents
, чтобы удалить обертки строк, чтобы все элементы стали элементами сетки и, следовательно, могли быть частью макета сетки. Это может дать вам дополнительный инструмент при создании запасных вариантов для расширенных макетов, поскольку, если вам нужно добавить дополнительную разметку, вы можете удалить ее с помощью display:contents при создании сетки или гибкого макета. Я не считаю, что такое использование должно вызывать какие-либо проблемы — хотя, если у кого-то есть более подробная информация о доступности, чем у меня, и он может указать на проблему, пожалуйста, сделайте это в комментариях.
Подведение итогов
В этой статье были рассмотрены значения генерации блока свойства display
. Надеюсь, теперь вы понимаете разницу в поведении display: none
, которая полностью удаляет блок и все дочерние элементы, и display: contents
, который удаляет только сам блок. Вы также должны понимать потенциальные проблемы использования этих методов, когда речь идет о доступности.