Обзор
Карточка объединяет один связанный фрагмент контента или один вариант. Это визуальный шаблон, а не фиксированная семантическая или интерактивная модель, поэтому сохраняйте смысл контента и используйте нативное взаимодействие, соответствующее его цели.
Правила
Выберите семантику для контента и взаимодействия с ним по отдельности:
- используйте
<article>в качестве корневого элемента карточки, независимо от того, ведет ли он на целевую страницу; - используйте нативную ссылку для навигации. Если вся карточка является одной целевой страницей, то одна ссылка может содержать
<article>, только если карточка не содержит других интерактивных элементов (a,button,input,select,textarea). - сохраняйте ссылки и кнопки для независимых действий в виде отдельных нативных элементов управления;
- используйте переключатель или флажок со связанным элементом
<label>илиoptionв нативном элементе<select>, если карточка представляет собой вариант выбора.
Медиаконтент, заголовок, дополнительный контент и действия должны быть расположены в логичном порядке. Не используйте свойство CSS order, чтобы изменить его (см. статью Макеты CSS и адаптивный дизайн).
Реализация
Используйте минимальную разметку и позвольте селекторам CSS распознавать каждый регион, чтобы простые карточки оставались простыми, а более насыщенные карточки оставались возможными. Карточка может содержать до четырех областей, перечисленных ниже в порядке их расположения в исходном коде. Любую из них можно опустить. Регионы являются прямыми дочерними элементами карточки и не группируются в элементы-оболочки, такие как .card__body, что не позволяет размещать и стилизовать регионы по селектору. Регион с одним элементом – это сам элемент, не заключенный в оболочку: отдельный абзац – это <p>. Используйте обертку, только если в регионе несколько элементов.
- Медиаконтент. Первым дочерним элементом должен быть
<img>,<picture>,<video>или<svg>. Добавляйте класс.mediaтолько к произвольному главному контенту, который не является одним из этих элементов, и никогда не помещайте простой элемент<img>в элемент.media. - Заголовок – заголовок, который не является частью другого элемента. Используйте
<hgroup>, только если у заголовка есть подзаголовок или слоган, и<header>, если в разделе есть не только заголовок, но и, например, поле автора или значок. Если у карточки есть основная целевая страница, ссылка на нее добавляется в заголовок. - Контент. Отдельный элемент
<p>,<ul>или<dl>. Если контент состоит из нескольких элементов, например нескольких абзацев или абзаца и списка, сгруппируйте их в одном элементе<div>, чтобы область была одним элементом сетки. - Нижний колонтитул – элемент
<footer>, содержащий независимые действия в виде нативных ссылок и кнопок. Ссылка "Подробнее" может вести на тот же URL, что и ссылка в заголовке, но у нее должно быть описательное доступное название, которое начинается с видимого текста и содержит визуально скрытый текст (например,Read more<span> about poached eggs</span>), поскольку одинаковые ссылки "Подробнее" в списке ссылок программы чтения с экрана могут запутать пользователя. Не добавляйте другие ссылки в нижний колонтитул, которые повторяют URL заголовка.
Простейшая карточка – это <article>, содержащий заголовок и абзац. Выберите шаблон ссылки и действия, соответствующий поведению карточки. Подробнее о моделях взаимодействия…
Для изображений или видео, которые должны заполнять область с фиксированным соотношением сторон, задайте aspect-ratio и object-fit: cover для самого элемента <img> или <video>, чтобы он заполнял область без искажений (может произойти кадрирование). Используйте aspect-ratio контейнера .media только для другого главного контента. В противном случае сохраняется исходное соотношение сторон. Добавляйте к информативным изображениям подходящий альтернативный текст, а к декоративным – атрибут alt="".
Адаптация к доступному пространству
Основывайте макет на доступном пространстве карточки, а не на области просмотра. Чтобы адаптировать дочерние элементы карточки (медиа, текст, действия), сделайте карточку контейнером размера (container-type: inline-size) и напишите правила @container для ее дочерних элементов. Не задавайте размеры на основе родительского элемента сетки или списка. Фактическая ширина карточки может зависеть от количества столбцов, пробелов и т. д., что делает контрольные точки на основе родительского элемента неточными.
В узком контейнере регионы располагаются друг под другом в порядке, заданном в исходном коде. В широком контейнере разместите медиаконтент в боковом столбце рядом с другими областями, но только для карточек, содержащих медиаконтент. Для этого задайте правила с помощью :has() в дочернем элементе медиаконтента (например, .card:has(> img)), чтобы определения столбцов и размещение grid-column никогда не применялись к карточке без медиаконтента. Карточка без медиаконтента всегда имеет один столбец, и в ней не должно быть пустого столбца для медиаконтента.
Выровнять карточки по сетке
Если карточки в строке должны иметь одинаковую высоту, используйте subgrid: сделайте так, чтобы каждая карточка занимала четыре общие строки (медиа, заголовок, контент, нижний колонтитул) и разместите области по селектору элементов, рассматривая все, что не является медиа, заголовком или <footer>, как контент. Если на карточке нет региона, его дорожка остается пустой, поэтому остальные регионы по-прежнему выстраиваются в линию с соседними карточками. Каждая дорожка содержит один элемент сетки, поэтому помещайте область контента в <div>, только если в ней больше одного элемента и карточки находятся на одной дорожке. Карточкам, которые не выровнены по соседним элементам, не нужны ни обертка, ни субсетка.
Модели взаимодействия
Карточки контента
Используйте <article> в качестве корневого элемента карточки. Ссылки и кнопки должны быть отдельными нативными элементами управления.
Карточки с одним пунктом назначения
Если вся карточка является одним целевым объектом и не содержит независимых действий, используйте одну нативную ссылку. Ссылка может быть обернута в <article>. Не вкладывайте в ссылку другие ссылки, кнопки или элементы управления формой. Текст "Читать далее" должен быть простым элементом <p> или <span>. Поскольку доступным названием ссылки является весь текст карточки, он должен быть коротким. Если в карточке много текста или других действий, используйте шаблон растянутой ссылки, чтобы ссылкой был только заголовок:
<a href="/recipes/poached-eggs">
<article class="card">
<h3>Poached eggs</h3>
<p>Two poached eggs served on toasted sourdough.</p>
</article>
</a>
Интерактивные карточки с независимыми действиями
Если нажатие на карточку запускает действие, а не переход, используйте <button> вместо ссылки.
Если карточка контента ссылается на основную целевую страницу, содержит другие интерактивные элементы и должна быть полностью кликабельной:
- Используйте одно согласие на основной ссылке: добавьте
.card-linkтолько на одну ссылку в карточке (ссылку в заголовке). Нижний колонтитул и другие ссылки не должны получать этот класс, иначе каждый из них будет растягивать свой оверлей, а последний захватит всю карточку. - Добавьте ссылку в заголовок и растяните область нажатия указателя на всю карточку с помощью
::after.
.card:has(a.card-link) {
position: relative;
}
.card a.card-link::after {
content: "";
position: absolute;
inset: 0;
}
- Выделите интерактивные элементы с помощью
position: relative; z-index: 1, чтобы они оставались доступными. Настройте таргетинг на типы элементов (например,a, button), а не на классы. - НЕ применяйте
z-indexко всему контейнеру, иначе он будет регистрировать события указателя, которые не приводят к каким-либо действиям.
.card:has(a.card-link) {
/* Keep other interactive elements above the overlay */
a:not(.card-link), button, input, x-button {
position: relative;
z-index: 1;
}
}
- Стилизуйте саму карточку при наведении/фокусе, а не растянутую ссылку:
.card {
a.card-link {
&:focus-visible {
outline: none; /* Draw it on the card instead */
}
}
&:has(a.card-link:focus-visible) {
/* Focus ring */
}
&:has(a.card-link:hover) {
/* Hover styles */
}
}
Карточки выбора
Для карточек, представляющих предопределенные варианты выбора, используйте <label class="card"> с флажком или переключателем в качестве прямого дочернего элемента.
Оформить выбранную карточку с помощью :has(:checked). Никогда не меняйте свойства, влияющие на макет, такие как border-width, padding или font-weight, при выборе, потому что карточка и соседние с ней элементы будут прыгать. Выделите карточку с помощью outline, box-shadow или прозрачной границы, которая меняет только цвет:
.card {
border: 2px solid transparent;
&:has(> :checked) {
border-color: var(--accent);
}
}
Видимый флажок или переключатель сам по себе является нецветным индикатором выбора, поэтому достаточно только изменения цвета. Если элемент управления визуально скрыт (оставьте его доступным для фокусировки и в дереве специальных возможностей, никогда не используйте display: none), добавьте бесцветный индикатор, который не влияет на макет, например значок галочки или более толстую outline.
Если варианты выбора находятся в раскрывающемся списке, элементы которого оформлены в виде карточек, используйте стандартный элемент <select> с appearance: base-select и стилизуйте элементы ::picker(select) и <option>, а не заменяйте элемент select карточками <div>. Подробную информацию и резервные варианты можно найти в разделе Специальные макеты для выбора.