Skip to main content

Command Palette

Search for a command to run...

Accessible card component

With pure (S)CSS (no JavaScript, the pseudo-content trick)

Published
2 min read
Accessible card component

When creating the card component, sometimes it’s advisable (or required by design) to make the whole card clickable. But how to do so without compromising the usability? Below I share a useful pseudo-content trick to make the whole card clickable and maintain its accessibility.

Problem statement

  • the whole card needs to be clickable
  • within the card there is also a “read more” link
  • inside a card, there are other separate links to different URL-s
  • you don’t want to harm the usability, e.g. allow the user to open all links in a new tab with a mouse right-click (context menu on touch devices)
  • support custom styles for hover and focus states
  • one last requirement: user should be able to select and copy the text within a card to the clipboard

How would you approach this task? Just a regular card component wrapped in an a element? Or maybe onclick in JavaScript directly on a div or article element (don’t do that!)?

How to handle such a case and maintain the accessibility in a simple and elegant way?

Possible solution

  1. Set position: relative on the container element
  2. Set position: absolute on the link’s :after pseudo-content
  3. Set value of 0 for top, right, bottom, and left properties on link’s :after pseudo-content
  4. Combine it with :focus-within and :hover to style different states
  5. Enhance it even further and make the text selectable with z-index
  6. If you want to add other links inside a card, use styles from card__separate to make it selectable (and/or clickable).

HTML

<div class="card">
  <p>
    <a href="#optional" class="card__separate">Optional</span>
  </p>
  <p>
    <span class="card__separate">Lorem ipsum</span>
  </p>
  <a href="#card-link" class="card__link">Link</a>
</div>

SCSS

.card {
  position: relative;
  border: 3px solid green;

  // Style hover and focus states.
  &:hover,
  &:focus-within {
    border-color: red;
  }

  // Make the content selectable.
  &__separate {
    position: relative;
    z-index: 2;
  }

  // Make the whole card clickable.
  &__link::after {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    content: "";
  }
}

Demo

Check clickable area (start with "Button 1") and try tab keyboard navigation in the following example:

Credits & further reading

I first saw the pseudo-content trick technique on Inclusive Components website. Check it out for other solutions to card issues and more inclusive components examples.