Bootstrap 4 card-deck with number of columns based on viewport

CssTwitter BootstrapTwitter Bootstrap-4Bootstrap 4

Css Problem Overview


I'm trying to implement the card-deck feature in bootstrap 4 to make all of my cards the same height.

The examples that bootstrap provides show 4 nice cards, but it's 4 cards on the row, no matter the viewport. See the codeply here.

This doesn't make sense to me since, I would assume, that you'd want a minimum size for your card to shrink to in order for your content to still look good.

I then tried adding in some viewport classes to break on screen sizes, but as soon as that div gets added, the card-deck doesn't apply anymore, thus not making the cards equal height.

How can I get this accomplished? Is this a missing feature that will be addressed in the full release of Bootstrap 4?

Here's the fiddle: https://jsfiddle.net/crrm5q9m/

<div class="card-deck-wrapper">
  <div class="card-deck">
    <div class="card card-inverse card-success text-center col-xs-6 col-sm-4 col-md-3 col-lg-2 col-xl-1">
      <div class="card-block">
        <blockquote class="card-blockquote">
          <p>It's really good news that the new Bootstrap 4 now has support for CSS 3 flexbox.</p>
          <footer>Makes flexible layouts <cite title="Source Title">Faster</cite></footer>
        </blockquote>
      </div>
    </div>
    <div class="card card-inverse card-danger text-center col-xs-6 col-sm-4 col-md-3 col-lg-2 col-xl-1">
      <div class="card-block">
        <blockquote class="card-blockquote">
          <p>The Bootstrap 3.x element that was called "Panel" before, is now called a "Card".</p>
          <footer>All of this makes more <cite title="Source Title">Sense</cite></footer>
        </blockquote>
      </div>
    </div>
    <div class="card card-inverse card-warning text-center col-xs-6 col-sm-4 col-md-3 col-lg-2 col-xl-1">
      <div class="card-block">
        <blockquote class="card-blockquote">
          <p>There are also some interesting new text classes for uppercase and capitalize.</p>
          <footer>These handy utilities make it <cite title="Source Title">Easy</cite></footer>
        </blockquote>
      </div>
    </div>
    <div class="card card-inverse card-info text-center col-xs-6 col-sm-4 col-md-3 col-lg-2 col-xl-1">
      <div class="card-block">
        <blockquote class="card-blockquote">
          <p>If you want to use cool icons in Bootstrap 4, you'll have to find your own such as Font Awesome or Ionicons.</p>
          <footer>The Glyphicons are not <cite title="Source Title">Included</cite></footer>
        </blockquote>
      </div>
    </div>
        <div class="card card-inverse card-success text-center col-xs-6 col-sm-4 col-md-3 col-lg-2 col-xl-1">
      <div class="card-block">
        <blockquote class="card-blockquote">
          <p>It's really good news that the new Bootstrap 4 now has support for CSS 3 flexbox.</p>
          <footer>Makes flexible layouts <cite title="Source Title">Faster</cite></footer>
        </blockquote>
      </div>
    </div>
    <div class="card card-inverse card-danger text-center col-xs-6 col-sm-4 col-md-3 col-lg-2 col-xl-1">
      <div class="card-block">
        <blockquote class="card-blockquote">
          <p>The Bootstrap 3.x element that was called "Panel" before, is now called a "Card".</p>
          <footer>All of this makes more <cite title="Source Title">Sense</cite></footer>
        </blockquote>
      </div>
    </div>
    <div class="card card-inverse card-warning text-center col-xs-6 col-sm-4 col-md-3 col-lg-2 col-xl-1">
      <div class="card-block">
        <blockquote class="card-blockquote">
          <p>There are also some interesting new text classes for uppercase and capitalize.</p>
          <footer>These handy utilities make it <cite title="Source Title">Easy</cite></footer>
        </blockquote>
      </div>
    </div>
    <div class="card card-inverse card-info text-center col-xs-6 col-sm-4 col-md-3 col-lg-2 col-xl-1">
      <div class="card-block">
        <blockquote class="card-blockquote">
          <p>If you want to use cool icons in Bootstrap 4, you'll have to find your own such as Font Awesome or Ionicons.</p>
          <footer>The Glyphicons are not <cite title="Source Title">Included</cite></footer>
        </blockquote>
      </div>
    </div>
  </div>
</div>

Css Solutions


Solution 1 - Css

Updated 2018

If you want a responsive card-deck, use the visibility utils to force a wrap every X columns on different viewport width(breakpoints)...

Bootstrap 4 responsive card-deck (v 4.1)


Original answer for Bootstrap 4 alpha 2:

You can use the grid col-*-* to get the different widths (instead of card-deck) and then set equal height to the cols using flexbox.

.row > div[class*='col-'] {
  display: flex;
  flex:1 0 auto;
}

http://codeply.com/go/O0KdSG2YX2 (alpha 2)

The problem is that w/o flexbox enabled the card-deck uses table-cell where it becomes very hard to control the width. As of Bootstrap 4 Alpha 6, flexbox is default so the additional CSS is not required for flexbox, and the h-100 class can be used to make the cards full height: http://www.codeply.com/go/gnOzxd4Spk


Related question: https://stackoverflow.com/questions/34140793/bootstrap-4-responsive-cards-in-card-columns

Solution 2 - Css

Here's a solution with Sass to configure the number of cards per line depending on breakpoints: https://codepen.io/migli/pen/OQVRMw

It works fine with Bootstrap 4 beta 3

// Bootstrap 4 breakpoints & gutter
$grid-breakpoints: (
    xs: 0,
    sm: 576px,
    md: 768px,
    lg: 992px,
    xl: 1200px
) !default;

$grid-gutter-width: 30px !default;

// number of cards per line for each breakpoint
$cards-per-line: (
    xs: 1,
    sm: 2,
    md: 3,
    lg: 4,
    xl: 5
);

@each $name, $breakpoint in $grid-breakpoints {
    @media (min-width: $breakpoint) {
        .card-deck .card {
            flex: 0 0 calc(#{100/map-get($cards-per-line, $name)}% - #{$grid-gutter-width});
        }
    }
}

EDIT (2019/10)

I worked on another solution which uses horizontal lists group + flex utilities instead of card-deck:

https://codepen.io/migli/pen/gOOmYLb

It's an easy solution to organize any kind of elements into responsive grid

<div class="container">
	<ul class="list-group list-group-horizontal align-items-stretch flex-wrap">
		<li class="list-group-item">Cras justo odio</li>
		<li class="list-group-item">Dapibus ac facilisis in</li>
		<li class="list-group-item">Morbi leo risus</li>
		<li class="list-group-item">Cras justo odio</li>
		<li class="list-group-item">Dapibus ac facilisis in</li>
		<!--= add as many items as you need  =-->
	</ul>
</div>
.list-group-item {
	width: 95%;
	margin: 1% !important;
}

@media (min-width: 576px) {
	.list-group-item {
		width: 47%;
		margin: 5px 1.5% !important;
	}
}

@media (min-width: 768px) {
	.list-group-item {
		width: 31.333%;
		margin: 5px 1% !important;
	}
}

@media (min-width: 992px) {
	.list-group-item {
		width: 23%;
		margin: 5px 1% !important;
	}
}

@media (min-width: 1200px) {
	.list-group-item {
		width: 19%;
		margin: 5px .5% !important;
	}
}

Solution 3 - Css

I got this to work by adding a min-width to the cards:

<div class="card mb-3" style="min-width: 18rem;">
  <p>Card content</p>
</div>

The cards don't go below this width, but still properly fill each row and have equal heights.

Solution 4 - Css

I've used CSS Grid to fix that. CSS Grid will make all the elements in the same row, all the same height.

I haven't looked into making all the elements in all the rows the same height though.

Anyway, here's how it can be done:

HTML:

<div class="grid-container">

  <div class="card">...</div>
  <div class="card">...</div>
</div>

CSS:

.grid-container {
  display: grid;  
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

Here's a complete JSFiddle. https://jsfiddle.net/bluegrounds/owjvhstq/4/

Solution 5 - Css

<div class="w-100 d-lg-none mt-4"></div>

I created 4 cards and place this code between second and third card, try this.

Solution 6 - Css

This answer is for those who are using Bootstrap 4.1+ and for those who care about IE 11 as well

Card-deck does not adapt the number visible of cards according to the viewport size.

Above methods work but do not support IE. With the below method, you can achieve similar functionality and responsive cards.

You can manage the number of cards to show/hide in different breakpoints.

In Bootstrap 4.1+ columns are same height by default, just make sure your card/content uses all available space. Run the snippet, you'll understand

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="container">
    <div class="row">
        <div class="col-sm-6 col-lg-4 mb-3">
            <div class="card mb-3 h-100">

                <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>
        <div class="col-sm-6 col-lg-4 mb-3">
            <div class="card mb-3 h-100">
                <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>
        <div class="col-sm-6 col-lg-4 mb-3">
            <div class="card mb-3 h-100">
                <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>
    </div>
</div>

Solution 7 - Css

Define columns by min width based on viewport:


    /* Number of Cards by Row based on Viewport */
    @media (min-width: 576px) {
        .card-deck .card {
            min-width: 50.1%; /* 1 Column */
            margin-bottom: 12px;
        }
    }
    
    @media (min-width: 768px) {
        .card-deck .card {
            min-width: 33.4%;  /* 2 Columns */
        }
    }
    
    @media (min-width: 992px) {
        .card-deck .card {
            min-width: 25.1%;  /* 3 Columns */
        }
    }
    
    @media (min-width: 1200px) {
        .card-deck .card {
            min-width: 20.1%;  /* 4 Columns */
        }
    }

Solution 8 - Css

Using Bootstrap 4.4.1, I was able to set the number of cards per deck using simple classes by adding some scss into the mix.

HTML

<div class="card-deck deck-1 deck-md-2 deck-lg-3">
   <div class="card">
      <h2 class="card-header">Card 1</h3>
      <div class="card-body">
          Card body
      </div>
      <div class="card-footer">
          Card footer
      </div>
   </div>
   <div class="card">
      <h2 class="card-header">Card 2</h3>
      <div class="card-body">
          Card body
      </div>
      <div class="card-footer">
          Card footer
      </div>
   </div>
   <div class="card">
      <h2 class="card-header">Card 3</h3>
      <div class="card-body">
          Card body
      </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 1 through $grid-columns {
  .deck-#{$i} > .card {
    $percentage: percentage(1 / $i);
    @if $i == 1 {
      $width: $percentage;
      flex-basis: $width;
      max-width: $width;
      margin-left: 0;
      margin-right: 0;
    } @else {
      $width: unquote("calc(#{$percentage} - #{$grid-gutter-width})");
      flex-basis: $width;
      max-width: $width;
    }
  }
}
@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 {
      .deck#{$infix}-#{$i} > .card {
        $percentage: percentage(1 / $i);
        @if $i == 1 {
          $width: $percentage;
          flex-basis: $width;
          max-width: $width;
          margin-left: 0;
          margin-right: 0;
        } @else {
          $width: unquote("calc(#{$percentage} - #{$grid-gutter-width})");
          flex-basis: $width;
          max-width: $width;
          margin-left: $grid-gutter-width / 2;
          margin-right: $grid-gutter-width / 2;
        }
      }
    }
  }
}

CSS

.deck-1 > .card {
  flex-basis: 100%;
  max-width: 100%;
  margin-left: 0;
  margin-right: 0; }

.deck-2 > .card {
  flex-basis: calc(50% - 30px);
  max-width: calc(50% - 30px); }

.deck-3 > .card {
  flex-basis: calc(33.3333333333% - 30px);
  max-width: calc(33.3333333333% - 30px); }

.deck-4 > .card {
  flex-basis: calc(25% - 30px);
  max-width: calc(25% - 30px); }

.deck-5 > .card {
  flex-basis: calc(20% - 30px);
  max-width: calc(20% - 30px); }

.deck-6 > .card {
  flex-basis: calc(16.6666666667% - 30px);
  max-width: calc(16.6666666667% - 30px); }

.deck-7 > .card {
  flex-basis: calc(14.2857142857% - 30px);
  max-width: calc(14.2857142857% - 30px); }

.deck-8 > .card {
  flex-basis: calc(12.5% - 30px);
  max-width: calc(12.5% - 30px); }

.deck-9 > .card {
  flex-basis: calc(11.1111111111% - 30px);
  max-width: calc(11.1111111111% - 30px); }

.deck-10 > .card {
  flex-basis: calc(10% - 30px);
  max-width: calc(10% - 30px); }

.deck-11 > .card {
  flex-basis: calc(9.0909090909% - 30px);
  max-width: calc(9.0909090909% - 30px); }

.deck-12 > .card {
  flex-basis: calc(8.3333333333% - 30px);
  max-width: calc(8.3333333333% - 30px); }

.deck-1 > .card {
  flex-basis: 100%;
  max-width: 100%;
  margin-left: 0;
  margin-right: 0; }

.deck-2 > .card {
  flex-basis: calc(50% - 30px);
  max-width: calc(50% - 30px);
  margin-left: 15px;
  margin-right: 15px; }

.deck-3 > .card {
  flex-basis: calc(33.3333333333% - 30px);
  max-width: calc(33.3333333333% - 30px);
  margin-left: 15px;
  margin-right: 15px; }

.deck-4 > .card {
  flex-basis: calc(25% - 30px);
  max-width: calc(25% - 30px);
  margin-left: 15px;
  margin-right: 15px; }

.deck-5 > .card {
  flex-basis: calc(20% - 30px);
  max-width: calc(20% - 30px);
  margin-left: 15px;
  margin-right: 15px; }

.deck-6 > .card {
  flex-basis: calc(16.6666666667% - 30px);
  max-width: calc(16.6666666667% - 30px);
  margin-left: 15px;
  margin-right: 15px; }

.deck-7 > .card {
  flex-basis: calc(14.2857142857% - 30px);
  max-width: calc(14.2857142857% - 30px);
  margin-left: 15px;
  margin-right: 15px; }

.deck-8 > .card {
  flex-basis: calc(12.5% - 30px);
  max-width: calc(12.5% - 30px);
  margin-left: 15px;
  margin-right: 15px; }

.deck-9 > .card {
  flex-basis: calc(11.1111111111% - 30px);
  max-width: calc(11.1111111111% - 30px);
  margin-left: 15px;
  margin-right: 15px; }

.deck-10 > .card {
  flex-basis: calc(10% - 30px);
  max-width: calc(10% - 30px);
  margin-left: 15px;
  margin-right: 15px; }

.deck-11 > .card {
  flex-basis: calc(9.0909090909% - 30px);
  max-width: calc(9.0909090909% - 30px);
  margin-left: 15px;
  margin-right: 15px; }

.deck-12 > .card {
  flex-basis: calc(8.3333333333% - 30px);
  max-width: calc(8.3333333333% - 30px);
  margin-left: 15px;
  margin-right: 15px; }

@media (min-width: 576px) {
  .deck-sm-1 > .card {
    flex-basis: 100%;
    max-width: 100%;
    margin-left: 0;
    margin-right: 0; }

  .deck-sm-2 > .card {
    flex-basis: calc(50% - 30px);
    max-width: calc(50% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-sm-3 > .card {
    flex-basis: calc(33.3333333333% - 30px);
    max-width: calc(33.3333333333% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-sm-4 > .card {
    flex-basis: calc(25% - 30px);
    max-width: calc(25% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-sm-5 > .card {
    flex-basis: calc(20% - 30px);
    max-width: calc(20% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-sm-6 > .card {
    flex-basis: calc(16.6666666667% - 30px);
    max-width: calc(16.6666666667% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-sm-7 > .card {
    flex-basis: calc(14.2857142857% - 30px);
    max-width: calc(14.2857142857% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-sm-8 > .card {
    flex-basis: calc(12.5% - 30px);
    max-width: calc(12.5% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-sm-9 > .card {
    flex-basis: calc(11.1111111111% - 30px);
    max-width: calc(11.1111111111% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-sm-10 > .card {
    flex-basis: calc(10% - 30px);
    max-width: calc(10% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-sm-11 > .card {
    flex-basis: calc(9.0909090909% - 30px);
    max-width: calc(9.0909090909% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-sm-12 > .card {
    flex-basis: calc(8.3333333333% - 30px);
    max-width: calc(8.3333333333% - 30px);
    margin-left: 15px;
    margin-right: 15px; } }
@media (min-width: 768px) {
  .deck-md-1 > .card {
    flex-basis: 100%;
    max-width: 100%;
    margin-left: 0;
    margin-right: 0; }

  .deck-md-2 > .card {
    flex-basis: calc(50% - 30px);
    max-width: calc(50% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-md-3 > .card {
    flex-basis: calc(33.3333333333% - 30px);
    max-width: calc(33.3333333333% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-md-4 > .card {
    flex-basis: calc(25% - 30px);
    max-width: calc(25% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-md-5 > .card {
    flex-basis: calc(20% - 30px);
    max-width: calc(20% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-md-6 > .card {
    flex-basis: calc(16.6666666667% - 30px);
    max-width: calc(16.6666666667% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-md-7 > .card {
    flex-basis: calc(14.2857142857% - 30px);
    max-width: calc(14.2857142857% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-md-8 > .card {
    flex-basis: calc(12.5% - 30px);
    max-width: calc(12.5% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-md-9 > .card {
    flex-basis: calc(11.1111111111% - 30px);
    max-width: calc(11.1111111111% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-md-10 > .card {
    flex-basis: calc(10% - 30px);
    max-width: calc(10% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-md-11 > .card {
    flex-basis: calc(9.0909090909% - 30px);
    max-width: calc(9.0909090909% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-md-12 > .card {
    flex-basis: calc(8.3333333333% - 30px);
    max-width: calc(8.3333333333% - 30px);
    margin-left: 15px;
    margin-right: 15px; } }
@media (min-width: 992px) {
  .deck-lg-1 > .card {
    flex-basis: 100%;
    max-width: 100%;
    margin-left: 0;
    margin-right: 0; }

  .deck-lg-2 > .card {
    flex-basis: calc(50% - 30px);
    max-width: calc(50% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-lg-3 > .card {
    flex-basis: calc(33.3333333333% - 30px);
    max-width: calc(33.3333333333% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-lg-4 > .card {
    flex-basis: calc(25% - 30px);
    max-width: calc(25% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-lg-5 > .card {
    flex-basis: calc(20% - 30px);
    max-width: calc(20% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-lg-6 > .card {
    flex-basis: calc(16.6666666667% - 30px);
    max-width: calc(16.6666666667% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-lg-7 > .card {
    flex-basis: calc(14.2857142857% - 30px);
    max-width: calc(14.2857142857% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-lg-8 > .card {
    flex-basis: calc(12.5% - 30px);
    max-width: calc(12.5% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-lg-9 > .card {
    flex-basis: calc(11.1111111111% - 30px);
    max-width: calc(11.1111111111% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-lg-10 > .card {
    flex-basis: calc(10% - 30px);
    max-width: calc(10% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-lg-11 > .card {
    flex-basis: calc(9.0909090909% - 30px);
    max-width: calc(9.0909090909% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-lg-12 > .card {
    flex-basis: calc(8.3333333333% - 30px);
    max-width: calc(8.3333333333% - 30px);
    margin-left: 15px;
    margin-right: 15px; } }
@media (min-width: 1200px) {
  .deck-xl-1 > .card {
    flex-basis: 100%;
    max-width: 100%;
    margin-left: 0;
    margin-right: 0; }

  .deck-xl-2 > .card {
    flex-basis: calc(50% - 30px);
    max-width: calc(50% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-xl-3 > .card {
    flex-basis: calc(33.3333333333% - 30px);
    max-width: calc(33.3333333333% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-xl-4 > .card {
    flex-basis: calc(25% - 30px);
    max-width: calc(25% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-xl-5 > .card {
    flex-basis: calc(20% - 30px);
    max-width: calc(20% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-xl-6 > .card {
    flex-basis: calc(16.6666666667% - 30px);
    max-width: calc(16.6666666667% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-xl-7 > .card {
    flex-basis: calc(14.2857142857% - 30px);
    max-width: calc(14.2857142857% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-xl-8 > .card {
    flex-basis: calc(12.5% - 30px);
    max-width: calc(12.5% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-xl-9 > .card {
    flex-basis: calc(11.1111111111% - 30px);
    max-width: calc(11.1111111111% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-xl-10 > .card {
    flex-basis: calc(10% - 30px);
    max-width: calc(10% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-xl-11 > .card {
    flex-basis: calc(9.0909090909% - 30px);
    max-width: calc(9.0909090909% - 30px);
    margin-left: 15px;
    margin-right: 15px; }

  .deck-xl-12 > .card {
    flex-basis: calc(8.3333333333% - 30px);
    max-width: calc(8.3333333333% - 30px);
    margin-left: 15px;
    margin-right: 15px; } }

Solution 9 - Css

@Zim provided a great solution above (well deserved up-vote from me), however, it didn't quite fit what I needed since I was implementing this in Jekyll and wanted my card deck to automatically update every time I added a post to my site. Growing a card deck such as this with each new post is straight forward in Jekyll, the challenge was to correctly place the breakpoints. My solution make use of additional liquid tags and modulo mathematics.

While this question is old, I came across it and found it useful, and maybe someday someone will come along wanting to do this with Jekyll.

<div class = "container">
  <div class = "card-deck">

    {% for post in site.posts %}
      <div class = "card border-0 mt-2">
        <a href = "{{ post.url }}"><img src = "{{ site.baseurl }}{{ post.image }}" class = "mx-auto" alt = "..."></a>
        <div class = "card-body">
          <h5 class = "card-title"><a href = "{{ post.url }}">{{ post.title }}</a></h5>
          <span>Published: {{ post.date | date_to_long_string }} </span>
          <p class = "text-muted">{{ post.excerpt }}</p>
        </div>
        <div class = "card-footer bg-white border-0"><a href = "{{ post.url }}" class = "btn btn-primary">Read more</a></div>
      </div>
      
      <!-- Use modulo to add divs to handle break points -->
      {% assign sm = forloop.index | modulo: 2 %}
      {% assign md = forloop.index | modulo: 3 %}
      {% assign lg = forloop.index | modulo: 4 %}
      {% assign xl = forloop.index | modulo: 5 %}
      
      {% if sm == 0 %}
        <div class="w-100 d-none d-sm-block d-md-none"><!-- wrap every 2 on sm--></div>
      {% endif %}
      
      {% if md == 0 %}
        <div class="w-100 d-none d-md-block d-lg-none"><!-- wrap every 3 on md--></div>
      {% endif %}
      
      {% if lg == 0 %}
        <div class="w-100 d-none d-lg-block d-xl-none"><!-- wrap every 4 on lg--></div>
      {% endif %}
      
      {% if xl == 0 %}
        <div class="w-100 d-none d-xl-block"><!-- wrap every 5 on xl--></div>
      {% endif %}
      
    {% endfor %}
  </div>
</div>

This whole code block can be used directly in a website or saved in your Jekyll project _includes folder.

Solution 10 - Css

There's simpler solution for that - set fixed height of card elements - header and body. This way, we can set resposive layout with standard boostrap column grid.

Here is my example: http://codeply.com/go/RHDawRSBol

 <div class="card-deck text-center">
    <div class="col-sm-6 col-md-4 col-lg-3">
        <div class="card mb-4">
            <img class="card-img-top img-fluid" src="//placehold.it/500x280" alt="Card image cap">
            <div class="card-body" style="height: 20rem">
                <h4 class="card-title">1 Card title</h4>
                <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>
                <p class="card-text"><small class="text-muted">Last updated 3 mins ago</small></p>
            </div>
        </div>

Solution 11 - Css

It took me a bit to figure this out, but the answer is to not use a card-deck, but instead to use .row and .cols.

This makes a responsive set of cards with specifics for each screen size: 3 cards for xl, 2 for lg and md, and 1 for sm and xs. .my-3 puts a padding on top and bottom so they look nice.

mixin postList(stuff)
  .row
    - site.posts.each(function(post, index){
      .col-sm-12.col-md-6.col-lg-6.col-xl-4
        .card.my-3
          img.card-img-top(src="...",  alt="Card image cap")
          .card-body
            h5.card-title Card title #{index}
            p.card-text Some quick example text to build on the card title and make up the bulk of the cards content.
            a.btn.btn-primary(href="#") Go somewhere
    - })

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiongandersView Question on Stackoverflow
Solution 1 - CssZimView Answer on Stackoverflow
Solution 2 - CssmigliView Answer on Stackoverflow
Solution 3 - CssSpanomalyView Answer on Stackoverflow
Solution 4 - CssbluegroundsView Answer on Stackoverflow
Solution 5 - CssMohammad Ayoub KhanView Answer on Stackoverflow
Solution 6 - CssRamesh NaviView Answer on Stackoverflow
Solution 7 - CssPyetroView Answer on Stackoverflow
Solution 8 - CssGoulvenView Answer on Stackoverflow
Solution 9 - CssedsandorfView Answer on Stackoverflow
Solution 10 - CssBart GluszakView Answer on Stackoverflow
Solution 11 - CssMichael ColeView Answer on Stackoverflow