Bootstrap: Add a way to make an entire card into a hyperlink

Created on 19 Nov 2015  ·  38Comments  ·  Source: twbs/bootstrap

I think it would be very useful to be able to link entire cards. We tried doing this in our application, but realised all text got blue which is not ok for us.

I would expect them to behave similar to linked list group items, and think a card view is a nice alternative to plain lists.

css feature has-pr v4

Most helpful comment

I dont' really understand why the concept of card should be complicated by adding another abstraction (an A tag within a card DIV)
I think dev can swap the DIV with A and keep in my some restrictions (no links in link) and only some sugar class or rule for A element with .card class could be added to cover most of use-cases, including disabled card:
https://codepen.io/blazejewicz/pen/OQEeLR/?editors=0100
It covers inlined links (with inline buttons).
There is no change in component-level markup, high level concept: Want link? Use A instead of DIV and mind embedded content

<a href="#" class="card">
    <div class="card-body">
        <h5 class="card-title">Special title treatment</h5>
        <p class="card-text">With supporting text below as a natural lead-in to additional content.</p>
        <button class="btn btn-primary">Go somewhere</button>
    </div>
</a>

It also probably solves the problem outline below, on condition that we do not want to enforce impossible (links within links) and simply swap A with Button:

The issue is still that you are not allowed to wrap links in links. So that
approach makes it impossible to have secondary actions inside a linked card
unfortunately.

Thanks!

All 38 comments

Would it correct to say that you are essentially trying to use a card as a button?

Well, maybe.. Is that the analogy for List groups?

Anyway, my analogy would rather be Google Material Design Grid Lists. That is - having a card linking the "primary" action and hopefully optionally supporting secondary actions via extra buttons.

In my mind, I'd expect a grid list to be made up of multiple cards, not within a single card. Interesting use case though

Absolutely one card per item. Our test page looked something like this ![Image of card view]
screen shot 2015-11-20 at 22 31 12

X-Ref: #18170

Looks like Twitter's cards do this by putting the <a> as the first child within the card and then styling it as:

{
position: absolute;
top: 0; left: 0;
height: 100%; width: 100%;
}

Huh, that's a neat approach. Shits on text selection I imagine, but still neat :).

Shits on text selection I imagine

Indeed it does.

I have the same problem too, but the current workaround I have is:

<a href="#" class="card-block clearfix"> <div class="row"> <div class="col-12"> Card </div> </div> </a>

and then add a style that's like this
a.card-block { color: black; }

If anyone is interested we (quite some time back) did a version of what @cvrebert posted as Twitter's solution. Our solution enables the use of smaller linked areas inside a fully linked card, which is normally a problem otherwise

    .panel.card-linked {
        position: relative;

        > a.card-link {  /* This is the link of the entire card */
            position: absolute;
            height: 100%;
            width: 100%;
            z-index: 1;

            &:hover ~ .card-title {  /* Hints by underlining title that the card is clickable */
                text-decoration: underline;
            }
        }

        .card-image, .card-title, .card-actions, .card-body {   /* Basically all possible content of our panel /*
            pointer-events: none;  /* IMPORTANT! Lets clicks fall through */
            position: relative;
            z-index: 10;         /* IMPORTANT! Makes actual content be on top of linked card */

            .button, a {
                pointer-events: auto;    /* IMPORTANT! ... Except for buttons and links that should be clickable */
            }
        }

Example markup (we do a lot of custom styling, but you get the idea):

<div class="panel panel-defaultcard-linked">
    <a class="card-link" href="..."></a>
    <div class="card-title">
        <div class="card-title-texts">
            <h3>Heading</h3>
        </div>
    </div>
    <div class="card-actions">
        <button class="btn btn-link">
             Do stuff
        </button>
    </div>
    <div class="card-body">
          Content of panel
    </div>
</div>

Any updates on this ? we are trying to do the same. having a card deck with clickable cards that point to various internal pages.

https://css-tricks.com/snippets/jquery/make-entire-div-clickable/

The above link explains how to do it and it was very easy.

HTML

<div class="card myBox">
  blah blah blah.
  <a href="http://google.com">link</a>
</div>

jQuery

$(".myBox").click(function() {
  window.location = $(this).find("a").attr("href"); 
  return false;
});

With a project I'm working on in BootStrap 4 and many cards on it, worked like a charm.

@fco-daniel Yes but that isn't great semantically and also requires the user to have javascript on to click a simple link - so less than ideal solution IMHO.

Wouldn't the most semantically correct version be actually wrapping the whole card in an 'a href' ?

This works for me - it might break layouts when using only card decks, but seeing as they're not responsive and the solution for now seems to be wrapping each card in a column, it seems to work fine....

Hello,

I had this issue a as well and solved it by doing the following:

  1. Add role="button" to the parent tag.
  2. Register a click handler on aforementioned parent tag.

From MDN:

The button role should be used for clickable elements that trigger a response when activated by the user. On its own, role="button" can make any element ... appear as a button control to a screen reader. Additionally, this role can be used in combination with the aria-pressed attribute to create toggle buttons.

Source

Disclaimers:

I only tested this on the latest version of Chrome .

Note: Where possible, it is recommended to use native HTML buttons (

Source

  <div class="feature-card card text-center">
      <div role="button" @click="handleClick()" class="card-block">
        <h3 class="card-title">Title</h3>
        <p class="card-text">
            Text
        </p>
      </div>
      <div class="card-footer" style="border-top: none;">
        <button role="button" class="btn btn-secondary">Button</button>
      </div>
  </div>

Hope this helped 👍

Hey everyone !
I was trying Bootstrap and i'm having an issue with this code...
<ul class="list-group">
<li class="list-group-item list-group-item-primary">This is not working</li>
<li class="list-group-item list-group-item-danger">This is list group Li-2</li>
<li class="list-group-item list-group-item-info">This is list group Li-3</li>
<li class="list-group-item list-group-item-success">This is list group Li-4</li>
</ul>
the primary one is not working with just this case !!!!
Can you pls check it ?

Hi even I had the same problem. But https://codepen.io/mrotaru/pen/Gydrp helped me. Hope it helps other too.

Not sure if this is the best approach, but as we're building ng components we wrapped the entire card in an anchor and added extra rules e.g. 'a .card-default {}' to override. This seems most flexible when breaking down the parts.

The issue is still that you are not allowed to wrap links in links. So that
approach makes it impossible to have secondary actions inside a linked card
unfortunately.

/Victor

On 5 February 2018 at 02:49, Julian notifications@github.com wrote:

Not sure if this is the best approach, but as we're building ng components
we wrapped the entire card in an anchor and added extra rules e.g. 'a
.card-default {}' to override. This seems most flexible when breaking down
the parts.


You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/twbs/bootstrap/issues/18294#issuecomment-362960560,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAbbQ_lg16ArywLzuwcgFvxc9yhYH-lLks5tRl4ngaJpZM4Gl97_
.

In HTML5 seems we can insert <div> inside <a>, as described here: https://css-tricks.com/snippets/jquery/make-entire-div-clickable/
https://davidwalsh.name/html5-elements-links
http://html5doctor.com/block-level-links-in-html-5/
https://github.com/ckeditor/ckeditor-dev/issues/514

https://www.w3.org/TR/2011/WD-html5-20110525/text-level-semantics.html#dom-a-text

The a element may be wrapped around entire paragraphs, lists, tables, and so forth, even entire sections, so long as there is no interactive content within (e.g. buttons or other links). This example shows how this can be used to make an entire advertising block into a link

I dont' really understand why the concept of card should be complicated by adding another abstraction (an A tag within a card DIV)
I think dev can swap the DIV with A and keep in my some restrictions (no links in link) and only some sugar class or rule for A element with .card class could be added to cover most of use-cases, including disabled card:
https://codepen.io/blazejewicz/pen/OQEeLR/?editors=0100
It covers inlined links (with inline buttons).
There is no change in component-level markup, high level concept: Want link? Use A instead of DIV and mind embedded content

<a href="#" class="card">
    <div class="card-body">
        <h5 class="card-title">Special title treatment</h5>
        <p class="card-text">With supporting text below as a natural lead-in to additional content.</p>
        <button class="btn btn-primary">Go somewhere</button>
    </div>
</a>

It also probably solves the problem outline below, on condition that we do not want to enforce impossible (links within links) and simply swap A with Button:

The issue is still that you are not allowed to wrap links in links. So that
approach makes it impossible to have secondary actions inside a linked card
unfortunately.

Thanks!

I'm using the following for clickable card, and link in link.

<div class="card">
    <img src="/public/img34.png" alt="Foo is Bar banner"/>
    <a href="/category/news" class="category">news</a>
    <h2>Foo is Bar !</h2>
    <p>lorem ipsum sir dalet ... </p>
    <a href="/article/foo-is-bar" class="read-more">Read more</a>
</div>
.card {
    position: relative;
}

.category {
    position: relative;
    z-index: 2;
}

.read-more:after {
    content: '';
    position: absolute;
    z-index: 1;
    top: 0; left: 0; bottom: 0; right: 0;
}

@azopyros How would you change the above if you didn't need to display 'Read More' but still maintain the clickability of the card?

@oyeanuj I've just tested on codepen (chrome) it works if the last link stay empty
<a href="/article/foo-is-bar" class="read-more"></a>
But I think each link need to have a little sentence, for screen reader, so instead of remove the 'Read More', you can hide it :

.read-more {
  display: block;
  height: 0px;
  color: transparent;
}

But i'm not a big fan of hide links.
Any suggestions ?

The Problem with all solutions (except fco-daniel's) is the loss of semantic meaning of the a-tag and because of that, the potential SEO problems.

If you do:

<div>
    <h1><a href='#'>Link-Text</a></h1>
    <p>Some other Text</p>
    <p class="smallerText">More Text</p>
</div>

Google and all other bots understand, that "Linkt-Text" is the link text and therefore the most important info for SEO.

If you just wrap a a-tag around something (for example a card):

<a href='#'>
    <div>
        <h1>Link-Text</h1>
        <p>Some other Text</p>
        <p class="smallerText">More Text</p>
    </div>
</a>

or if you create an empty a-tag

<div>
    <a href='#' style='position: absolute; top: 0; left: 0; height: 100%; width: 100%;'></a>
    <h1>Link-Text</h1>
    <p>Some other Text</p>
    <p class="smallerText">More Text</p>
</div>

How should Google (or any maschine) understand, which is the main info, the link text? Is it "Link-Text" or "Some other Text" or "More Text"? Nobody knows.

So from SEO perspektive, the solution of @fco-daniel is the best one.

Hey guys I'm having almost same problem , But I'm putting link on the image in card but it's not working kindly give me a solution ASAP . Currently I'm using the following code but it's not working :
And One more thing I'm using overly effect too.

  <div class="card  text-white">
               <a href="Photography-Galleries.html"><img class="card-img" src="img/All- 
                    covers/COVER.jpg" alt="A&Bsite"></a>
               <div class="card-img-overlay ovl">
                   <h4 class="card-title mt-5 pt-3"> A-B site</h4>
                   <p class="card-text">A-B Gallery</p>
                   <p class="card-text">Check it Out</p>
               </div>
      </div>

CSS

.ovl {
opacity: 0;
transition: 1s;
}
.ovl:hover {
opacity: 1;
cursor: pointer;
background-color: rgb(0,0,0,0.6);
}

The Problem with all solutions (except fco-daniel's) is the loss of semantic meaning of the a-tag and because of that, the potential SEO problems.

This wasn't a reason to stop the feature from being added to list group items, so why should it be here?

However could an SEO bot determine what the most important text is inside a block-level element? Especially when it contains an h1 tag? Yes that would be a real-headscratcher.

We all know developers have been abusing block-level elements as links for ages, it's not like Google is hearing of this for the first time. It's not that hard to figure out that the biggest text is the most important text if the developer has ANY intention of being user-friendly, and search engines will adapt to that.

It's great that people care about the web being SEO-compatible, but it should be the other way around, SEO should be web-compatible.

It's great that people care about the web being SEO-compatible, but it should be the other way around, SEO should be web-compatible.

Yes. And there should be peace everywhere, but thats not the case in the real world, so we have to deal with it. And as long as your business depends on high SERP placement, you have to deal with SEO.

Nobody really knows, how such things affect seo. The only (but old) answer to this question I could find is this one: https://productforums.google.com/forum/#!topic/webmasters/HOVcX-hK6hc/discussion

So, yes you CAN use it, but its better to make it clear and maschine readable. At least, when using a-tag as block level, provide a title-tag with the link text, so you should be fine,

coming in late, but: as noted early on in this discussion, CSS solutions that overlay/expand a link to cover the whole card generally break text selection. Also, there can be problems in situations where a card actually contains more than one link (one link being the "primary", but then some additional link). In general, I'd say a JS-based solution (like something along the lines of https://codepen.io/patrickhlauke/pen/vpQNgJ) would be my preferred approach here.

if having secondary links inside the card is not a concern / won't ever happen, then wrapping the whole card in a link (and making sure the styling of link text doesn't then affect the look of the whole card's content) is an option, but note that this doesn't always play nice with assistive technologies (who will then, as you're reading through the content of the card, keep announcing that everything is a link, continuously)

I have the simple issue of wanting the whole card to be a link in certain situations, and not intending to have a link within a link, so the following suggested solution may be too simple (and semantically wrong) for the discussion above, but I spent a while looking until I tried this. Since you can't make the card an a tag without losing style, I wrapped the entire contents of the card div in an a tag, and apply a new card-link class

.card.card-link a {
    color: inherit;
    text-decoration: none;
}

And usage is:

<div class="card card-link">
  <a href="examples.html">
    <img class="card-img-top" src="images/example_400x200.jpg" alt="example img">
    <div class="card-body">
      <h5 class="card-title">Example title</h5>
      <p class="card-text">This is just a simple example</p>
    </div>
  </a>
</div>

An example of it is use with some additional styling is on the first image card here http://www.lft-concept.co.uk/barebones.html

I agree with @patrickhlauke a JS solution seems better

CSS solutions that overlay/expand a link to cover the whole card generally break text selection

You 're not able to select the text in the js example either, you'll be redirected if you try to do that.

a JS solution seems better

A JS solution will prevent the native advantages like ⌘-click or ctrl-click to open in a new tab, dragging the link to a new tab, right click for link options, cursor:pointer by default, link preview in the browser,...

@patrickhlauke & @Johann-S have you checked out https://github.com/twbs/bootstrap/pull/26184 yet? This provides css-only solution with all the native advantages.

You 're not able to select the text in the js example either, you'll be redirected if you try to do that.

It's possible to add extra checks around that to allow it, but yeh my slapped together demo there currently doesn't.

A JS solution will prevent the native advantages like ⌘-click or ctrl-click to open in a new tab, dragging the link to a new tab, right click for link options, cursor:pointer by default, link preview in the browser,...

If you go to the actual link, you get all of that.

Anyway, IF we can guarantee that there won't be another secondary link in a card (or strongly advise against doing it, since having nested links, or weird stuff like buttons inside links, is not valid), then... shrug

26184 doesn't wrap the card in a link, but uses a pseudo element which is stretched over the card (or other components).

Seems an awesome solution @MartijnCuppens from a quick view 👍

26184 is merged and will provide a solution for this in v4.3.

A solution with a little javascript :

<article>
  <div class="post-link card d-flex flex-lg-row flex-sm-column pt-0 mb-4 p-2">

      <div class="align-items-center">
        <?php the_post_thumbnail('medium', array( 'class' => 'card-img-left flex-auto d-none d-md-block')); ?>
      </div>

      <div class="card-block d-flex flex-column px-3 pt-0 pb-2 flex-grow-1">
        <h3 class="card-title text-capitalize entry-title mb-2">
          <?php the_title(); ?>
        </h3>
        <?php the_excerpt(); ?>
        <div class="d-flex flex-row flex-grow-1 align-items-end justify-content-end">
            <a class="btn btn-primary btn-sm mt-3" href="<?php esc_url( the_permalink() ) ?>" role="button">Continue Reading</a>
        </div>
      </div>
    </div>
</article>

Javascript :

/**
 * Redirect to a post when a card is clicked in categories template
 */

$(".post-link").click(function() {
  window.location = $(this).find("a").attr("href");
  return false;
});

@boutmos Why you wrote this here? Since version 4.3 we have "stretched links" utility class. See more: https://getbootstrap.com/docs/4.4/utilities/stretched-link/ And for older Bootstrap you can replicate same CSS yourself.

Was this page helpful?
0 / 5 - 0 ratings