View all posts

Interactive Cards

Table of contents
  1. Introduction
  2. Static Cards
    1. Anatomy
    2. Code example
  3. Interactive Cards
    1. Anatomy Interactive Cards
    2. Simple Interactive Cards
    3. Complex Interactive Card
    4. Complex Interactive Cards should NOT have a stretched link when:
  4. Use Cases
    1. Change the Image When Hovering or Focusing the Interactive Card
    2. Action Card: Save the Product to Favorites
    3. Button Only Interactive Card
    4. Link Card
    5. Booking Card
    6. Disclosure Card
    7. Promo Card with a Single CTA
    8. Category Tile
    9. Product Card with a stretched link and two buttons: Add to Cart and Save
    10. Article Card with a Bookmark Button
    11. Product Card with Variant and Quantity Pickers
    12. Pricing Plan with Two CTAs
    13. Order Card with Copyable Details
    14. Selectable Cards: Delivery Speed
  5. WCAG 2.2 success criteria met
DISCLAIMER: in this post I used AI generated images. Could I have used images from the internet? yes, but I did not. I won't make any disclaimer about the writing because as you might have noticed, it is not perfect and has a very informal and messy tone. English is not my first language and I only use it to communicate my ideas, my knowledge, etc so as long as you understand what I am trying to say, for me it is a win! I understand that reading a text generated by AI shuts the brain; it is like you automatically decide to avoid it. Bah, at least that is what happens to me.

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:

  1. Know the difference between and . (pppss, you can learn the difference here)
  2. 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

1aria-labelledby="title"2

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.(...)

  1. <article>

    wraps the whole card.

  2. aria-labelledby="title"

    its value should be an IDREF pointing to the `id` value on the main heading inside the article.

  3. <h3 id="title">

    main topic of the card.

  4. <p>

    a description or extra information related to the topic that the article groups.

The information from this example was extracted from Wikipedia

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.

  1. First Layer: <article>

    Should be a plain article. You should not force the interaction by adding a tabindex="0" or tabindex="-1" to force the focus programmatically or a onclick to force the functionality in JavaScript. The accessible name should be passed by adding an aria-labelledby pointing to the IDREF in the main heading of the card. The final step that will do the magic later is adding in CSS a position: 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;
    }
  2. 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>
  3. Third Layer: ::after to stretch the action target

    An 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:hover fires anywhere on it and the whole article should have a position: relative. Screen reader users interact with the real link in layer 2. pss, you can make the text selectable by adding user-select: text; to force it.

    .card__link::after {
      content: "";
      position: absolute;
      inset: 0;
    }
    
    article {
      position: relative;
    }
    
    article > p {
      user-select: text;
    }
    
  4. 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 ::after pseudo-element with position: 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

  1. Change the Image When Hovering or Focusing the Interactive Card

    Simple Interactive Card

    Hover the entire card or focus the main link to change the image of the card. This functionality is purely decorative and does not add any extra information and it is a demostration of stretched link card.

  2. 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.

  3. 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.

    About Kyoto

    Kyoto served as Japan's imperial capital for over a thousand years. Today it is best known for its seventeen UNESCO-listed sites, including Kinkaku-ji and Kiyomizu-dera, and for the lantern-lit alleys of the Gion geisha district.

  4. 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.

  5. 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.

    Fushimi Inari Torii Gates Pathway

    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.

  6. 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 Wikipedia
  7. Promo 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.

  8. Category Tile

    A group of Simple Interactive Cards with their corresponding stretched link.

  9. 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

    More information about the product

    €24

  10. Article Card with a Bookmark Button

    Complex Interactive Card: a stretched link and a bookmark button.

  11. 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!

    Product

    €69

    Colour: Sand
    Quantity

  12. Pricing Plan with Two CTAs

    Complex Interactive Card with two CTAs.

  13. Order Card with Copyable Details

    Complex Interactive Card with one button to copy the order number and two CTAs.

  14. Selectable Cards: Delivery Speed

    Delivery speed

WCAG 2.2 success criteria met

SCLevelMet by
1.3.1 Info and RelationshipsAEvery card is an <article> named by its heading through aria-labelledby
2.1.1 KeyboardAEvery action is a native <a> or <button> and receives focus with the keyboard
2.4.3 Focus OrderATab 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)ALink text such as "Kyoto, Japan" and "Learn more about Kyoto" is clear next to the card's heading
2.4.7 Focus VisibleAAThe 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, ValueANative a/button have role and name; native <details>/<summary> exposes expanded/collapsed state without ARIA; aria-pressed on the save toggle.