TGViewer
<divelopers> <divelopers> @alexnozer_dev · 1.18K subscribers
Post #313 783
Улучшение семантики карточки

Наткнулся в LinkedIn на пост с рецептом пропорционально масштабируемой карточки на основе единиц cqi и математики. Но меня зацепило не это, а разметка карточки:

<div class="card">
<div class="card-inner">
<img
class="card-img"
alt=""
src="..."
>
<div class="card-content">
<div class="card-title">
Добро пожаловать!
</div>
<div class="card-desc">
Это масштабируемая карточка.
</div>
<a
class="card-button"
href="..."
target="_blank"
>
Подписаться
</a>
</div>
</div>
</div>


<div> в <div>-е сидит и <div>-ом погоняет. Понятно, что разметка иллюстративная, а суть поста в CSS-технике. Иллюстративная ведь, да? Я не смог пройти мимо и решил сделать из этого пост. Итак, чиним семантику карточки.

Элемент .card может быть размечен как <article>, если карточка представляет независимый контент, который можно вырвать из контекста без потери смысла. Альтернатива — <div role="group">.

Возможен вариант с <section>, если карточка — большой тематический раздел. Если карточка находится в <li>, то <div> остаётся как обёртка компонента или сам <li> берёт на себя эту функцию.

Элемент .card-inner кажется лишним. Возможно, это требуется для стилей. Но выглядит так, что можно использовать родительский .card, а .card-inner можно удалить. Чем меньше узлов, тем лучше.

С .card-img всё ок. Пустой alt уместен для декоративных изображений, иначе нужно описание. Но можно лучше: добавить адаптивность за счёт атрибутов srcset и sizes, хотя-бы с x-дескриптором.

Можно добавить width и height для предотвращения сдвигов макета. Если карточка находится за пределами начальной области просмотра, loading="lazy" отложит загрузку картинки, а fetchpriority и decoding дадут больше контроля.

Элемент .card-content так же выглядит лишним. Расположить изображение и остальной контент можно с помощью flex или grid у .card, без лишних обёрток. В таких мелочах раздувается размер DOM.

.card-title надо заменить на заголовок, title в названии класса намекает. Скорее всего, <h3>, карточка обычно находится в разделе с <h2>. Но возможен вариант с <h2>, всё зависит от структуры.

Судя по классу и короткому тексту без дополнительной разметки, элемент .card-desc принимает обычный текст. Тут больше подойдёт элемент <p>. <div> уместен для rich-контента из WYSIWYG.

У ссылки .card-button не хватает информации об открытии страницы в новой вкладке для удобства пользователей вспомогательных технологий. Дополнительная иконка со стрелкой обеспечит визуальную подсказку.

Картинку и заголовок можно поменять местами в DOM и инвертировать порядок через CSS. Чтобы при быстром переходе к заголовку в скринридерах картинка не затерялась. Это имеет смысл для контентных картинок с alt-текстом.

К <article> можно привязать заголовок с помощью aria-labelledby для дополнительного контекста. Можно попробовать aria-roledescription для уточнения роли элемента. Но такие моменты желательно тестировать.

<article
class="card"
aria-labelledby="heading"
>
<h3
class="card-title"
id="heading"
>
Добро пожаловать!
</h3>
<img
class="card-img"
alt=""
src="..."
srcset="... 1x, ... 2x"
sizes="..."
width="380"
height="380"
loading="lazy"
decoding="async"
>
<p class="card-desc">
Это масштабируемая карточка.
</p>
<a
class="card-button"
href="..."
target="_blank"
>
Подписаться
<svg
role="img"
aria-label="(откроется в новой вкладке)"
>
<!-- ... -->
</svg>
</a>
</article>


Лучше? Лучше! Конечно, важно учитывать контекст. Где-то <article> будет не уместен, у изображения должно быть описание, а заголовок должен быть другого уровня. Также это моя версия разметки, кто-то может не согласиться.

В <div> нет ничего плохого. Но когда почти всё — <div>, вот это плохо. Плохо для SEO, вспомогательных технологий, расширений, парсеров, ИИ, специальных браузеров и режимов отображения веб-контента.

(Отредактировано, чтобы влезло в один пост)

#html
  • ❤ 17
  • 👍 10
  • 👾 5
  • 🌚 1
More from @alexnozer_dev
  1. Sep 21, 2026Реализация пользовательских атрибутов Под конец прошлого года я рассказывал об API пользов…
  2. Sep 14, 2026Подклассы Event вместо CustomEvent Многие библиотеки предоставляют систему событий в качес…
  3. Sep 11, 2026Эволюция стилей в темах Shopify Адам Ватан на днях поделился новостью, что Shopify выкупил…
  4. Sep 9, 2026Persistent Widgets Многие сайты не должны быть SPA. Но иногда эта архитектура продиктована…
  5. Sep 7, 2026Processing Instructions и маркеры В DOM всё представлено в виде узлов (Node) разных типов.…
  6. Sep 1, 2026@scope и потоковая передача HTML Ноам Розенталь поделился интересной техникой, в которой с…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →