Bootstrap: Responsive Card Decks

Created on 18 Jul 2016  Â·  56Comments  Â·  Source: twbs/bootstrap

The previous issue about this was #19826 but got closed by the reporter without getting the ability to receive proper feedback.

It would really great to be able to define how many cards per row you maximum want. The card deck is an awesome (and only way in BS) to get the same height of all the items in the row. But the main problem is that if you have more then 2-3 items in it, it already starts to become squeezed together on smaller screens.

In the previous ticket it was mentioned to use something like card-deck cards-sm-6 cards-md-4 cards-lg-3 but maybe something like card-deck-md-3 card-deck-lg-4 where you define the amount of columns you want could work too. As people may want to include 5 columns and that doesn't work well with the grid system.

css feature v4 v5

Most helpful comment

I've managed to find a way of having cards in the responsive system while having equal heights just like a deck. I found most of the solution here, option 4:
https://scotch.io/bar-talk/different-tricks-on-how-to-make-bootstrap-columns-all-the-same-height

Not all of this CSS is required as some options are already enabled by Bootstrap. I enable it by adding the CSS class 'equal-height' to a row which then has cards contained within responsive columns:

.row.equal-height {
    display: flex;
    flex-wrap: wrap;
}
.row.equal-height > [class*='col'] {
    display: flex;
    flex-direction: column;
}

.card {
    flex: 1;
}

basic html structure:

<div class="row equal-height">
    <div class="col-12 col-md-6">
        <div class="card">
            <!-- Your card content here -->
        </div>
    </div>
</div>

edit: the value 'flex: 1 0 0;' I was using on class .card was causing problems. Safari is happy with 0 but Chrome expects 0%. Being honest I don't understand what flex-shrink and flex-basis do but specifying flex: 1; so only setting the flex-grow value works in all the browsers I tested.

edit2 June 2020: I've come back as I needed this on another project, I see this is closed and a solution has been found for responsive columns but they don't give you equal height. I used my fix again and realised it didn't work if you just used col, not col-(some modifier). I've changed the code to fix that, match 'col' not 'col-'.
But now the footer is broken, if I find a fix I'll post it.

All 56 comments

Funny enough, the entire reason I opted for trying out Bootstrap 4's alpha was to use card decks for same-height containers, but when I realized I couldn't adjust where the breakpoint occurs, I had to step back and roll my own CSS anyway. Welp! :P

Long-winded +1, basically.

When using flexbox, columns get the same height anyway, so you could probably get the effect you are looking for by just using standard columns?

This works for me

<div class="row">
    <div class="col-sm-6 col-md-4 col-lg-3">
        <div class="card">
            <div class="card-block">
                <h3 class="card-title">The title</h3>
                <div class="card-text">
                    The text
                </div>
            </div>
        </div>
    </div>
    <div class="col-sm-6 col-md-4 col-lg-3">
        <div class="card">
            <div class="card-block">
                <h3 class="card-title">The title</h3>
                <div class="card-text">
                    The text
                </div>
            </div>
        </div>
    </div>
    <div class="col-sm-6 col-md-4 col-lg-3">
        <div class="card">
            <div class="card-block">
                <h3 class="card-title">The title</h3>
                <div class="card-text">
                    The text
                </div>
            </div>
        </div>
    </div>
    <div class="col-sm-6 col-md-4 col-lg-3">
        <div class="card">
            <div class="card-block">
                <h3 class="card-title">The title</h3>
                <div class="card-text">
                    The text
                </div>
            </div>
        </div>
    </div>
</div>

Although it kind of defeats the point of having card decks.

Edit: You would need to add a class to the card to give it 100% height to make the border extend to the full column.

Hopefully not too offtopic but ignoring the flexbox option: What if worked around this by rendering separate card decks for each breakpoint, eg. 2 card decks for medium screen, 3 card decks for large screen. It will produce some duplicate data so will I get penalized by search engines or is there a way to avoid that?

OK I figured out how to do this at least effectively and cleanly. I was inspired by this article http://www.minimit.com/demos/bootstrap-3-responsive-columns-of-same-height.

Add this SCSS to your project:

// bootstrap
@import "_variables";
@import "../../../node_modules/bootstrap/scss/_variables";
@import "../../../node_modules/bootstrap/scss/mixins/_breakpoints";

// <http://www.minimit.com/demos/bootstrap-3-responsive-columns-of-same-height>

/* USAGE
<div class="row">
  <div class="row-height">
    <div class="col-xs-2 col-xs-height col-xs-middle">
      <div class="inside"></div>
    </div>
    <div class="col-xs-4 col-lg-5 col-xs-height col-xs-middle">
      <div class="inside"></div>
    </div>
  </div>
</div>
*/

/* content styles */

.inside-full-height {
  // if you want to give content full height give him height: 100%;
  // with content full height you can't apply margins to the content
  // content full height does not work in ie http://stackoverflow.com/questions/27384433/ie-display-table-cell-child-ignores-height-100
  height: 100%;
  margin-top: 0;
  margin-bottom: 0;
}

/* columns of same height styles */
.row-height {
  display: table;
  table-layout: fixed;
  height: 100%;
  width: 100%;
}
.col-height {
  display: table-cell;
  float: none;
  height: 100%;
}
.col-top {
  vertical-align: top;
}
.col-middle {
  vertical-align: middle;
}
.col-bottom {
  vertical-align: bottom;
}

@include media-breakpoint-only(xs) {
  .row-xs-height {
    display: table;
    table-layout: fixed;
    height: 100%;
    width: 100%;
  }
  .col-xs-height {
    display: table-cell;
    float: none;
    height: 100%;
  }
  .col-xs-top {
    vertical-align: top;
  }
  .col-xs-middle {
    vertical-align: middle;
  }
  .col-xs-bottom {
    vertical-align: bottom;
  }
}

@include media-breakpoint-only(sm) {
  .row-sm-height {
    display: table;
    table-layout: fixed;
    height: 100%;
    width: 100%;
  }
  .col-sm-height {
    display: table-cell;
    float: none;
    height: 100%;
  }
  .col-sm-top {
    vertical-align: top;
  }
  .col-sm-middle {
    vertical-align: middle;
  }
  .col-sm-bottom {
    vertical-align: bottom;
  }
}

@include media-breakpoint-only(md) {
  .row-md-height {
    display: table;
    table-layout: fixed;
    height: 100%;
    width: 100%;
  }
  .col-md-height {
    display: table-cell;
    float: none;
    height: 100%;
  }
  .col-md-top {
    vertical-align: top;
  }
  .col-md-middle {
    vertical-align: middle;
  }
  .col-md-bottom {
    vertical-align: bottom;
  }
}

@include media-breakpoint-only(lg) {
  .row-lg-height {
    display: table;
    table-layout: fixed;
    height: 100%;
    width: 100%;
  }
  .col-lg-height {
    display: table-cell;
    float: none;
    height: 100%;
  }
  .col-lg-top {
    vertical-align: top;
  }
  .col-lg-middle {
    vertical-align: middle;
  }
  .col-lg-bottom {
    vertical-align: bottom;
  }
}

@include media-breakpoint-only(xl) {
  .row-xl-height {
    display: table;
    table-layout: fixed;
    height: 100%;
    width: 100%;
  }
  .col-xl-height {
    display: table-cell;
    float: none;
    height: 100%;
  }
  .col-xl-top {
    vertical-align: top;
  }
  .col-xl-middle {
    vertical-align: middle;
  }
  .col-xl-bottom {
    vertical-align: bottom;
  }
}

Example HTML usage (reference the article for more info):

      <div class="row text-xs-center">
        <div class="row-md-height row-lg-height row-xl-height">
          <div class="col-xs-12 col-sm-12 col-md-6 col-lg-6 col-xl-6 col-md-height col-lg-height col-xl-height col-md-top col-lg-top col-xl-top">
            <div class="inside inside-full-height card bg-inverse">
              <div class="card-block p-y-2">
                <h2 class="card-title">Get Started</h2>
                <kbd class="d-inline-block p-a-1 bg-success">npm install -g crocodile</kbd>
                <div class="clearfix"></div>
                <p class="card-text m-t-1">
                  <a href="https://github.com/crocodilejs/crocodile-node-mvc-framework#requirements" target="_blank" class="btn btn-outline-secondary bg-inverse btn-sm"><i class="fa fa-cogs"></i> You'll need Node.js + MongoDB + Redis</a>
                </p>
              </div>
            </div>
          </div>
          <div class="hidden-md-up col-xs-12 col-sm-12 m-y-1"></div>
          <div class="col-xs-12 col-sm-12 col-md-6 col-lg-6 col-xl-6 col-md-height col-lg-height col-xl-height col-md-top col-lg-top col-xl-top">
            <div class="inside inside-full-height card card-outline-secondary">
              <div class="card-block p-y-2">
                <h3 class="card-title h2">Using Commercially?</h2>
                <button type="button" class="btn btn-primary btn-md">Purchase License + Free Swag</button>
                <p class="card-text"><small class="text-muted">We use <a href="https://stripe.com" target="_blank">Stripe</a> for credit-card processing</small></p>
              </div>
            </div>
          </div>
        </div>
      </div>

I built this for my framework @crocodilejs which uses Bootstrap 4 https://github.com/crocodilejs/crocodile-node-mvc-framework.

screen shot 2016-09-27 at 8 41 39 am
screen shot 2016-09-27 at 8 41 33 am
screen shot 2016-09-27 at 8 41 28 am

Updated HTML/SCSS above to account for XL class.

I don't really see how that is clean. Compare it to the code above that just needs a class to give 100% height and uses built in classes.

@robwent show the example + CSS that gives 100% height?

.any-class {
height: 100%;
}

Add that to each card or col and turn on flexbox.

Probably don't even need that with flexbox, make it stretch.

Does not work without flexbox

On Sep 27, 2016 11:22 AM, "Robert Went" [email protected] wrote:

.any-class {
height: 100%;
}

Add that to each card or col and turn on flexbox.

Probably don't even need that with flexbox, make it stretch.

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/twbs/bootstrap/issues/20321#issuecomment-249894252,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAf7hbNpr_2IAE5RSwReM_ZnDz82Gab0ks5quTO9gaJpZM4JOy7_
.

@robwent Thanks for the tip with height: 100% in combination with flexbox.

However when I do so, the margin-bottom of the cards looses its effect which causes the cards on top of each other to stick together. Any idea why this happens?

As a workaround I added a padding-bottom to the card-wrapping columns.

@elafari Yeah, I just noticed this myself a couple of days ago.
I ended up adding a mb-1 class and adding it to the column (Or I created a mb-g class for a margin bottom grid spacer).

I thought it was actually down to the way I was using the cards as looking at my setup they should just really be columns with a background colour :)

So basically, I have nothing helpful to add, sorry.

+1 would be nice to see grid type system support for card decks.

height: 100% isn't working in Safari :(

I encountered this issue and the non-flexbox CSS uses display:table to achieve the 100% height. I decided to just write a custom media query to remove that styling at the breakpoint where things start looking funky. In my case it was 950px. You can see a demo here http://codepen.io/JacobLett/pen/rWXJPV

As an intermediate easy step, maybe just adding decks that break at different break points. The current implementation is based on media-breakpoint-up(sm), but having card-deck-md, card-deck-lg and card-deck-xl would be easy to implement and offer a lot more flexibility.

Another approach/workaround for responsive card-deck is to force a wrap using the visibility utils every X cards...

<div class="card-deck">
        <div class="card">
            ..
        </div>
        <div class="card">
            ..
        </div>
        <div class="w-100 hidden-xs-down hidden-md-up"><!-- wrap every 2 on sm--></div>
        <div class="card">
            ..
        </div>
        <div class="w-100 hidden-sm-down hidden-lg-up"><!-- wrap every 3 on md--></div>
        <div class="card">
            ..
        </div>
        <div class="w-100 hidden-xs-down hidden-md-up"><!-- wrap every 2 on sm--></div>
        <div class="w-100 hidden-md-down hidden-xl-up"><!-- wrap every 4 on lg--></div>
        <div class="card">
            ..
        </div>
        <div class="w-100 hidden-lg-down"><!-- wrap every 5 on xl--></div>
        <div class="card">
            ..
        </div>
</div>

@robwent

I don't really see how that is clean. Compare it to the code above that just needs a class to give 100% height and uses built in classes.

Clean, but doesn't work in all browsers. Dirty is better than clean and broken...

@mbrookes If you mean flexbox then you might as well stick with bs3

@robwent https://github.com/twbs/bootstrap/issues/20321#issuecomment-269035101
I had the same issue.

@mbrookes It worked fine for me in all browsers supported by bs4.

If it doesn't work for you, then try the other suggestions and then move on.

Tagging people in 6-month-old threads to make smug comments is just a waste of everybody's time.
I'm blocking your notifications, so don't expect any more replies.

The most annoying part of this is they already have a solution for card-columns. When you use them all you need to do is specify the column-count you want at each breakpoint:

.card-columns {
  @include media-breakpoint-only(xl) {
    column-count: 5;
  }
  @include media-breakpoint-only(lg) {
    column-count: 4;
  }
  @include media-breakpoint-only(md) {
    column-count: 3;
  }
  @include media-breakpoint-only(sm) {
    column-count: 2;
  }
}

Card decks only behave responsively when you get to the xs breakpoint, they then go to 1 column.

I've managed to find a way of having cards in the responsive system while having equal heights just like a deck. I found most of the solution here, option 4:
https://scotch.io/bar-talk/different-tricks-on-how-to-make-bootstrap-columns-all-the-same-height

Not all of this CSS is required as some options are already enabled by Bootstrap. I enable it by adding the CSS class 'equal-height' to a row which then has cards contained within responsive columns:

.row.equal-height {
    display: flex;
    flex-wrap: wrap;
}
.row.equal-height > [class*='col'] {
    display: flex;
    flex-direction: column;
}

.card {
    flex: 1;
}

basic html structure:

<div class="row equal-height">
    <div class="col-12 col-md-6">
        <div class="card">
            <!-- Your card content here -->
        </div>
    </div>
</div>

edit: the value 'flex: 1 0 0;' I was using on class .card was causing problems. Safari is happy with 0 but Chrome expects 0%. Being honest I don't understand what flex-shrink and flex-basis do but specifying flex: 1; so only setting the flex-grow value works in all the browsers I tested.

edit2 June 2020: I've come back as I needed this on another project, I see this is closed and a solution has been found for responsive columns but they don't give you equal height. I used my fix again and realised it didn't work if you just used col, not col-(some modifier). I've changed the code to fix that, match 'col' not 'col-'.
But now the footer is broken, if I find a fix I'll post it.

@TC72 your solution is flawless as far as I can tell. This should be integrated into Bootstrap.

@TC72 Seems to work very well, except in IE11 (and probably IE10). However, removing flex-direction: column; seems to work in IE11, latest Chrome, Firefox and Safari. Struggle to see the logic in that though. Using card-img-top seems to have display problems in IE as well, but that's another story...

Thanks @TC72 for this solution!

@mdo Please implement this into Bootstrap's next release (v4.1).
Card Decks idea is great, but not very useful if we can't set its responsive behaviour.

PS: Bootstrap 4 is absolutely amazing, stunned by all the new possibilities. Thank you!

like @Tomas76 I had to remove flex-direction: column; as well so it works in latest Chrome.

That's what I did to change the card-deck breakpoint:

@include media-breakpoint-between(sm, md) { .card-deck .card { flex: 0 0 95%; } }

My solution to this was to make a little utility class in lieu of a row, like so :

.card-cols {
  @include make-row();
  .card {
    background: none;
  }
  .card-body {
    background: $white;
  }
}

(since cards themselves have a background, I apply the background only to the body, as explained in my weird hacky gist - which also gives a few more options/examples)

And the HTML allows usage of a card as a grid item, like so :

<div class="card-cols">
  <div class="card col-sm-6 col-lg-4">
    <img src="https://placeimg.com/640/480/any" class="card-img-top">
    <div class="card-body">
      <h2 class="card-title">Card Title</h2>
      <p class="card-text">Lorem ipsum dolor sit amet, consectetur adipisicing elit</p>
    </div><!-- ./ .card-body -->
    <div class="card-footer">
      <p class="small">card footer</p>
    </div><!-- ./ .card-footer -->
  </div><!-- ./ .card -->
</div><!-- ./ card-cols -->

I'm sure mdo, et al. have much more elegant solutions in mind but this is what I'm using on a site I'm working on for the time being.

Here is how i achieved the equal height cards in bootstrap4 beta 2

<div class="row d-flex align-items-stretch">
  <div class="col-md-3 d-flex flex-wrap">
    <div class="card">
      ...
    </div>
  </div>
  <div class="col-md-3 d-flex flex-wrap">
    <div class="card">
      ...
    </div>
  </div>
  <div class="col-md-3 d-flex flex-wrap">
    <div class="card">
      ...
    </div>
  </div>
</div>

The new "Pricing" example page is using card-deck in a responsive way, see:
https://getbootstrap.com/docs/4.0/examples/pricing/

Yet the Bootstrap docs still say: "For the time being, these layout options are not yet responsive."

UPDATE:

Nevermind, they're just adding:

.card-deck .card {
  min-width: 220px;
}

That's not really what we're after...

How about something like this?

.card-deck {
    .card {
        @include media-breakpoint-up(sm) {
            // 2-up
            flex: 0 0 calc(100%/2 - 30px); // Subtract left+right margin
        }

        @include media-breakpoint-up(md) {
            // 3-up
            flex: 0 0 calc(100%/3 - 30px);
        }

        @include media-breakpoint-up(lg) {
            // 4-up
            flex: 0 0 calc(100%/4 - 30px);
        }

        @include media-breakpoint-up(xl) {
            // 5-up
            flex: 0 0 calc(100%/5 - 30px);
        }
    }
}

I implemented @mattsims 's solution on Codepen here https://codepen.io/migli/pen/OQVRMw
with a sass map to configure the number of cards per line.

Based on pen from @migliori I've achieved the same using CSS Grid Layout: https://codepen.io/bugmenot/pen/aqmEer

Prefixed it should work for IE10+.

Thank you for this @mattsims! This works well for me.

Would it be feasible to add something like this to Bootstrap? And the docs?

@mixin card-deck-column-count($count: 1) {
  flex: 0 0 calc(100% / #{$count} - #{$card-deck-margin} * 2);
}

Usage:

.card-deck {
  .card {
    @include media-breakpoint-up(sm) {
      @include card-deck-column-count(2);
    }

    @include media-breakpoint-up(md) {
      @include card-deck-column-count(3);
    }

    @include media-breakpoint-up(lg) {
      @include card-deck-column-count(4);
    }

    @include media-breakpoint-up(xl) {
      @include card-deck-column-count(5);
    }
  }
}

@m-vdv you might want to try, this fits my need nicely.

.card-deck .card {
min-width: 220px;
max-width: 220px;
}

Great idea :) I like this idea with breakpoint like in other things :) I hope you will add this in next version of BS4, curently I had to use below code to see only 1 card on mobile phones:

@media (max-width: 767px) { .card-deck .card { -webkit-box-flex: auto; -ms-flex: auto; flex: auto; margin-bottom: 15px; } }

Here's how I solved it. I had a section with id case-studies with a card-deck inside of it:

#case-studies .card-deck {
  display: grid;
}
@media (min-width: 0) {
  #case-studies .card-deck {
    grid-template-columns: repeat(1, 1fr);
  }
}
@media (min-width: 768px) {
  #case-studies .card-deck {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (min-width: 992px) {
  #case-studies .card-deck {
    grid-template-columns: repeat(3, 1fr);
  }
}
@media (min-width: 1400px) {
  #case-studies .card-deck {
    grid-template-columns: repeat(5, 1fr);
  }
}

While I love the solution from @TC72 , I do have a related question. Since cards of different heights are now "stretched" to be of equal height in a row, the buttons / links are now not anymore at the bottom of the cards, as they should be (check https://material.io/guidelines/components/cards.html#cards-actions)

Any idea how to achieve that?

@AndreasEK Bootstrap 4 has card-footer for this case with pre-styled background-color and border-top https://getbootstrap.com/docs/4.0/components/card/#header-and-footer
You can implement a <div> with an own class for yourself if you want custom styling.

The solution from @iatek inspired me to use this strategy to break up a deck of 4 cards to start stacked, then display 2x2 at sm, and 1x4 across at larger viewports:

<!-- placed after second card -->
<div class="d-none d-sm-block d-md-none flex-basis-100"><!-- wrap every 2 on sm --></div>
<!-- placed before third card -->
.flex-basis-100 {
  flex-basis: 100%;
}

The flex-basis forces the next card to wrap to a new row, and the responsive utility classes control when the wrapping occurs. I added some utility spacing classes to the cards to adjust the vertical spacing when stacked 2x2.

The solution from @tihab worked just right in my case, it didn't even needs to create new css classes and works with the grid layout just as expected.

I know there are several solutions proposed throughout this thread, but maybe even just a simple solution of adding a variable to select which breakpoint they go full width would be helpful. I was experimenting with something like this:

Changing https://github.com/twbs/bootstrap/blob/v4-dev/scss/_card.scss#L149 to

@include media-breakpoint-up($card-deck-breakpoint) {

and adding that variable to vars.scss - $card-deck-breakpoint: sm;

Bootstrap 4.1 has .card-columns which solves this problem. They must have listened to all these bright ideas ;-).

Bootstrap 4.1 has .card-columns which solves this problem. They must have listened to all these bright ideas ;-).

This is not we expect, column works different than gropus.

@migliori @midzer thank You for Your solutions.
They will help me a lot.
@mdo any chance this could be added to v4 or must we wait for v5?

Following css proposal to make card-group, card-deck or simply cards can be made responsive (without any JS code).
This feature only supports the browsers listed here.

.grid-container {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
        grid-gap: 20px;
        padding: 3px 8px;
        width: 100%;
    }
    .grid-item {
        display: grid;
        height: 148px;
        overflow: hidden;
        max-width: 400px;
        box-shadow: 0 6px 10px rgba(0, 0, 0, .08), 0 0 6px rgba(0, 0, 0, .05);
        transition: .3s transform cubic-bezier(.155, 1.105, .295, 1.12), .3s box-shadow;
        border-radius: 5px;
    }

Demo

We might not need this feature after all...
Simply drop h-100 on cards in grid.
An example in the API doc is a valid solution.

<div class="row">
  <div class="col-sm-6 my-3">
    <div class="card h-100"> <!-- full height -->
      <div class="card-header"></div>
      <div class="card-body"></div>
      <div class="card-footer"></div>
    </div>
  </div>
</div>

As said before being able to use the class .card-deck and followed by classes card-deck-md-3 card-deck-lg-4 would be great!

The way i did my code now is like this:

<div class="container">
  <div class="card-group">
    <div class="col-md-6 col-lg-4 mb-4 m-lg-0"> <!-- Wrap card in a col -->
      <div class="card h-100"> <!-- Add full height to card -->
        <div class="card-header"></div>
        <div class="card-body"></div>
        <div class="card-footer"></div>
      </div>
    </div>
  </div>
</div>

Just opened https://github.com/twbs/bootstrap/pull/29073 to try to tackle this in a way that works for v4 and v5. This is a long time coming, and thanks to all the code snippets shared here, I had a few paths I could explore. Can y'all weigh in on that PR?

just add
height: calc(100vh - 120px);

just add
height: calc(100vh - 120px);

What a stupid way to code.. adding a fix height vh and fix px height is not done!

With #29073 merged, this will be possible in v4.4 and v5!

<div class="row row-cols-md-2">
  <div class="col mb-4">
    <div class="card">
      {{< placeholder width="100%" height="140" class="card-img-top" text="Image cap" >}}
      <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">
      {{< placeholder width="100%" height="140" class="card-img-top" text="Image cap" >}}
      <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">
      {{< placeholder width="100%" height="140" class="card-img-top" text="Image cap" >}}
      <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">
      {{< placeholder width="100%" height="140" class="card-img-top" text="Image cap" >}}
      <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>

Closing out per last comment.

I know this issue has been closed, but I wanted to share the solution I found which works well for me, and allows card-footers to align with each other —which isn't the case with the row/col solution above.

On smaller screens, the existing card-deck implementation displays only one card per row, without margins, and I've ensured this is still the case for maximum interoperability. It might be useful to mention this in the card-deck documentation.

Example HTML:

<div class="card-deck deck-md-2 deck-lg-3">
    <div class="card">
        <div class="card-body">
            Card contents
        </div>
        <div class="card-footer">
            Card footer
        </div>
    </div>
    <div class="card">
        <img src="..." class="card-img-top" alt="...">
        <div class="card-body">
            This is a longer card with more content. The text should wrap, but footers should remain aligned with one another thanks to Flexbox magic. Yay!
        </div>
        <div class="card-footer">
            Card footer
        </div>
    <div class="card">
        <div class="card-body">
            This is a longer card with even more content. 
            <br />And line breaks to ensure text does wrap.
            <br />And another line break for good measure.
        </div>
        <div class="card-footer">
            Card footer
        </div>
    </div>
</div>

SCSS

// _card_deck_columns.scss
// add deck-X and deck-BP-X classes to select the number of cards per line
@for $i from 2 through $grid-columns {
  $percentage: percentage(1 / $i);
  $calc: calc(#{$percentage} - #{$card-deck-margin * 2});
  .deck-#{$i} {
    // Force flex display, even on small screens
    display: flex;
    flex-flow: row wrap;
    margin-left:  -$card-deck-margin;
    margin-right: -$card-deck-margin;
    & > .card {
      flex-basis: $calc;
      max-width:  $calc;
      // Cards have no left/right margins on small screens by default
      margin-left:  $card-deck-margin;
      margin-right: $card-deck-margin;
    }
  }
}
@each $breakpoint in map-keys($grid-breakpoints) {
  $infix: breakpoint-infix($breakpoint, $grid-breakpoints);
  @include media-breakpoint-up($breakpoint) {
    @for $i from 1 through $grid-columns {
      $percentage: percentage(1 / $i);
      $calc: calc(#{$percentage} - #{$card-deck-margin * 2});
      .deck#{$infix}-#{$i} {
        margin-left:  -$card-deck-margin;
        margin-right: -$card-deck-margin;
        & > .card {
          flex-basis: $calc;
          max-width:  $calc;
          margin-left:  $card-deck-margin;
          margin-right: $card-deck-margin;
        }
      }
    }
  }
}

This code could probably be improved, feel free to ping me with edits if you know how.

Edit 1: _Expanded HTML code to show the differences with the existing row/col solution._
Edit 2: _Improved SCSS code to better leverage Bootstrap's card-deck default styles and generate the minimum required code._

@goulvench what's the difference between your version and new version of BS which support row-cols-md-2

@SkuterPL the deck-BP-X solution I suggest has two main benefits:

  1. it requires much less HTML (just a card-deck container, with cards as direct children), which is better both in terms of memory usage and for code readability, and
  2. card-footers align with each other, which is not the case with the row/col solution.
Was this page helpful?
0 / 5 - 0 ratings

Related issues

IamManchanda picture IamManchanda  Â·  3Comments

bellwood picture bellwood  Â·  3Comments

eddywashere picture eddywashere  Â·  3Comments

devfrey picture devfrey  Â·  3Comments

matsava picture matsava  Â·  3Comments