skip to Main Content

I receive some elements, and I want to insert some elements in a page. These elements can be "small" or "big". I cannot know in advance how many elements I will receive, or their order.

  • If they are "small", I want them to be large col-4.
  • If they are "big", I want them to be large as much as possible, from the previous element to the end of the row.

So, a "big" element can be large col-4, col-8 or col-12 depending on its position.
In a picture:

enter image description here

The most-similar question I’ve found on SO is the following: Bootstrap fill remaining columns

I have tried to use the approach suggested in the question, but it does not cover the case when, in the same row, you have a "small" element after a "big" element. Using the same words from the linked question:

it does not cover the case when, in the same row, you have a blue element after a rogue element

.col-4{
  background:red;
}

.big{
 background:yellow; 
}

.row{
  background:white;
}

 
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>

<h1>
Expected result
</h1>
The goal is to obtain this same behaviour using the same style for every "big" element

<div class="container-fluid pt-2">
  <div class="row">
    <div class="col-4 mb-1">
      small
    </div>
    <div class="col-4  mb-1">
      small
    </div>
    <div class="col-4  mb-1">
      small
    </div>
    <div class="col-12 big mb-1">
      big
    </div>
    <div class="col-4   mb-1">
      small
    </div>
    <div class="col-4  mb-1">
      small
    </div>


    <div class="col-4 big mb-1">
      big
    </div>
    <div class="col-4  mb-1">
      small
    </div>
    <div class="col-8 big mb-1">
      big
    </div>
    <div class="col-4  mb-1">
      small
    </div>
    

  </div>
</div>

<h1>
Not working attemp 1 (don't use any col)
</h1>
Issue: The "big" elements start on a new row instead of filling the previous row.

<div class="container-fluid pt-2">
  <div class="row">
    <div class="col-4 mb-1">
      small
    </div>
    <div class="col-4  mb-1">
      small
    </div>
    <div class="col-4  mb-1">
      small
    </div>
    <div class="big mb-1">
      big
    </div>
    <div class="col-4   mb-1">
      small
    </div>
    <div class="col-4  mb-1">
      small
    </div>
    <div class="big mb-1">
      big
    </div>
    <div class="col-4  mb-1">
      small
    </div>
    <div class="big mb-1">
      big
    </div>
    <div class="col-4  mb-1">
      small
    </div>

  </div>
</div>


<h1>
Not working attemp 2 (use only "col")
</h1>
Issue: Instead of occupying a whole row, the "big" elements shrink to make space for the next elements

<div class="container-fluid pt-2">
  <div class="row">
    <div class="col-4 mb-1">
      small
    </div>
    <div class="col-4  mb-1">
      small
    </div>
    <div class="col-4  mb-1">
      small
    </div>
    <div class="col big mb-1">
      big
    </div>
    <div class="col-4   mb-1">
      small
    </div>
    <div class="col-4  mb-1">
      small
    </div>
    <div class="col big mb-1">
      big
    </div>
    <div class="col-4  mb-1">
      small
    </div>
    <div class="col big mb-1">
      big
    </div>
    <div class="col-4  mb-1">
      small
    </div>

  </div>
</div>

https://jsfiddle.net/bhLq86o4/

So, how can I assign to the "big" elements the same class, so that the final results looks like the one described in the examples?

2

Answers


  1. After trying multiple possible configurations (flex, grid, float, etc.), I figured out how you can do it as requested ("big" elements have the same class):

    CODE:

    .small {
      width: 33.3%;
      float: left;
      background: red;
    }
    
    .big {
      background: yellow; 
    }
    <h1>
      Expected result
    </h1>
    The goal is to obtain this same behaviour using the same style for every "big" element
    
    <div>
      <div class="small">
        small
      </div>
      <div class="small">
        small
      </div>
      <div class="small">
        small
      </div>
      <div class="big">
        big
      </div>
      <div class="small">
        small
      </div>
      <div class="small">
        small
      </div>
    
    
      <div class="big">
        big
      </div>
      <div class="small">
        small
      </div>
      <div class="big">
        big
      </div>
      <div class="small">
        small
      </div>
    </div>

    Some final words: since this is a non-obvious task, I recommend you to do it with native CSS, instead of struggling many days with BS classes.

    Regards

    Login or Signup to reply.
  2. Don’t use float

    @perplexyves’ answer won’t work in practice. It only looks correct because OP’s example only has one word per div.

    It breaks if we add some more content, e.g., to the second div:

    It will also break in plenty of other ways (e.g., padding/margins as OP noticed) because the float layout is not a real grid, just a superficial hack.


    Use flex instead

    For each "big" element:

    1. Use Bootstrap’s .flex-grow-1 class to fill the remaining row

      (Or if you prefer using your own .big class, add .big { flex-grow: 1 !important; } to your CSS)

    2. Add an empty div to force a row break

    <div class="col-4 flex-grow-1">big</div> <div></div>
    <!--              ^fill to end           ^break into new row  -->
    

    This flex layout will produce a real grid that works regardless of content/styling:


    Complete flex example

    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
    
    <div class="row">
      <div class="col-4 bg-warning">small</div>
      <div class="col-4 bg-warning">This is the second `div` using the `flex` layout. Note how the grid is completely fine now, even with longer/uneven content.</div>
      <div class="col-4 bg-warning">small</div>
      <div class="col-4 bg-danger flex-grow-1">big</div> <div></div>
      <!--                        ^fill to end           ^break row -->
      <div class="col-4 bg-warning">small</div>
      <div class="col-4 bg-warning">small</div>
      <div class="col-4 bg-danger flex-grow-1">big</div> <div></div>
      <!--                        ^fill to end           ^break row -->
      <div class="col-4 bg-warning">small</div>
      <div class="col-4 bg-danger flex-grow-1">big</div> <div></div>
      <!--                        ^fill to end           ^break row -->
      <div class="col-4 bg-warning">small</div>
    </div>

    Complete flex example with auto-inserted row breaks

    If you are unable/unwilling to append the empty divs manually, use insertAdjacentHTML to insert them automatically:

    document.querySelectorAll('.flex-grow-1').forEach(big =>
      big.insertAdjacentHTML('afterend', '<div></div>'))
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
    
    <div class="row">
      <div class="col-4 bg-warning">small</div>
      <div class="col-4 bg-warning">This is the second `div` using the `flex` layout and using JS to automatically insert the empty `div` row breaks.</div>
      <div class="col-4 bg-warning">small</div>
      <div class="col-4 bg-danger flex-grow-1">big</div>
      <!--                        ^fill to end           ^row break will be auto-inserted here via JS -->
      <div class="col-4 bg-warning">small</div>
      <div class="col-4 bg-warning">small</div>
      <div class="col-4 bg-danger flex-grow-1">big</div>
      <!--                        ^fill to end           ^row break will be auto-inserted here via JS -->
      <div class="col-4 bg-warning">small</div>
      <div class="col-4 bg-danger flex-grow-1">big</div>
      <!--                        ^fill to end           ^row break will be auto-inserted here via JS -->
      <div class="col-4 bg-warning">small</div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search