Make a Card Clickable

How to nest an entire card inside of a link

On the surface, this one seems straight forward: a grid of clickable cards, easy right? Well as you may have seen when we use an anchor tag, it comes with some default styling we don't necessary want.

This isn't very sexy, is it?

The Start

First, let's get a good looking card we can use. Let's take this one from the Le Wagon UI Kit.

Title here

Short description here!

£99.99

Looks sharp, right? But try to click it, still no link yet.

Let's see what happens when we wrap the same code inside of an anchor tag.

<a href="#">
  <!-- card html -->
</a>

Or the Rails way...

<%= link_to card_path do %>
  <!-- card html -->
<% end %>

Title here

Short description here!

£99.99

The Problem

This just ruined all of our style. We can click on it, but all the text had that text-underline and unfortunate blue. So, let's take a step back and take a different approach.

The Solution

This might seem strange at first, but we're not going to wrap the card in the link. We're going three dimensional here. We're going to place the link over the card.


First: we build a link inside of our card with no text inside of our link to display. Let's also create a new class called card-link

<a href="#" class='card-link'></a>

Or the Rails way...

<%= link_to '', card_path, class: 'card-link'  %>

Second: we make our card position: relative, then we can make our link position: absolute


Third: we stretch the link over the entirety of the card. Our link won't take up an space, so we have to give it some special css attributes. Pin it to the corners then stretch over the entire width like this:

top: 0;
bottom: 0;
left: 0;
width: 100%;

Now we have a clickable card that looks like our original:

Title here

Short description here!

£99.99

The CSS

.card-trip {
  overflow: hidden;
  background: white;
  box-shadow: 0 0 15px rgba(0,0,0,0.2);
  position: relative; // NEEDED FOR THE LINK
}

.card-trip > img {
  height: 200px;
  width: 100%;
  object-fit: cover;
}

.card-trip h2 {
  font-size: 16px;
  font-weight: bold;
  margin: 0;
}

.card-trip p {
  font-size: 12px;
  opacity: .7;
  margin: 0;
}

.card-trip .card-trip-infos {
  padding: 16px;
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  position: relative;
}

.card-trip-infos .card-trip-user {
  position: absolute;
  right: 16px;
  top: -20px;
  width: 40px;
}

// To stretch the link on top of the card div
.card-link {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 100%;
}

The ERB Way

<div class="card-trip">
  <%= image_tag "https://raw.githubusercontent.com/lewagon/fullstack-images/master/uikit/greece.jpg" %>
  <div class="card-trip-infos">
    <div>
      <h2>Title here</h2>
      <p>Short description here!</p>
    </div>
    <h2 class="card-trip-pricing">£99.99</h2>
    <%= image_tag "https://kitt.lewagon.com/placeholder/users/dmbf29", class: "card-trip-user avatar-bordered" %>
  </div>
  <%= link_to '', card_path(element), class: 'card-link'  %>
  <!-- You need to replace card_path with your appropriate route  -->
</div>

The Pure HTML way

<div class="card-trip">
  <img src="https://raw.githubusercontent.com/lewagon/fullstack-images/master/uikit/greece.jpg" />
  <div class="card-trip-infos">
    <div>
      <h2>Title here</h2>
      <p>Short description here!</p>
    </div>
    <h2 class="card-trip-pricing">£99.99</h2>
    <img src="https://kitt.lewagon.com/placeholder/users/dmbf29" class="card-trip-user avatar-bordered" />
  </div>
  <a href="#" class='card-link'></a>
  <!-- You need to replace the href # with your appropriate route -->
</div>