Home > Mobile >  How to instantly reverse flexbox item order with non-full row at the bottom?
How to instantly reverse flexbox item order with non-full row at the bottom?

Time:11-21

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 >
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
  <div ></div>
</div>

CodePudding user response:

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 >REVERSE</button>
<button >NORMAL</button>

<div >
  <div >1</div>
  <div >2</div>
  <div >3</div>
  <div >4</div>
  <div >5</div>
  <div >6</div>
  <div >7</div>
  <div >8</div>
  <div >9</div>
  <div >10</div>
  <div >11</div>
  <div >12</div>
  <div >13</div>
  <div >14</div>
</div>

CodePudding user response:

.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 >
        <div >1</div>
        <div >2</div>
        <div >3</div>
        <div >4</div>
        <div >5</div>
        <div >6</div>
        <div >7</div>
        <div >8</div>
        <div >9</div>
        <div >10</div>
        <div >11</div>
        <div >12</div>
        <div >13</div>
        <div >14</div>
      </div>

CodePudding user response:

I think you can easily fix your problem by setting the flex-direction to row-reverse

https://flexboxfroggy.com/#fr[Here is a game to help you with flex:][1]

  • Related