Lesson 9: Cards

Cards in Bootstrap

Cards actually fall under the "component" category but they are so quirky that I thought a separate lesson might be in order. Cards were designed by marketing specialists. You have an image, text descriptions, and call to action in a self-contained display element. They really are the second bread and butter of Bootstrap (after the grid) simply because they are so darned useful. The "card" isn't really a new thing in web design but Bootstrap just makes it easy to create one without custom CSS.

For these examples I will be using random images from Lorum Picsum and forcing most of them into a column to constrain their size. Like most Bootstrap elements, Cards will take up 100% of their parent container.

A Basic Card

Card title

Some quick example text to build on the card title and make up the bulk of the card's content.

<div class="card">
  <img src="https://picsum.photos/300/200?random=1" class="card-img-top" alt="...">
  <div class="card-body">
    <h5 class="card-title">Card title</h5>
    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
  </div>
  <div class="card-footer">
  	<a href="#" class="btn btn-primary">Go somewhere</a>
  </div>
</div>

Card Layout: Option 1 - Sizing Utilities

Just want to place a card right in the middle of your page and make it, say 50% of the page? You can do this very easily with Bootstrap's sizing utilities. The class naming convention is very simple. H for height, or W for width. Then we choose a number in quarters....eg.: h-100 or w-75. See how those work? You can apply them to elements and they will apply the specified sizing to the element based on the parent element. These aren't 100% fool-proof and it will take some trial and error to get them to do what you want sometimes.

Another thing that is helpful is using Bootstrap's margin utilities to center an item. No need for a centered DIV. This applies to, in this case, a card sitting all alone with no container, row, or columns. Just add mx-auto to the class of the element and will center. Remember. M is "margin. X is the X axis (left to right, like crossing the street). Auto gives you margins equal from both left and right of the parent container.

...
Card title

Some quick example text to build on the card title and make up the bulk of the card's content.

Go somewhere
<div class="card w-50 mx-auto">
  <img src="https://picsum.photos/600/300?random=4" class="card-img-top" alt="...">
  <div class="card-body">
    <h5 class="card-title">Card title</h5>
    <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
    <a href="#" class="btn btn-primary">Go somewhere</a>
  </div>
</div>

Card Layout: Option 2 - Grid System

Setting cards in a grid can be a challenge. There are actually several ways to align cards into a grid but not all of them are self-evident. the first way is to use the standard grid layout with Containers, Rows, and columns. This works perfectly when your images are all the same size...when you stray from that, the cards can all be different sizes - as seen in the example below.

Card title

Some quick example text to build on the card title and make up the bulk of the card's content.

Card title

Some quick example text to build on the card title and make up the bulk of the card's content.

Card title

Some quick example text to build on the card title and make up the bulk of the card's content.

Not at all appealing....However, there is a very simple way around this. Set the class h-100 on the card DIV. This sizing utility will set all of the cards to the height of the parent container. In this case the parent is a row so as the cards stretch the row height the cards will fit to match that height.

Card title

Some quick example text to build on the card title and make up the bulk of the card's content.

Card title

Some quick example text to build on the card title and make up the bulk of the card's content.

Card title

Some quick example text to build on the card title and make up the bulk of the card's content.

Now, if you have design OCD like I do, those pictures look wrong being different sizes. So, there is a "hack" we can apply that works perfectly to correct this.

Card title

Some quick example text to build on the card title and make up the bulk of the card's content.

Card title

Some quick example text to build on the card title and make up the bulk of the card's content.

Card title

Some quick example text to build on the card title and make up the bulk of the card's content.

Much better! I think this is worth a snippet now....Info on how this "hack" works below.



<style>
.card-img-top-fix {
    	width: 100%;
    	height: 15vw;
    	object-fit: cover;
	}
</style>

<div class="container-fluid">
    <div class="row">
        <div class="col-xl-4">
            <div class="card h-100">
            <img src="https://picsum.photos/300/200?random=1" class="card-img-top card-img-top-fix" alt="...">
            <div class="card-body">
            <h5 class="card-title">Card title</h5>
            <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
            </div>
            <div class="card-footer">
            <a href="#" class="btn btn-primary">Go somewhere</a>
            </div>
            </div>
        </div>
        <div class="col-xl-4">
            <div class="card h-100">
            <img src="https://picsum.photos/300/200?random=2" class="card-img-top card-img-top-fix" alt="...">
            <div class="card-body">
            <h5 class="card-title">Card title</h5>
            <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
            </div>
            <div class="card-footer">
            <a href="#" class="btn btn-primary">Go somewhere</a>
            </div>
            </div>
        </div>
        <div class="col-xl-4">
            <div class="card h-100">
            <img src="https://picsum.photos/300/200?random=3" class="card-img-top card-img-top-fix" alt="...">
            <div class="card-body">
            <h5 class="card-title">Card title</h5>
            <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
            </div>
            <div class="card-footer">
            <a href="#" class="btn btn-primary">Go somewhere</a>
            </div>
            </div>
        </div>
    </div>
</div>

That CSS style is what does the trick with the image sizing. There are a couple of thoughts you might consider when using it.

  1. The class name card-img-top-fix is what I use when I don't want to apply it to every card. You can easily just keep the name card-img-top and it will apply to every card.
  2. This little hack will mess things up on mobile devices - the images will appear squashed. You can apply the class within a custom css file set to appear only on Large and Extra-Large breakpoints.

Card Layout: Option 3 - Card Groups

A card group is a series of cards that are attached to each other - separated only by a border.

...
Card title

This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.

Last updated 3 mins ago

...
Card title

This card has supporting text below as a natural lead-in to additional content.

Last updated 3 mins ago

...
Card title

This is a wider card with supporting text below as a natural lead-in to additional content. This card has even longer content than the first to show that equal height action.

Last updated 3 mins ago

<div class="card-group">
  <div class="card">
    <img src="https://picsum.photos/300/175?random=1" class="card-img-top" alt="...">
    <div class="card-body">
      <h5 class="card-title">Card title</h5>
      <p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
      <p class="card-text"><small class="text-muted">Last updated 3 mins ago</small></p>
    </div>
  </div>
  <div class="card">
    <img src="https://picsum.photos/300/175?random=2" class="card-img-top" alt="...">
    <div class="card-body">
      <h5 class="card-title">Card title</h5>
      <p class="card-text">This card has supporting text below as a natural lead-in to additional content.</p>
      <p class="card-text"><small class="text-muted">Last updated 3 mins ago</small></p>
    </div>
  </div>
  <div class="card">
    <img src="https://picsum.photos/300/175?random=3" class="card-img-top" alt="...">
    <div class="card-body">
      <h5 class="card-title">Card title</h5>
      <p class="card-text">This is a wider card with supporting text below as a natural lead-in to additional content. This card has even longer content than the first to show that equal height action.</p>
      <p class="card-text"><small class="text-muted">Last updated 3 mins ago</small></p>
    </div>
  </div>
</div>

Card Layout: Option 4 - Card Decks

A card "deck" is a group of cards that are NOT connected. This layout has a lot of great uses.

...
Card title

This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.

Last updated 3 mins ago

...
Card title

This card has supporting text below as a natural lead-in to additional content.

Last updated 3 mins ago

...
Card title

This is a wider card with supporting text below as a natural lead-in to additional content. This card has even longer content than the first to show that equal height action.

Last updated 3 mins ago


Card Layout: Option 5 - Masonry Grid

This one is a lot of fun. You can loop over a series of cards and have them displayed in a "masonry" grid. Masonry in web design is cascading grid that will attempt to fit everything into the defined space regardless of height or width. It's pretty neat, really. Check this out.

...
Card title that wraps to a new line

This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.

Someone famous in Source Title
...
Card title

This card has supporting text below as a natural lead-in to additional content.

Last updated 3 mins ago

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat.

Someone famous in Source Title
Card title

This card has a regular title and short paragraphy of text below it.

Last updated 3 mins ago

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.

Someone famous in Source Title
...
Card title

This is another card with title and supporting text below. This card has some additional content to make it slightly taller overall.

Last updated 3 mins ago

<div class="card-columns">
  <div class="card">
    <img src="https://picsum.photos/300/175?random=1" class="card-img-top" alt="...">
    <div class="card-body">
      <h5 class="card-title">Card title that wraps to a new line</h5>
      <p class="card-text">This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
    </div>
  </div>
  <div class="card p-3">
    <blockquote class="blockquote mb-0 card-body">
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p>
      <footer class="blockquote-footer">
        <small class="text-muted">
          Someone famous in <cite title="Source Title">Source Title</cite>
        </small>
      </footer>
    </blockquote>
  </div>
  <div class="card">
    <img src="https://picsum.photos/300/175?random=2" class="card-img-top" alt="...">
    <div class="card-body">
      <h5 class="card-title">Card title</h5>
      <p class="card-text">This card has supporting text below as a natural lead-in to additional content.</p>
      <p class="card-text"><small class="text-muted">Last updated 3 mins ago</small></p>
    </div>
  </div>
  <div class="card bg-primary text-white text-center p-3">
    <blockquote class="blockquote mb-0">
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat.</p>
      <footer class="blockquote-footer text-white">
        <small>
          Someone famous in <cite title="Source Title">Source Title</cite>
        </small>
      </footer>
    </blockquote>
  </div>
  <div class="card text-center">
    <div class="card-body">
      <h5 class="card-title">Card title</h5>
      <p class="card-text">This card has a regular title and short paragraphy of text below it.</p>
      <p class="card-text"><small class="text-muted">Last updated 3 mins ago</small></p>
    </div>
  </div>
  <div class="card">
    <img src="https://picsum.photos/300/175?random=3" class="card-img-top" alt="...">
  </div>
  <div class="card p-3 text-right">
    <blockquote class="blockquote mb-0">
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p>
      <footer class="blockquote-footer">
        <small class="text-muted">
          Someone famous in <cite title="Source Title">Source Title</cite>
        </small>
      </footer>
    </blockquote>
  </div>
  <div class="card">
    <div class="card-body">
      <h5 class="card-title">Card title</h5>
      <p class="card-text">This is another card with title and supporting text below. This card has some additional content to make it slightly taller overall.</p>
      <p class="card-text"><small class="text-muted">Last updated 3 mins ago</small></p>
    </div>
  </div>
</div>

Card Layout: Option 6 - Perfect Grid

This one is the most useful of the group if we really look at it hard. If you want to display database content as cards instead of row by row in a table, you can do it with this "perfect grid" layout.

Now, the term, "perfect" may seems like a bold statement. And it is if you fail to apply the hacks we used on the card images and to set equal heights. This one uses the row-cols-{number} and/or row-cols-{breakpoint}-{number} classes which set the number of columns within the row dynamically. So you can theoretically feed 100 records from a database into this layout and it will give you a perfect grid containing 100 cards.

...
Card title

This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.

...
Card title

This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.

...
Card title

This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.

...
Card title

This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.

...
Card title

This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.

...
Card title

This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.

...
Card title

This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.

...
Card title

This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.

<div class="row row-cols-2 row-cols-md-3">
  <div class="col mb-4">
    <div class="card">
      <img src="https://picsum.photos/300/175?random=1" class="card-img-top" alt="...">
      <div class="card-body">
        <h5 class="card-title">Card title</h5>
        <p class="card-text">This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
      </div>
    </div>
  </div>
  <div class="col mb-4">
    <div class="card">
      <img src="https://picsum.photos/300/175?random=2" class="card-img-top" alt="...">
      <div class="card-body">
        <h5 class="card-title">Card title</h5>
        <p class="card-text">This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
      </div>
    </div>
  </div>
  <div class="col mb-4">
    <div class="card">
      <img src="https://picsum.photos/300/175?random=3" class="card-img-top" alt="...">
      <div class="card-body">
        <h5 class="card-title">Card title</h5>
        <p class="card-text">This is a longer card with supporting text below as a natural lead-in to additional content.</p>
      </div>
    </div>
  </div>
  <div class="col mb-4">
    <div class="card">
      <img src="https://picsum.photos/300/175?random=4" class="card-img-top" alt="...">
      <div class="card-body">
        <h5 class="card-title">Card title</h5>
        <p class="card-text">This is a longer card with supporting text below as a natural lead-in to additional content. This content is a little bit longer.</p>
      </div>
    </div>
  </div>
</div>

In the visual demo above, I used ColdFusion to loop over the cards and give me 8 of them but the snippet only gives you 4. I think you get the idea. So, in closing, cards are super useful, very attractive, and not overly complex to use. Once you get the hang of it, you will know which layout will suit your purpose best and have it working in minutes.