Creating a unique Bootstrap 5 layout for various sized cards, inspired by the popular Pinterest design

I'm currently in the process of building a website using Bootstrap 5. One section of the website will feature various cards, similar to this example: https://i.sstatic.net/haNeN.png

Each card on the site may vary in size depending on the content and thumbnail image included. My goal is to make them appear compact, much like the layout seen on the Pinterest homepage.

Which class should I use in Bootstrap 5 to achieve this compact card layout? Any suggestions for the ideal layout configuration?

Answer №1

According to the Bootstrap 5 documentation, the Masonry JS plugin is now the favored choice for achieving a "Pinterest" style layout. The card-columns feature from Bootstrap 4 is no longer included in Bootstrap 5.

Implementing the Masonry plugin is straightforward. Simply utilize the appropriate col-* class to specify the number of columns and add the data-masonry attribute to the parent 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 approach (i.e., grid-template-rows: masonry;) mentioned by others currently functions only in Firefox, and it is not yet advised as a standard method.

Answer №2

#content-box {
  columns:3;
  column-gap: 5px;
}
#content-box>div {
  background: #c1c1ff;
  margin-bottom: 5px;
  break-inside:avoid;
}
<div id="content-box">
<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>

Answer №3

Avoid utilizing Bootstrap in this scenario and opt for the CSS Grid Feature instead. It can efficiently handle dynamic content looping and is simple to configure.

.grid-container {
    width: 100%;
    margin: 0 auto;
    display: grid;
    grid-gap: 20px;
    text-align: center;
    margin-top: 1rem;
    grid-template-columns: repeat(3, 1fr);
}

Answer №4

Just a quick note before we jump into the solution. The grid-template in Moz mentioned earlier keeps the divs in a grid layout rather than stacking them, you can find more information at this link: here

If you have a fixed number of items and don't need features like infinite scrolling or A-Z ordering down the page, you won't require an external library.

One thing to keep in mind is that with this approach, the cards are ordered A-Z down each column and then across, instead of A-Z across the page and down, which could lead to the last item appearing in an unexpected spot.

But if you enjoy figuring things out on your own and don't want to rely on external libraries, here's a simple math and logic-based approach:

The Logic You can place all the cards in a d-flex column with flex-wrap, and then use a few lines of JavaScript or jQuery to adjust the container height based on the total height and width of the cards, causing the columns to overflow with their wrapping to create neat columns without overflowing issues.

An Example of the Logic Pseudocode:

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

   // calculate the card width based on the number of columns, minus the gap width
   var cardWidth = (innerWidth / colNumber) - colGap 
   // calculate the total card height including gaps between each card except the last one
   var layoutTotalCardHeight = cardArrayHeight + ((cardArray.length-1) * colGap)
   // set the container height to fit into the specified number of columns while accounting for gaps
   var containerHeight = (layoutTotalCardHeight / (1+ (1/colNumber))) - (colNumber * colGap)

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

})

Remember, there are always multiple ways to achieve the same result!

Answer №5

Creating a Masonry layout is the goal you're aiming for. Achieving this can be done using various methods such as CSS grid, Flexbox, or utilizing CSS columns. For more in-depth information on these approaches, I recommend checking out this resource on css-tricks.com.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Pairing two actions with a single event

I am looking to connect two events together. Currently, I have set up a binding for all mouse actions to a canvas and then utilize a wrapper function to adjust the mouse position relative to the canvas. This wrapper function then triggers the appropriate ...

Floating left and right positions for a fixed CSS div

My navbar is currently set to float right and 330px left with absolute positioning. Everything is working fine in this setup, but I want it to be fixed. The problem arises when trying to convert it to a fixed position. I've tried various methods but n ...

Struggling with implementing CSS in React even after elevating specificity levels

I am struggling with a piece of code in my component that goes like this: return ( <div className="Home" id="Home"> <Customnav color="" height="80px" padding="5vh"/> <div className= ...

Using jQuery functionality on rendered results in Angular

Currently, I'm working on truncating a string based on its character count and then adding an ellipsis if the number of characters exceeds 21. I've included a truncate class in the HTML div using jQuery. Everything seems to be functioning correc ...

Set the height of the main div container to a fixed size

I am facing an issue with my div container (mapInfo-Container) which contains multiple div blocks. I want the container to have a fixed height of 250px, and be scrollable for any content exceeding this height. Here is the code snippet: http://jsfiddle.net ...

Show image in entire browser window without resizing unless image is oversized

I am trying to achieve the display of an image centered within the entire browser window with a few conditions in place. If the image can fit within the browser's client area, it should be displayed at its original size. If the image is too tall or to ...

What is the best way to ensure that my chosen fonts are implemented on a text box?

I've designed a dropdown menu featuring various font styles. Below the list, I've included a text box. How can I ensure that my font selection applies to the text in the textbox? The goal is to offer customers the ability to personalize their na ...

Executing an .exe file directly through a web browser (using any method)

Currently, I am managing various devices within a local network through a page. However, there are certain advanced settings that can only be accessed by using an .exe file located on the computer where the configuration page is run. I would like to stream ...

Displaying a picture solely in a designated region

I created a basic menu using an unordered list: <ul class="courses"> <a href="#"> <li class="spinny"> <h3>Course Title</h3> <img class="rotateme" src="images/logo_transparent.png"/> </li& ...

Enhance the functionality of selectize.js by incorporating select options through ajax

I'm currently working on implementing options to a select box using AJAX and selectize.js. When not using selectize.js, everything functions correctly. The two select boxes are interconnected so that when one is updated, the values in the other select ...

Struggling to make AngularJS routes function properly

After starting from scratch, I rebuilt it with freshly downloaded angularJS (version 1.5.8). I simply placed both angular.js and angular-route.js in the library folder following this setup: https://gyazo.com/311679bf07249109671d621bc89d2d52 Here is how in ...

Chrome does not support gradient, while Firefox does

When I attempt to utilize the webkit gradient tag specifically for Chrome, it fails to function altogether. On the other hand, when tested on Firefox using background:-moz-linear-gradient(#000, #888);, it operates smoothly. Despite this, applying backgrou ...

Enhancing functionality with extra JavaScript tags in next.js

Recently, I delved into programming with react & next.js after previously working with node.js. It didn't take long for me to create my first application, but upon inspecting the page, I noticed an abundance of extra JavaScript code (see image below). ...

What could be causing my React components to not display my CSS styling properly?

If you're developing a React application and integrating CSS for components, ensure that you have included the style-loader and css-loader in your webpack configuration as shown below: module.exports = { mode: 'development', entry: &apo ...

Utilizing fanybox-2 for creating a variety of background colors

I am currently using fancybox to showcase some of my website links with opaque backgrounds as requested by the designer. I have successfully customized the background color to meet the requirements. However, I am now facing a new question: is it possible ...

Utilizing document.getSelection() for extracting data into an array, similar to how document.getSelection().toString() functions for handling strings

In my Angular JS application, I have a table with filtering functionality. I need to extract only the selected data from the table and store it in an array of arrays called "rows[]" and "cell[]". This makes it challenging to just export the entire table da ...

Aligning the Navbar in the center causes the text to become compressed

My goal is to have a navbar that is always centered and displayed at the top of the screen. However, every time I try to fix it, something goes wrong and the text gets all smushed together. I want the navbar to be straight across without any overlap betwee ...

It is not possible to invoke a function within the AJAX success method

When trying to display an error message in my notify (toast) div using jQuery in Ajax success, I am encountering difficulties. Despite decoding the response from the URL properly, only .show() and .hide() functions seem to work. Although I have used conso ...

Tips for managing three select menus in AngularJS

Assistance needed for creating a series of interconnected dropdown menus in AngularJS. The functionality should allow the second dropdown to open upon selecting a value in the first dropdown, and the third dropdown to open upon selecting a value in the sec ...

Full page occupied by image, not just a banner separator

I'm having trouble creating a scrolling banner that blurs as you scroll. Whenever I attempt it, the image takes up the entire page background (it's positioned behind all elements but still fills the entire page). I actually want the image to be i ...