skip to Main Content

I have a flexbox container in which I have around 128 items(the amount can change). I’ll use 14 here. They go like this:

-----------------
|  1  2   3   4 |
|  5  6   7   8 |
|  9 10  11  12 |
| 13 14         |
-----------------

what im trying to achieve is reversing the order so that if the number of items is not divisible by 4 the items are always aligned to the left and the half-empty row is always at the bottom and the items arent stretched in any way. Like this:

-----------------
| 14 13  12  11 |
| 10  9   8   7 |
|  6  5   4   3 |
|  2  1         |
-----------------

I tried doing flex-wrap: wrap-reverse; and flex-direction: row-reverse; but that leaves me with a half-empty row at the top.

-----------------
| 14 13         |
| 12 11  10   9 |
|  8  7   6   5 |
|  4  3   2   1 |
-----------------

After not finding any solution to this I resorted to javascript where I tried changing the order properly.

let itemsCount = $('.flex-container').children().length;

for (let item of $('.flex-container').children()) {
   item.style.order = itemsCount;
   itemsCount--;
}

Which indeed worked! Well, kinda.. Because when I press the reverse button, I can actually see how the items each move during the for loop and it looks very ugly. I need it to be instant.

This is probably a beginner mistake so I really didn’t want to ask here but after hours of unsuccessful attempts I gave up. Any feedback is very much appreciated.

Demo:

.flexbox-container {
  display: flex;
  flex-wrap: wrap;
  flex-direction: row;
  padding-left: 30px;
  padding-right: 30px;
  padding-bottom: 60px;
}

.item {
  width: 330px;
  max-width: 330px;
  height: 400px;
  margin: 15px;
  position: relative;
}
<div class="flexbox-container">
  <div class="item item-1"></div>
  <div class="item item-2"></div>
  <div class="item item-3"></div>
  <div class="item item-4"></div>
  <div class="item item-5"></div>
  <div class="item item-6"></div>
  <div class="item item-7"></div>
  <div class="item item-8"></div>
  <div class="item item-9"></div>
  <div class="item item-10"></div>
  <div class="item item-11"></div>
  <div class="item item-12"></div>
  <div class="item item-13"></div>
  <div class="item item-14"></div>
</div>

2

Answers


  1. .flexbox-container {
        display: flex;
        flex-wrap: wrap-reverse;
        flex-direction: row-reverse;
    }
    
    .item {
        flex: 1 1 24%;
        
        background-color: #111;
        width: 100px;
        height: 100px;
        color: white;
        border: 2px solid tomato;
        text-align: center;
        display: grid;
        place-content: center;
        font-size: 2rem;
        font-family: 'Courier New', Courier, monospace;
    }
    <div class="flexbox-container">
            <div class="item item-1">1</div>
            <div class="item item-2">2</div>
            <div class="item item-3">3</div>
            <div class="item item-4">4</div>
            <div class="item item-5">5</div>
            <div class="item item-6">6</div>
            <div class="item item-7">7</div>
            <div class="item item-8">8</div>
            <div class="item item-9">9</div>
            <div class="item item-10">10</div>
            <div class="item item-11">11</div>
            <div class="item item-12">12</div>
            <div class="item item-13">13</div>
            <div class="item item-14">14</div>
          </div>
    Login or Signup to reply.
  2. This solution uses order property of CSS.

    More about order

    I could not find an easy way to make it work without Javascript, but at least it does the job by manipulating style only.

    It does work no matter the amount of items is 14 or 128, and fit with any width of the container.

    Hope this will help!

    Example:

    const items = document.querySelectorAll(".item");
    const btnReverse = document.querySelector(".btn.reverse");
    const btnNormal = document.querySelector(".btn.normal");
    
    btnReverse.addEventListener("click", () => items.forEach((item, index, arr)=>item.style.order = arr.length - index))
    btnNormal.addEventListener("click", () => items.forEach((item)=>item.style.order = ""))
    .flexbox-container {
      display: flex;
      flex-wrap: wrap;
      max-width: 220px;
      gap: 6px;
      margin-top: 12px;
    }
    
    .item {
      order: revert;
      width: 50px;
      max-width: 50px;
      height: 50px;
      display: flex;
      justify-content: center;
      align-items: center;
      font-size: large;
      position: relative;
      background-color: pink;
    }
    
    .btn {
      padding: 3px;
    }
    <button class="btn reverse">REVERSE</button>
    <button class="btn normal">NORMAL</button>
    
    <div class="flexbox-container">
      <div class="item item-1">1</div>
      <div class="item item-2">2</div>
      <div class="item item-3">3</div>
      <div class="item item-4">4</div>
      <div class="item item-5">5</div>
      <div class="item item-6">6</div>
      <div class="item item-7">7</div>
      <div class="item item-8">8</div>
      <div class="item item-9">9</div>
      <div class="item item-10">10</div>
      <div class="item item-11">11</div>
      <div class="item item-12">12</div>
      <div class="item item-13">13</div>
      <div class="item item-14">14</div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search