DEV Community

Cover image for Clickable Card Patterns and Anti-Patterns
Michael Mathews
Michael Mathews

Posted on

Clickable Card Patterns and Anti-Patterns

A frequent design requirement is to maximize the interaction area by making an entire card container clickable, for example, linking to a detail page.

However, when this approach is combined with card text that itself may contain links (such as to an author's profile, category tags, or action buttons), it creates a conflict that violates HTML semantics and could compromise accessibility.

The Problem

The core of the problem lies in attempting to nest interactive content. Consider the following structure used to make a card fully clickable:

<!-- ⚠️ Don't do this -->
<a href="/article/card-detail">
  <div class="card">
    <p>Author: <a href="/authors/jamil">Jamil</a>.</p>
  </div>
</a>
Enter fullscreen mode Exit fullscreen mode

This structure is problematic for at least two reasons:

  1. The HTML Specification: A hyperlink (an <a> element that has an href attribute) is interactive content. According to the HTML Living Standard, an interactive element must not contain other interactive or focusable elements as descendants, which effectively prohibits a hyperlink from containing elements like <button>, <input>, or another <a href="…">.
  2. Assistive Tech Trip-Ups: For users relying on screen readers or keyboard navigation, this nesting creates confusion and redundancy. Assistive technologies encounter two different links with overlapping hit areas. Tabbing behavior becomes unpredictable, and the link name (as read out by screen readers) becomes the card's entire contents. Not great!

Use the Stretched Link Pattern

The recommended approach to achieving a fully clickable card—while maintaining semantic validity and good accessibility—is to use the Stretched Link Pattern, which leverages CSS positioning and stacking context (z-index).

The goal is to ensure that only the primary element (e.g., the card title) is wrapped in the "more information" link, and then use CSS to expand its hit area to cover the entire card, deliberately positioning other interactive elements above it.

1. Semantic HTML Structure

The recommended structure keeps the primary link and secondary interactive elements separate and non-nested.

<div class="card">
  <!-- 💁‍♂️ Use this as the primary link for the whole card. -->
  <a href="/article/card-detail" class="card__main-link">
    <h3>Article Title</h3>
  </a>

  <img src="article-thumb.jpg" alt="Article Thumbnail">

  <!-- 👇 More links may be in the body of the card. -->
  <p>Author: <a href="/authors/jamil">Jamil</a>.</p>
</div>

Enter fullscreen mode Exit fullscreen mode

2. CSS Implementation: Stacking Context Management

We use position: absolute and z-index to manage layer order, ensuring the stretched link remains visually active while internal links retain interaction priority.

Element Key CSS Properties Function
.card position: relative; Establishes the stacking context for absolute children.
.card__main-link::after content: ''; position: absolute; inset: 0; z-index: 1; Stretches the (invisible) link across the whole card to act as the primary click target.
Inner Interactive Elements (a, button) position: relative; z-index: 2; Lifts these elements above the stretched link's hit area, preserving their intended functionality and focus order.
/* 1. The parent element context */
.card {
  position: relative; 
  /* Other styles (border, padding, etc.) */
}

/* 2. The stretched click area */
.card__main-link::after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1; /* Less than the inner interactive elements */
  pointer-events: auto; 
}

/* 3. Priority for Internal Interactive Elements */
.card p a,
.card button {
  position: relative;
  z-index: 2; /* Above the stretched click area */
}

Enter fullscreen mode Exit fullscreen mode

Conclusion

Using the Stretched Link Pattern resolves the conflict between design intent (making the card itself fully clickable) and technical compliance (avoiding nested interactive elements).

By prioritizing correct HTML semantics and managing the stacking context, developers and designers can ensure that components are robust, fully accessible, and provide a predictable user experience.


Photo by gabby-k

Top comments (0)