Bootstrap 5 layout for different sizes cards - like Pinterest
Asked Answered
A

5

6

I am building a web that would use Bootstrap 5, the web would have a section which displays several cards like this enter image description here

As you can see, each card may have different sizes (Depending on the description and thumbnail)

How do I make them compact, as in like the Pinterest homepage

enter image description here

What class do I need to use (In bootstrap 5), or what layout

Araceli answered 27/12, 2020 at 16:45 Comment(1)
Use CSS Grid. Don't search for bootstrap grid - those are different.Knowitall
B
11

As explained in the Bootstrap 5 docs, the Masonry JS plugin is the recommended option for this type of "Pinterest" layout. The multi-column card layout (card-columns) that was used in Bootstrap 4 is no longer available in Bootstrap 5.

Using the Masonry plugin is easy. Just use the appropriate col-* class to set the number of columns across, and then the data-masonry attribute on the containing row...

<div class="container">
    <div class="row" data-masonry='{"percentPosition": true }'>
        <div class="col-*">
            ...
        </div>
    </div>
</div>

https://codeply.com/p/yrjCBwUeKR


Note: The CSS grid masonry (ie: grid-template-rows: masonry;) option mentioned by others currently only works in Firefox, and is not yet a recommended option.

Bibliomania answered 27/12, 2020 at 18:1 Comment(2)
Thank you, I will also add that I have to use imagesloaded to solve a problem where loading images cause the masonry to looks weirdAraceli
It won't work without this in your main HTML file <script src="cdn.jsdelivr.net/npm/[email protected]/dist/…" integrity="sha384-GNFwBvfVxBkLMJpYMOABq3c+d3KnQxudP/mGPkzpZSTYykLBNsZEnG2D9G/X/+7D" crossorigin="anonymous" async></script>Eustashe
A
5

#cont {
  columns:3;
  column-gap: 5px;
}
#cont>div {
  background: #c1c1ff;
  margin-bottom: 5px;
  break-inside:avoid;
}
<div id="cont">
<div style="height:30px"></div>
<div style="height:50px"></div>
<div style="height:70px"></div>
<div style="height:55px"></div>
<div style="height:90px"></div>
<div style="height:40px"></div>
<div style="height:60px"></div>
<div style="height:35px"></div>
</div>
Austrasia answered 27/12, 2020 at 17:6 Comment(0)
B
2

Don't use Bootstrap for this. Use CSS Grid Feature It can help you through the looping if dynamic content is loading as well as very easy to setup.

.grid-container {
    width: 100%;
    margin: 0 auto;
    display: grid;
    grid-gap: 20px;
    text-align: center;
    margin-top: 1rem;
    grid-template-columns: repeat(3, 1fr);
}
Burglar answered 27/12, 2020 at 16:54 Comment(0)
M
0

Quick point before solution. The Moz grid-template mentioned above doesn't stack the divs.. they are still in a grid.. check the link
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout/Masonry_layout#masonry_layout_with_spanning_items

External library is not needed if you have a set number of items and don't require an infinite scroll or A-Z ordering down the page.

!NOTE : The disadvantage with this approach is the ordering of cards is A-Z down each column then across, instead of A-Z across the page and down.. meaning the last item could appear in the first row third column.

However it's really simple and doesn't require external libraries - and if you like to figure out your own approach using a bit of math and logic.. here it is.

Logic Put all of the cards into a d-flex column with flex-wrap, then just a few lines of javascript or jquery that changes container height based the total height and width of cards, which casuses the columns to overflow with their wrapping to generate columns that do not overflow and are reasonably flush at the bottom.

Logic example ie. peudocode

arrayofcards = getallelements('cards'), 
sumHeights = arrayofcards.map(arrayofcards.height),
height of container = sumHeights / numberOfDesiredColumns
width of cards = (innerWidth / numberOfDesiredColumns) - gapWidth

Actual Code Example

HTML

<div class="cards-group d-flex flex-column flex-wrap">
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
</div>

Jquery/Javascript

$(()=>{
   // get the card dom elements
   var cardArray = Array.from($('.cards-group').find('.card'));
   // get width of the card container / parent div
   var innerWidth = $('.cards-group').width();

   // get the cumulative height for all the cards
   var cardArrayHeight=0;
   cardArray.map((card)=>{  cardArrayHeight += $(card).height() });

   // your custom number of columns (which you could data-tag to parent div)
   let colNumber = 3  // change to suit tastes
   // your custom card gap (which you could data-tag to parent div)
   let colGap = 16 //= 1 rem default for html/body  // change to suit tastes

   // card width is the based on column numbers, less a column gap
   var cardWidth = (innerWidth / colNumber) - colGap 
   // the total cumulative height is the height of all the cards, plus all the gaps except one gap (don't include a gap at the end)
   var layoutTotalCardHeight = cardArrayHeight + ((cardArray.length-1) * colGap)
   // the container height, will be a gross down of the height to fit into the number of columns, LESS the gaps at the bottom of each folumn
   var containerHeight = (layoutTotalCardHeight / (1+ (1/colNumber))) - (colNumber * colGap)

   $('.cards-group').height(containerHeight);
   $('.cards-group').css('gap',colGap);
   $('.cards-group .card').css('width',cardWidth);

})

There's always more than one way to peel a banana.

Mccann answered 15/8, 2023 at 3:23 Comment(0)
B
-1

What you want to achieve is called a Masonry layout. There are different ways to do this, with CSS grid, Flexbox or with CSS' column functionality. Check out this link on css-tricks.com for details to the approaches.

Bermuda answered 27/12, 2020 at 16:58 Comment(1)
Indeed ! It is a Masonry Layout and CSS-Grids can help the most. CSS Grid also has grid-template-rows: masonry; available :)Chaiken

© 2022 - 2024 — McMap. All rights reserved.