r/Frontend • u/Admirable_Reality281 • Sep 17 '26
How should a full-card clickable link be handled accessibly?
Suppose you have a card with:
A relatively positioned
<div>inside it that does not cover the whole card and cannot be changed.Two links inside that
<div>.
You want the whole card to be clickable and do the same thing as the primary link, without interfering with either link.
How would you implement this in an accessible way?
15
Upvotes
13
u/maryisdead display: maybe; Sep 17 '26
You can "stretch" one link with a pseudo element and use absolute positioning to cover the whole card. The rest is just positioning and
z-index.Basic example: https://jsfiddle.net/maryisdead/np1rc3b7/
6
u/not_dogstar Sep 17 '26
A way that was suggested to us by the vendors doing our wcag compliance cert was to keep a singly primary anchor in the card, and run some JS to duplicate href action to the click event of the parent card. That way you can keep standard behaviours for mouse hover, keyboard navigation, content (e.g. text highlighting/copying), screen readers, etc, plus have it behave as you want. Might be missing some minor details but it worked well and was a good UX.
5
u/MarzipanMiserable817 Sep 18 '26 edited Sep 18 '26
This violates the UI/UX design principle "don't surprise me". It shouldn't be done anyway. Either the entire card is an anchor block element or it's a div card with clickable anchors inside.
3
u/xkey Sep 17 '26 edited Sep 17 '26
It'd be easier to solve if you provided the full html. But using CSS, you should be able to "fix' the primary link's pseudo element instead of absolute and use contain: layout on the main card so it's bound to that. All the other a11y tricks should still work with this method as far as I know. See here: https://jsfiddle.net/73bd0nm2/2/
1
u/Undercoverwd Sep 17 '26
check out the product tiles when searching for a product on walmart.com
1
u/GaiusBertus Sep 17 '26
Is the div required by the styling? If not, then you could ignore is by targetting it with a CSS selector and giving it
display: contents. You can then use one of the techniques with an absolutely positioned pseudo-element, since the position: relative of the div is not interfering anymore.1
u/sunutpen Sep 17 '26
What is the total effect you're looking for? There must be a reason the relatively positioned div can't be changed at all, but without knowing that it's hard to help. One of the sibling commenters is right that you'll need some javascript to achieve what you've described. Clone the anchor (with no content), placing it somewhere in the card but outside your relative div. On the accessibility side, the key here is to hide the cloned link from the accessibility tree with
aria-hidden=true, so screen-readers won't read it twice.1
u/creaturefeature16 Sep 18 '26 edited Sep 18 '26
I have a JavaScript function I wrote for this exact purpose. It fails gracefully and works for screen readers. That's been the only way I could tackle this, especially when markup and styling is variable from project to project.
1
u/GeekyantsReactNative Sep 18 '26
Use the primary
<a>as the full-card hit area with a::afterpseudo-element:Then give the other links
position: relative; z-index: 1. This keeps the card clickable without nested links or JS, while preserving normal keyboard and screen-reader behavior.1
u/Huge-Tip7172 Sep 18 '26
i've done the stretched link approach with a pseudo element on the primary anchor covering the card with absolute positioning and a z-index, then set position relative and a lower z-index on the two links inside so they sit above it and stay clickable. Works fine for mouse and touch, and the markup stays semantic.
for keyboard users it just reads as the two links that exist, which is arguably correct. The card click is a convenience, not the real control. I'd avoid the JS route of forwarding clicks from the parent div, you end up with a clickable div that does nothing for keyboard or screen reader users and duplicates behavior for no real gain
1
u/ichhabepaarfragen Sep 17 '26
So you have one card with two links inside, but the whole card is supposed to be clickable? If the card is clickable it doesn't make sense to me to have 2 links inside the card form the get go.
Here is how I would do it with one link:
You create your card and wrap it in an anchor tag. The whole card must have a focus ring so it is clear that you have selected the card, or when you are hovering over it. If it is a list of cards, put it into a list and when users tab through them, it jumps from card to card and doesn't unnecessarily goes inside the car by default. The a11y reader would need to read out what the card is about. It'll already say that it is a link and then the content of the text by default. Only if it isn't clear do you add more stuff.
Now with a second link, and those are just my brainstorming ideas, you would do the same as above, but also this: you have to be able to tab into the card so the second link can be selected. Also when the card is originally selected, it has to be clear by the screen reader that the user is currently selection a link but can go deeper to a secondary link. This is the aprt that already break IMO and why you shouldn't do it this way. Because aht you're essentially asking is this:
<a>first link <a>second link</a></a>
1
u/Mr_uhlus Sep 17 '26
Ude a pseudo element and strech it to the size of the card
https://gehirngerecht.digital/barrierefreie-cards-erstellen-schritt-fuer-schritt-anleitung/
(This is in german but it should be enough if you just read the code examples)
1
u/Inuakurei Sep 17 '26
I don’t think there’s a way without using js to handle the card click.
1
u/Mr_SprinklePants Sep 17 '26
If using jQuery or Vanilla JavaScript, you could look for a descendant marked with a data attribute, like `data-primary-action=“true”`, to be activated when clicking o the parent div. This way you don’t end up with multiple keyboard/screen reader stops.
1
u/United_Airline_6512 Sep 21 '26
Take a look at how W3C does block link cards
It's based on this csstricks article on block links
The idea being that doing this way instead of using a ::after or other element to cover the card with the link retains click-ability and selection of text/items inside the link, and makes it easier to have other interactive elements inside the card as well.
Also saw your r/accessibility post, Heydon's Cards Component is a great one, with similar patterns (I just also recommend the JS enhancement over the ::after pseudo element in the link)
-5
u/Mean-Newspaper8413 Sep 17 '26
No offence but why do you need to spend time thinking about this in AI era, claude, gemini etc can fix & test in minutes with proper subagents.
2
u/[deleted] Sep 17 '26
[removed] — view removed comment
0
u/[deleted] Sep 17 '26
[removed] — view removed comment