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.
The Start
First, let's get a good looking card we can use. Let's take this one from the Le Wagon UI Kit.
Looks sharp, right? But 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 %>
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
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>
Top comments (3)
Great article!
I noticed a potential accessibility concern with making the entire card clickable using an absolutely positioned link. While it works visually, screen readers and keyboard navigation may miss the link since it doesn't contain readable text.
To fix this, you can use an aria-label and ensure the link is meaningful. Here's an example:
I was looking for water and I found gold. Awesome trick. It works flawlessly.
Hey, what a cool trick. I never would have imagined such a simple solution for this issue. I tried it and it worked perfectly. Thanks man!!!