Responsive DIVs placement with Bootstrap
Asked Answered
S

1

5

I need to place some DIVs inside their parent container, no matter if it is the body, table's cell or another div, with Bootstrap 5, like shown on the attached illustration:

In case of even number of DIVs they should take 50% of the available width placed by 2 at a single line. Or, in case there is odd number of DIVs, the last one should take 100% of the available width while all previous still take 50% of the available width and are placed by 2 at a single line.

Preferably with possibility to change the DIVs order (like on the Mobile View example).

There is no problem to make this with the UIKit using some simple code like

<div class="uk-grid">
    <div class="uk-width-large-1-2">DIV 1 takes 50% of available width</div>
    <div class="uk-width-large-1-2">DIV 2 takes 50% of available width</div>
    <div class="uk-width-large-1-2">DIV 3 takes 100% of available width</div>
</div>

But whatever I've searched for with Bootstrap's documentation (as well as Stack Overflow) I still can't find the solution.

Saponify answered 26/8, 2021 at 17:20 Comment(0)
S
6

Bootstrap is mobile-first, meaning whatever we define at smaller breakpoints will cascade up to larger breakpoints until overridden.

There are 5 explicit breakpoints in addition to the implicit (default) mobile breakpoint:

| Breakpoint | Dimensions
|------------|----------- 
| NONE       | <576px
| sm         | ≥576px
| md         | ≥768px
| lg         | ≥992px
| xl         | ≥1200px
| xxl        | ≥1400px

To resize the divs

Use columns with the responsive breakpoint syntax:

<div class="row g-2">
  <div class="col-12 col-md-6">...</div>
  ...
</div>
  • col-12 specifies full width (12 of 12) at mobile and above
  • col-md-6 specifies half width (6 of 12) at md and above (i.e., starting at md, this rule overrides the col-12 rule)
  • g-2 specifies gutters to auto-pad the columns (or use manual spacing utilities)

Note that the written order (col-12 col-md-6 vs col-md-6 col-12) is irrelevant, as with any css classes. Bootstrap applies the styles in mobile-first order.


To auto-expand the last div

But what if I don't know how many divs are going to be inside the row and therefore do not know if their number would be an odd or an even? Don't know which exact div is going to be the last one but still need the last div inside the container to be 100% width?

If you are using a templating language, I suggest putting this logic in the template. That's a bit out of scope for this question, but for example with django, a minimal template might look like:

<div class="row">
  {% for col in cols %}
  <div class="col-12{% if loop.last and not forloop.counter|divisibleby:2 %} col-md-6{% endif %}">
    ...
  </div>
  {% endfor %}
</div>

Or to handle it with pure css, you could add a width rule targeting the last col if odd:

.row > .col-md-6:last-child:nth-child(odd) {
  width: 100%;
}

To reorder the divs

Use the responsive flex order utilities:

<div class="row">
  <div class="order-2 order-md-1">...</div>
  <div class="order-1 order-md-2">...</div>
  ...
</div>
  • order-2 order-md-1 specifies position 2 at mobile and above, position 1 at md and above
  • order-1 order-md-2 specifies position 1 at mobile and above, position 2 at md and above

Note that the parent container needs to be a flex container. A bootstrap row is flex by default, but for non-flex containers, add the d-flex class explicitly.


Minimal example

desktop mobile

.row > .col-md-6:last-child:nth-child(odd) {
  width: 100%;
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">

<body class="bg-secondary">
  <div class="container pt-3">
    <div class="row g-2">
      <div class="col-12 col-md-6 order-2 order-md-1">
        <div class="bg-light text-center p-2">DIV 1</div>
      </div>
      <div class="col-12 col-md-6 order-1 order-md-2">
        <div class="bg-light text-center p-2">DIV 2</div>
      </div>
      <div class="col-12 col-md-6 order-3">
        <div class="bg-light text-center p-2">DIV 3</div>
      </div>
      <div class="col-12 col-md-6 order-4">
        <div class="bg-light text-center p-2">DIV 4</div>
      </div>
      <div class="col-12 col-md-6 order-5">
        <div class="bg-light text-center p-2">DIV 5</div>
      </div>
    </div>
  </div>
</body>
Sulfapyridine answered 26/8, 2021 at 17:32 Comment(7)
@Sulfapyridine Also I should remove col-md-6 for the last DIV in order to make it 100% width. But what if I don't know how many DIVs are going to be inside the row and therefore do not know if their number would be an odd or an even? Don't know which exact DIV is going to be the last one but still need the last DIV inside the container to be 100% widthSaponify
And one more thing... how to get rid of those default margins? They ruin even your example making the content wider than its container.Saponify
re: odd/even issue, a pure css way is to use child selectors to target the last child if odd (answer updated with example). however if you are using a templating language (e.g. jinja, ejs), i would put that logic in the template (i.e., only add col-md-6 if the last iteration is odd). i added a minimal example of a django template, but beyond that, more in-depth templating issues should probably go in a separate question post.Sulfapyridine
re: margins, my original example was just the bare bare minimum to demo the size/order classes. i updated the example to have more spacing (gutters/padding classes).Sulfapyridine
@Sulfapyridine >it sounds like this is being done within some kind of templating language ... No, it is just a number of the news articles which can change during the day.Saponify
@Sulfapyridine Thanks a lot for explaining each step so detailed. Your solution really works and answers my question, so I've marked it as the answer. But am I the only one who now firmly believes that the Bootstrap's methods are overcomplicated and poorly documented?Saponify
@Saponify You're welcome. Re: Bootstrap complexity, it's hard for me to say since (a) I've been using it for a long time and (b) I'm not too familiar with the alternatives. I do remember struggling with the breakpoint syntax until hearing the "mobile first" explanation, which is why I like to mention that. Also when I see your UIKit example (auto-expand the last div), it does look very appealing. In Bootstrap's defense, it was (one of) the first of its kind, so everyone else has had the opportunity to iterate on it.Sulfapyridine

© 2022 - 2024 — McMap. All rights reserved.