Using Flexbox for dynamic-height items with column wrapping

Struggling to create a dynamic layout that adapts differently for mobile and desktop devices? The goal is to have items sorted based on screen size, with the layout changing accordingly.

Check out the main objective below, with a mobile layout on the left and a desktop layout on the right:

https://i.sstatic.net/nPwGD.png

The content in the blue, purple, and yellow divs may vary, allowing for adjustable heights. On desktop, the purple and yellow blocks should always be positioned next to the gray + blue block.

Currently, the layout works well with only 3 columns, but the dynamic height is duplicated across all columns. See the issue here: Bootstrap 4: sidebar between columns on mobile. Columns under each other layout

Explore some desktop variations for more possibilities: https://i.sstatic.net/D8YLK.png

I've tried using floats, but the columns end up aligning on top of each other. I've also experimented with a static max-height for the parent container and column wrap, but I prefer to avoid a fixed height as the content should be dynamic.

My goal is to achieve this without relying on glitchy JavaScript or unsupported grid-CSS solutions.

Share your ideas and suggestions - looking forward to hearing from you! Cheers.

Answer №1

To achieve the desired layout, you can utilize a combination of CSS columns (instead of CSS grid) for "desktop" and flexbox for "mobile".

<div class="container">
    <div class="d-flex d-md-columns flex-column min-vh-100">
        <div class="d-md-inline-block light order-0">
            light
        </div>
        <div class="d-md-inline-block blue order-2">
            blue
        </div>
        <div class="d-md-inline-block purple order-1">
            purple
        </div>
        <div class="d-md-inline-block yellow order-3">
            yellow
        </div>
    </div>
</div>

For the larger (md) desktop widths, include a media query to adjust the columns layout. On mobile, the flexbox ordering will take effect.

@media (min-width: 768px) {
    .d-md-columns {
        display: inline-block !important;
        column-count: 2;
        -webkit-column-gap: 0;
        -moz-column-gap: 0;
        column-gap: 0;
    }
}

This method is tailored for a 4 column layout. Keep in mind that flexbox columns do not seamlessly align vertically like a "masonry" layout: Is it possible for flex items to align tightly to the items above them?

Answer №2

It seems like finding a pure CSS solution for this layout challenge is quite tricky without resorting to CSS-grid or display:contents. I've tested various CSS methods like float and column flexbox, but they don't quite work in this specific case.

Column flexbox struggles to properly wrap an item when dealing with variable height content, while float alone can't achieve a masonry layout effect. Even Bootstrap's card-columns won't solve the problem because the main goal is to align the left and right columns equally in height.

While I understand the desire to avoid buggy JavaScript, sometimes it's necessary to achieve the desired layout. That's why I'm sharing a jQuery solution that doesn't rely on adding a d-none class to prevent duplication issues and SEO problems.

Considering that you're already using Bootstrap, a framework that heavily incorporates jQuery, seeking a bit of jQuery assistance shouldn't be a major concern. Here's the solution I propose:

function move(){
    if($(".main .col-lg-8").css('display')=='block'){
      $('.purple').insertAfter('.gray');
    } else {
      $('.purple').insertBefore('.yellow'); 
    }
}

$(window).resize(function(){move()})
$(document).ready(function(){move()})

This function moves the purple div to the second position when .col-lg-8 is displayed with block visibility.

Here's the complete code in action:

function move(){
  if($(".main .col-lg-8").css('display')=='block'){
    $('.purple').insertAfter('.gray');
  } else {
    $('.purple').insertBefore('.yellow'); 
  }
}

$(window).resize(function(){move()})
$(document).ready(function(){move()})
.gray{
  background-color: gray;
}

.blue{
  background-color: blue;
}

.purple{
  background-color: purple;
}

.yellow{
  background-color: yellow;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>

<div class="container mt-5">
  <div class="row main">
      <div class="col-lg-4 d-lg-flex flex-lg-column">
        <div class="gray mb-4">
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque sodales finibus faucibus. Morbi blandit neque a diam laoreet pellentesque. Vivamus in orci sed turpis posuere iaculis quis sed augue. Curabitur lorem magna, bibendum vitae vestibulum nec faucibus. Morbi blandit neque a diam laoreet pellentesque. Vivamus in orci sed turpis posuere iaculis quis sed augue. Curabitur lorem magna, bibendum vitae vestibulum nec, feugiat eget justo. Ut aliquam quis velit non euismod. Ut vehicula, sem quis cursus pretium, purus libero tincidunt eros, vitae hendrerit nisi mi vitae erat. Curabitur augue purus, sagittis tempor volutpat quis, congue sed mi. Sed gravida odio sed orci iaculis tincidunt. Etiam ac mauris sit amet turpis consequat fermentum ut vitae sem. Aliquam tincidunt convallis sem.</div> 
        <div class="blue flex-fill mb-4 mb-lg-0">
        Lorem ipsum dolor sit amet, consectetur.Quisque sodales finibus </div>
      </div>
      <div class="col-lg-8 d-lg-flex flex-lg-column">
        <div class="purple mb-4">
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. faucibus. Morbi blandit neque a diam laoreet pellentesque. Vivamus in orci sed turpis posuere iaculis quis sed augue. Curabitur lorem magna, bibendum vitae vestibulum nec, feugiat eget justo. Ut aliquam quis velit non euismod. Ut vehicula, sem quis cursus pretium, purus libero tincidunt eros, vitae hendrerit nisi mi vitae erat. Curabitur augue purus, sagittis tempor volutpat quis, congue sed mi. Sed gravida odio sed orci iaculis tincidunt. Etiam ac mauris sit amet turpis consequat fermentum ut vitae sem. Aliquam tincidunt convallis sem. </div>
        <div class="yellow flex-fill">
        Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>
      </div>
  </div>
</div>

If you're still looking for a purely CSS solution, this might be a viable approach.

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

CSS stylized horizontal navigation bar completed

* { border: 0px; margin: 0px; padding: 0px; } body { background-color: #FFC; } #wrapper { width:70%; margin: 0% auto; } #header { background-color: #C1D1FD; padding: 3%; } #nav { clear:both; padding: auto; position:inherit; background-color:#F0D5AA; wid ...

What is the best way to make an animated image move?

Seeking guidance on how to achieve a particular effect like the one showcased at I'm specifically interested in replicating the block movement upon hover and the change in block coordinates when the cursor is not active. Does anyone know of a suitabl ...

In-line divs are known for their rebellious nature, refusing to conform to traditional

I'm in need of some assistance with taming my unruly HTML. It seems to be misbehaving lately. The content area on the page I'm currently designing has a two-column layout. Instead of using separate containing divs for each column, I opted for a ...

Relocate a table beside an image

Check out the layout of my webpage: ------------- ------------- Image here ------------- ------------- Table1 here Table2 here Table3 here My goal is to redesign it to look like this: ------------- ------------- Image here Table1 here - ...

Dynamic Loading of CSS Styles

My style-sheet is saved in this unique location: /opt/lampp/htdocs/project/core/styles/Style.css To load the CSS file using the full directory, considering that the files utilizing it are situated here: /opt/lampp/htdocs/project/client/ The ultimate ob ...

Turning off the ability to horizontally scroll in an iframe using touch controls

I am trying to disable horizontal scrolling in an iframe on my website, particularly when a user uses touch input and drags horizontally. The scroll bars can still be visible and draggable when touched directly. Unfortunately, I do not have control over th ...

Adapting a CSS design

Having some trouble with creating a CSS style. Here's what I have so far: http://jsfiddle.net/WhNRK/26/ Originally designed for a label, but now attempting to modify it for something like this: <input type='radio' name='mcq' ...

What is the best way to add a border to the <map coordinates>?

Is there a way to add a border around the active link section of an image defined by coordinates? I have been able to show an outline when the user clicks using outline-color and href, but now I need a default border around the specified coordinates. I am ...

What is the best way to implement a never-ending scrolling grid loader within a scrollable area using Codeigniter?

In my Codeigniter framework and bootstrap installation, I have multiple sub-pages. On one of these pages, I am attempting to implement an infinite scroll loader using a jQuery script from a tutorial found at gridScrollFx.js. Here is the JS file I am using: ...

What are the best practices for avoiding text wrapping around a DIV?

I have scoured this site extensively, searching for a solution to my problem. What I thought was a simple issue has left me frustrated after hours of trying to figure it out on my own. So, I've finally admitted defeat and turned to seek help... Here& ...

What is the best way to unselect the "all" selector if one of the inputs is no longer selected?

I am facing an issue with a search filter functionality. When all filters are selected and then deselected individually or together, the "all" button remains selected. I need help in ensuring that when any filter is deselected, the "all" button also gets d ...

Ensure that button positioning lines up properly even if adjacent content causes it to shift

I have developed several products using only HTML & CSS. One challenge I am encountering is that when the content inside the div exceeds a certain length, it causes everything to shift down, resulting in uneven alignment (refer to the 3rd product in the i ...

What is the process to design and implement this button using HTML and CSS?

I am in need of creating a button similar to the google button shown in the image, but I am struggling to position it correctly on the margin. Can someone please assist me with this? The google button is the specific type of button that I am aiming to rep ...

What is the best way to make hyperlinks in impress.js?

Wanting to craft a visually stunning brochure for my client with the help of impress.js. I want to include a link on each slide that directs to the relevant page when clicked. Is it feasible to have a clickable link to each slide on every page as well? ...

Utilizing a webkit transition to conceal a div element by setting its display property to "none"

I'm currently working with code that looks something like this: <style> #submenu { background-color: #eee; height:200px; width:400px; opacity: 1; -webkit-transition: all 1s ease-in-out; } .doSomething { ...

Turn off automatic zooming for mobile device input

One common issue observed in mobile browsers is that they tend to zoom in on an input field or select drop-down when focused. After exploring various solutions, the most elegant one I came across involves setting the font-size of the input field to 16px. W ...

Trigger the show.bs.modal event prior to the parent event being called

In my Bootstrap website (built with Bootstrap 4), I have a button that triggers a modal and transfers the data from the button to the form inside the modal using the following function: $('#exampleModal').on('show.bs.modal', function ( ...

Personalized jQuery Slider with automatic sliding

I am currently working on creating my own image slider without relying on plugins. 1st inquiry : How can I achieve horizontal animation for the slider? 2nd inquiry : I want the images to cover both the height and width of their container while maintainin ...

Retrieve the input value from a Bootstrap Form Input

When using a Bootstrap Form Input to allow the user to enter text, I am wondering how to save that text and use it as a parameter in a function. Below is the HTML snippet I have: <!--Directory Input Form--> <div class="row"> <div class= ...

In a jQuery application, the action of adding text from an input field to a div is triggered by clicking a

It's possible this is a duplicate question, but none of the answers I found solved my issue. I'm attempting to create a jQuery script where text entered into a text box is appended to a div when a button is clicked. This is part of a game I' ...