-
-
Notifications
You must be signed in to change notification settings - Fork 79k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Responsive Card Decks #20321
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
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. |
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 { 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:
|
@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 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 |
Another approach/workaround for responsive card-deck is to force a wrap using the visibility utils every X cards...
|
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 #20321 (comment) |
@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. |
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 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: 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:
basic html structure:
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-'. |
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 - |
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. |
Following css proposal to make card-group, card-deck or simply cards can be made responsive (without any JS code).
|
We might not need this feature after all... <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 The way i did my code now is like this:
|
Also updated jumbotron component to extend all his height Based on: twbs/bootstrap#20321 (comment)
Just opened #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 |
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 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 |
@goulvench what's the difference between your version and new version of BS which support |
@SkuterPL the
|
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 likecard-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.The text was updated successfully, but these errors were encountered: