Budowa karty, która jest w całości klikalna, a jednocześnie zawiera w sobie dodatkowe akcje (jak przycisk „Ulubione”), to jedno z częstych wyzwań UX/UI.
Opisywany komponent karty
Na czym polega problem?
Zgodnie ze standardami HTML i WCAG, nie wolno umieszczać elementów interaktywnych wewnątrz innych elementów interaktywnych.
Taka konstrukcja prowadzi do błędów w drzewie dostępności, utrudniając poprawną nawigację przy użyciu czytników ekranowych.
Co chcemy osiągnąć?
Naszym celem jest rozdzielenie warstwy wizualnej od semantyki:
Dla użytkownika:
cała karta wygląda jak klikalna
kursor zmienia się na „łapkę” na całej powierzchni
Dla technologii asystujących:
linkiem jest tylko konkretny element (np. tytuł)
przyciski są osobnymi, niezależnymi kontrolkami
Rozwiązanie: stretched link
Zamiast owijać całą kartę w <a>, traktujemy:
link
przyciski
jako oddzielne elementy.
Kluczowa idea
Link umieszczamy tam, gdzie ma on sens semantyczny, najczęściej w tytule.
Następnie:
Rozciągamy link: za pomocą ::after sprawiamy, że link z nagłówka pokrywa całą powierzchnię karty.
Warstwujemy akcje: przyciski (np. „Ulubione”) wyciągamy na wierzch przez z-index, by pozostały niezależne i klikalne.
.card{position:relative;}.overlay-link{&::after{content:'';position:absolute;inset:0;z-index:1;/* Warstwa podstawowa */}/* Wyraźny focus klawiatury widoczny na obrysie całej karty */&:focus-visible::after{outline:3pxsolid#3b82f6;outline-offset:4px;}}/* Przyciski interaktywne wyciągnięte "NAD" link */.fav-btn,.btn-primary{position:relative;z-index:2;/* Przebija się przez warstwę linku głównego */}
Co wyróżnia to podejście?
Prawidłowa semantyka: czytnik ekranu ogłasza tylko krótki, konkretny tytuł jako link.
Niezależne akcje: możemy dodać przycisk „Ulubione”, „Koszyk” czy „Tagi”, m.in. dzięki z-index: 2.
Zgodność z HTML5: unikamy błędu zagnieżdżania przycisku wewnątrz linku.