От автора: CSS Grid Layout позволяет превратить элемент в сетку и поместить в него его дочерние элементы первого уровня. Учитывая это, может возникнуть соблазн использовать более плоскую разметку, с меньшим количеством значений, но, как правило, менее доступную. С использованием display contents CSS мы можем поместить в сетку дочерние элементы второго уровня, что позволяет получить доступную разметку и красивую компоновку. Давайте рассмотрим это подробнее!
Ниже я детальнее поясню, что я имею в виду под дочерними элементами первого и второго уровня, а затем покажу, как мы можем использовать display: contents, чтобы улучшить это. Примечание: в настоящее время существуют проблемы с доступностью из-за реализации в браузерах.
Grid распространяется на дочерние элементы первого уровня
В Grid Layout, когда сетка определена для данного элемента, только дочерние элементы первого уровня становятся элементами сетки. Для тех, кто не знаком с синтаксисом, давайте рассмотрим следующий пример. С этой HTML-разметкой:
1 2 3 4 5 6 7 8 9 10 11 12 |
<div class="container"> <h1 class="item">Penne with tomato sauce</h1> <p class="item">This simple recipe has few ingredients but tastes delicious.</p> <div class="item ingredients"> <h2>You'll need</h2> <ul> <li>canned tomatoes</li> <li>onions</li> <li>garlic</li> </ul> </div> </div> |
мы можем использовать этот CSS:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
.container { display: grid; /* элемент становится контейнером сетки */ grid-template-columns: repeat( 4, 1fr ); /* сетка имеет 4 столбца */ .item:nth-child(1) { grid-columns: 1 / 2; /* Размещаем элементы между линиями сеткиe 1 и 2 */ } .item:nth-child(2) { grid-columns: 2 / 4; /* Размещаем элементы между линиями сеткиe 2 и 4 */ } .item:nth-child(3) { grid-columns: 4 / 5; /* Размещаем элементы между линиями сеткиe 4 и 5 */ } |
Я использовал .container и .item в качестве имен классов, потому что это основа для Grid Layout: контейнеры сетки и элементы сетки. Очевидно, вы можете использовать любую конвенцию имен, которая требуется для вашим проектов.
Причина, по которой мы можем размещать эти элементы в сетке, заключается в том, что они являются прямыми дочерними элементами контейнера сетки. Но посмотрите, что произойдет, если мы хотим добавить список спонсоров, например, так:
Мы могли бы добавить список в нашу разметку:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<div class="container"> <h1 class="item">Penne with tomato sauce</h1> <p class="item">This simple recipe has few ingredients but tastes delicious.</p> <div class="item ingredients"> <h2>You'll need</h2> <ul> <li>canned tomatoes</li> <li>onions</li> <li>garlic</li> </ul> </div> <ul class="item sponsors"> <li>Supermarket 1</li> <li>Supermarket 2</li> </ul> </div> |
Но мы не сможем разместить каждого спонсора на сетке. Это происходит потому, что только ul является прямым потомком элемента контейнера и, следовательно, элементом сетки. li не являются таковыми: потому что они не прямые дочерние элементы первого уровня для контейнера сетки, они не участвуют в его сетевой игре. Но что, если мы действительно хотим выровнять спонсоров по сетке?
Более плоская разметка
Одним из очевидных способов ввести в сетку спонсоров является удаление ul и использование div для каждого спонсора. Однако в этом случае мы бы сделали разметку более «плоской». Это то же самое, что выплеснуть ребенка вместе с водой из ванны.
Преимущества использования элемента ul (неупорядоченный список) — это:
он отображается, как список, вне контекста страницы, например, в режиме Safari Reader, он будет отображаться в виде списка
при печати с отключенной таблицей стилей он все равно будет отображаться в виде списка
для тех, кто использует для чтения экранных дикторов — это список (экранный диктор может объявлять такие вещи, как «список, 3 элемента»).
Если мы сделаем разметку более плоской, мы потеряем эти преимущества.
На помощь приходит display: contents
С помощью display: contents мы можем получить и разметку, и размещение в сетке. Это свойство делает элемент таким, что выглядит, будто он больше не существует. Он не генерирует блок, поэтому фоны, границы и другие свойства, связанные с блоком, больше не будут применимы для него. Свойства размещения сетки также больше не будут работать. Но все эти вещи будут применимы для дочерних элементов. В спецификации говорится, что такой элемент ведет себя так, «как если бы он был заменен […] его содержимым».
На практике, применив для наших целей к элементу display: contents, мы получим следующее: элемент перестает быть частью сетки, и частью сетки становится его содержимое. Это позволяет нам указывать наших спонсоров в сетке, а не в списке, в котором они содержатся.
В спецификации описано несколько интересных случаев применения свойства для таких элементов, как img и video.
Проблемы доступности при текущей реализации display: contents в браузерах
Для тех, кто использует вспомогательные технологии (AT), браузеры предоставляют свойства доступности, в том числе такие, как элементы role. Таким образом AT знает, что размещено на странице. Многие элементы имеют встроенные role, например, списки имеют role — list.
Здесь и начинаются проблемы в текущих версиях браузеров, которые поддерживают display: contents. Они не интерпретируют display: contents только как компонент макета, они также воспринимают смысловую часть. В этом и проблема. Возвращаясь к примеру нашего списка спонсоров, это означает, что элемент больше не рассматривается как список, а как что-то еще (Тестовый пример на CodePen).
Я добавил результаты теста для разных браузеров ниже. В каждом из них наш ul без display: contents корректно получает role, но после применения свойства элемент терял role.
Firefox 61
Список получает role — text leaf (журнал ошибок Firefox).
Chrome 66
Список отображается, как «узел доступности не представлен, элемент не отображается» (журнал ошибок Chromium).
Safari
Список отображается, как «нет информации о доступности» (журнал ошибок Safari)
ul — это просто пример того, это происходит с любым элементом, который получает display: contents и раньше имел role.
Если вы решительно хотите, чтобы доступность с display: contents была реализована, пожалуйста, подумайте над тем, чтобы написать комментарии в соответствующие журналы ошибок браузеров, с примерами и т. д. Я надеюсь, что разработчики прислушаются к этому.
Заключение
С помощью display: contents, вы можете поместить больше дочерних элементов в сетку. Это позволяет использовать больше семантической разметки, что отлично подходит для доступности. Чем более значимой будет ваша разметка, тем более детально вспомогательная технология может предоставить ее пользователям. Однако есть одна оговорка: ни один из браузеров, которые в настоящее время поддерживают display: contents, не отображают элементы, к которым применено это свойство с соответствующей role для доступности.
Я считаю, что role не должны исчезать при установке display: contents, поскольку это противоречит цели применения display: contents. Поэтому я написал в журналы ошибок Firefox, Chromium и Safari. Я очень надеюсь, что мы сможем использовать display: contents, сохраняя при этом role доступности, чтобы у нас были отличные макеты и высокая доступность. Надеюсь, продолжение следует!
Автор: Hidde de Vries
Источник: //hiddedevries.nl/
Редакция: Команда webformyself.