Reputation: 784
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.
col-4
.So, a "big" element can be large col-4
, col-8
or col-12
depending on its position.
In a picture:
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?
Upvotes: 5
Views: 1607
Reputation: 41327
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.
flex
insteadFor each "big" element:
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)
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:
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>
flex
example with auto-inserted row breaksIf you are unable/unwilling to append the empty div
s 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>
Upvotes: 2
Reputation: 2183
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):
.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
Upvotes: 2