Interactive Cards
Table of contents
- Introduction
- Static Cards
- Interactive Cards
- Use Cases
- Change the Image When Hovering or Focusing the Interactive Card
- Action Card: Save the Product to Favorites
- Button Only Interactive Card
- Link Card
- Booking Card
- Disclosure Card
- Promo Card with a Single CTA
- Category Tile
- Product Card with a stretched link and two buttons: Add to Cart and Save
- Article Card with a Bookmark Button
- Product Card with Variant and Quantity Pickers
- Pricing Plan with Two CTAs
- Order Card with Copyable Details
- Selectable Cards: Delivery Speed
- WCAG 2.2 success criteria met
Introduction
Lately, I have been working a lot on standardizing for myself and for my clients how should be built. To be honest, it took me a lot of time researching, building, testing and iterating to find the right examples to make this UI pattern accessible.
First of all, we have to understand what a is. A Card is a UI pattern really helpful to group information in an engaging way. That information can be an image, a link, a paragraph, a button, heading, etc. Interactive Cards are an entry point into more information because the user can click a button to go to the PDP (Product Description Page) of a product or save a product to favorites, etc.
What we need to know before building an interactive card:
- Know the difference between and . (pppss, you can learn the difference here)
- Know how to make the card interactive without breaking the logical HTML semantic.
Interactive cards can be organized in two different categories: Simple and Complex. But first, we have to learn what a card is.
Static Cards
Since a Card is a visual group of a specific semantic concept, we have to use an HTML element that conveys that meaning and that element is... an . According to HTML Standard, an is:
The article element represents a complete, or self-contained, composition in a document, page, application, or site and that is, in principle, independently distributable or reusable, e.g. in syndication. This could be a forum post, a magazine or newspaper article, a blog entry, a user-submitted comment, an interactive widget or gadget, or any other independent item of content.
So, cool, an should be built using an <article>. We can move forward. Well, yes and no because I am pretty sure that only 10% of developers know how to build an accessible card. Let's break the example to understand its anatomy.
Anatomy
Kyoto, Japan Cultural Heritage
Kinkaku-ji Temple3
id="title"4'Temple of the Golden Pavilion' (...) is a Zen Buddhist temple in Kyoto, Japan and a tourist attraction. It is designated as a World Heritage Site, a National Special Historic Site, a National Special Landscape, and one of the 17 Historic Monuments of Ancient Kyoto.(...)
- <article>
wraps the whole card.
- aria-labelledby="title"
its value should be an IDREF pointing to the `id` value on the main heading inside the article.
- <h3 id="title">
main topic of the card.
- <p>
a description or extra information related to the topic that the article groups.
Code example
<article aria-labelledby="id-of-the-heading">
<img src="/link-to-the-source" alt="">
<h2 id="id-of-the-heading">Main title of the article</h2>
<p>Extra information or a description of the topic that the article groups</p>
</article>Interactive Cards
are a whole different world. They combine the article structure and the interactive behavior of a link or a button and this is an extremely dangerous zone where all of you fail because you do not even know how to do a simple static card or to differentiate a link from a button. There could be a card that redirects the user to another location, opens a modal, when it receives focus or hover changes the images, expands the content or has complex interactions inside of it. I am going to cover all those cases and explain their risks and how to mitigate them.
Anatomy Interactive Cards
Expand the sections to discover more information about the layers.
First Layer:
<article>Should be a plain
article. You should not force the interaction by adding atabindex="0"ortabindex="-1"to force the focus programmatically or aonclickto force the functionality in JavaScript. The accessible name should be passed by adding anaria-labelledbypointing to the IDREF in the main heading of the card. The final step that will do the magic later is adding in CSS aposition: relative. This property will help us to stretch that makes it the containing block the stretched pseudo-focus on the whole card when the main interactive element receives focus.<article aria-labelledby="card-title"> {content} </article>article { position: relative; }Second Layer:
<a>The interactive element that will be stretched to make the whole card interactive with the techniques in points 3 and 4.
<h3 id="card-title"> <a href="/kyoto" className="card__link">Kyoto, day to night</a> </h3>Third Layer:
::afterto stretch the action targetAn empty pseudo-element on the link, absolutely positioned with
inset: 0, so the entire card surface becomes the link's hit area for mouse and touch, and.card:hoverfires anywhere on it and the whole article should have aposition: relative. Screen reader users interact with the real link in layer 2. pss, you can make the text selectable by addinguser-select: text;to force it..card__link::after { content: ""; position: absolute; inset: 0; } article { position: relative; } article > p { user-select: text; }Fourth Layer:
article:has([element]:focus-visible)When the stretched interactive element in the interactive card receives focus a simil focus outline should wrap the whole card to point out that the whole area is interactive.
article:has(a:focus-visible) { outline: 2px solid black; outline-offset: 4px; }
Simple Interactive Cards
- Only have one interactive element with a single purpose which could be redirecting the user to a new location or expanding more information.
- One stretched
<a>or<button>with a::afterpseudo-element withposition: absolute; inset: 0, if applicable. - The card itself,
article, should never be the interactive element. - One Tab stop per card.
- When the link is focused, visually highlights the entire card.
- The screen reader announces the elements in a hierarchical way: first the article with its accessible name, then the heading, description, action, for example.
- Can be used on: blog or news teasers, category tiles, team member cards, promo cards with a single CTA.
<article class="card" aria-labelledby="hotel-1">
<h3 id="hotel-1">
<a class="card__link" href="#">Hotel</a>
</h3>
<p>Information about the hotel</p>
</article>Complex Interactive Card
- Have two or more interactive elements, each with its own purpose. For example: a card with an 'add to cart' button, a 'save to favorites' button and a 'go to product details' link.
- The interactive elements are siblings, never nested because this is an accessibility failure and a bad practice.
- The card can have a stretched interactive element but only if it has a clear destination. For example, a link to go to the PDP page.
- One tab stop per control: primary link first then, secondary actions.
- If applicable, when focusing on the primary link, it highlights the entire card using a streched link technique.
- As in Simple Interactive Card, the screen readers should announce first the article with its accessible name, then the heading with the primary link, then the description and then the rest of the actions.
- Can be used on: e-commerce product cards (Add to cart, save to favorites), social media posts (Like, Reply, share), articles with a Bookmark button.
<article class="card" aria-labelledby="product-1">
<h3 id="product-1">
<a class="card__link" href="#">Product 1</a>
</h3>
<p>Description of the product 1</p>
<button class="card__control">Add product 1 to cart</button>
<button class="card__control" aria-pressed="false">
<span class="visually-hidden">Save Product 1 to favorites</span>
</button>
</article>Complex Interactive Cards should NOT have a stretched link when:
- The Interactive Card does not have a single destination but two CTAs, for example a "Start Trial" button and a "Compare Features" button.
- The card contains controls such as swathcers, a quantity stepper or inline links.
Use Cases
Change the Image When Hovering or Focusing the Interactive Card
Simple Interactive Card
Action Card: Save the Product to Favorites
Complex Interactive Card with a stretched link over the whole card and then three more interactive elements: a bookmark button to save the place into favorites and a link to learn more about Kyoto in Wikipedia.
Button Only Interactive Card
Simple Interactive Card with a button that opens a modal dialog with more information about Kyoto. In this case, the button is not stretched because that technique is only for links.
Kyoto, Japan
Japan's old capital, famous for its classical Buddhist temples, imperial gardens, geisha districts, and traditional tea ceremonies.
Link Card
Simple Interactive Card with a stretched link that when focused the entire card receives an outline as well to point out that the whole card is clickable via mouse.
Kyoto, Japan
Japan's old capital, famous for its classical Buddhist temples, imperial gardens, geisha districts, and traditional tea ceremonies.
Booking Card
Complex Interactive Card with two action buttons: one to save to favorites and the other to book the trip and opens a modal dialog with a stepper.
Kyoto: Fushimi Inari Path
Ready to start your journey? Select your dates, determine your duration, and reserve your passage through the iconic vermilion Torii gates.
Disclosure Card
Simple Interactive Card because it only contains one interactive element, an HTML details tag to expand more information.
Arashiyama Bamboo Grove
Kyoto, Japan Natural MonumentA historic walking path through thousands of towering stalks, renowned for its meditative natural soundscape.Arashiyama is famous for its towering bamboo paths. Walking through the soaring green stalks is like stepping into another world, where the wind rustles the leaves with a meditative sound. The Ministry of the Environment has named this grove one of the "100 Soundscapes of Japan".
History and Heritage:
Favored by Japanese nobles since the Heian Period (794–1185) for its serene autumn colors and cherry blossoms, this grove is part of a larger protected historic area.
Visitor Information and Tips:
- Best time to visit
- Early morning (before 8:00 AM) to avoid crowds and hear the rustling wind.
- Admission
- Free and open 24/7.
- Getting there
- A 10-minute walk from JR Saga-Arashiyama Station.
Accessibility Info:
The main walking path is paved, flat, and wheelchair-accessible. Accessible restrooms are located near the main entrance and Tenryu-ji Temple.
Eco-Tourism:
Please stay on the designated paths to prevent soil compaction and protect the fragile root systems of the giant bamboo.
Explore Arashiyama on WikipediaPromo Card with a Single CTA
Simple Interactive Card with a stretched link, so the whole card has a visible outline when the link receives focus.
The autumn table
Shop the collection: The autumn tableCategory Tile
A group of Simple Interactive Cards with their corresponding stretched link.
Product Card with a stretched link and two buttons: Add to Cart and Save
Complex Interactive Card with one stretched link that when focused an outline wraps the entire card and then two interactive buttons: one add to cart and the other to save to favorites.
Product
€24
Article Card with a Bookmark Button
Complex Interactive Card: a stretched link and a bookmark button.
Product Card with Variant and Quantity Pickers
Complex Interactive Card: one stretched link, a radio button group, a quantity stepper and a add-to-cart button. In this case, the link is not stretched as we mentioned in the explanation of this technique. Really complex but not impossible!
Pricing Plan with Two CTAs
Complex Interactive Card with two CTAs.
Pro
€12 per month
- 3 gifts
- Unlimited products
- Priority support
Order Card with Copyable Details
Complex Interactive Card with one button to copy the order number and two CTAs.
Out for delivery
Arriving today by 20:00
Order 402-1187-5530
Selectable Cards: Delivery Speed
WCAG 2.2 success criteria met
| SC | Level | Met by |
|---|---|---|
| 1.3.1 Info and Relationships | A | Every card is an <article> named by its heading through aria-labelledby |
| 2.1.1 Keyboard | A | Every action is a native <a> or <button> and receives focus with the keyboard |
| 2.4.3 Focus Order | A | Tab order follows the DOM and the stretched link adds no extra tab stop, then, if applicable, the focus is placed on the next interactive element inside the card |
| 2.4.4 Link Purpose (In Context) | A | Link text such as "Kyoto, Japan" and "Learn more about Kyoto" is clear next to the card's heading |
| 2.4.7 Focus Visible | AA | The whole card is outlined through :has(:focus-visible) when its stretched link has focus. Secondary controls have their own focus ring |
| 4.1.2 Name, Role, Value | A | Native a/button have role and name; native <details>/<summary> exposes expanded/collapsed state without ARIA; aria-pressed on the save toggle. |