marly
marly

Reputation: 55

Is there a DRY way of Flex ordering?

Newbie to flex use/web development.

I currently have 6 boxes within a flex container ordered like this for mobile devices: Mobile view

with code more or less like this (CSS not included, but the class “box” is the grey box you see above):

<div class="flex-container">
    <div class=“box item” />
    <div class=“text item”>
        <h4>Text</h4>
    </div>
    <div class=“box item” />
    <div class=“text item”>
        <h4>Text</h4>
    </div>
    <div class=“box item” />
    <div class=“text item”>
        <h4>Text</h4>
    </div>
</div> 

This is what I want for mobile devices!

For desktop however, I’d like to achieve this: Desktop View

Currently, the only way I’m achieving this is by using this unappealing flex order css:

item:nth-of-type(1) {order:1;}
item:nth-of-type(2) {order:2;}
item:nth-of-type(3) {order:4;}
item:nth-of-type(4) {order:3;}
item:nth-of-type(5) {order:5;}
item:nth-of-type(6) {order:6;}

My question is, is there a way to achieve my desired goal (i.e. switching the order of items 3 and 4) without having to order every single item in the container creating a yucky, repetitive block of code?

Upvotes: 1

Views: 122

Answers (4)

Asons
Asons

Reputation: 87191

You can accomplish that with only 2 CSS selectors, and with order defaults to 0, we re-position item 3 and 5/6, here done with a media query for screens wider than 600px, to 1 and 2.

.item:nth-of-type(3)   { order:1; }               /*  put 3 after 4   */
.item:nth-of-type(n+5) { order:2; }               /*  put 5,6 after 3 */

Stack snippet

.flex-container { display: flex; flex-wrap: wrap; }
.item           { height: 50px; flex-basis: 100%; }
.box            { background: lightgray; }

@media (min-width: 600px) {
  .item                  { flex-basis: 50%; }
  .item:nth-of-type(3)   { order:1; }               /*  put 3 after 4   */
  .item:nth-of-type(n+5) { order:2; }               /*  put 5,6 after 3 */
}
<div class="flex-container">
  <div class="box item"></div>
  <div class="text item">
    <h4>Text</h4>
  </div>
  <div class="box item"></div>
  <div class="text item">
    <h4>Text</h4>
  </div>
  <div class="box item"></div>
  <div class="text item">
    <h4>Text</h4>
  </div>
</div>

Upvotes: 1

Israfel
Israfel

Reputation: 1692

In addition to TripWire's answer, you need not to set a different order number for every <div> after the 4th one.

.item:nth-of-type(3), .item:nth-of-type(4) ~ .item {order:100;}
.item:nth-of-type(4) {order:50;} 

A pen: https://codepen.io/israfel/pen/eEbWWG

Upvotes: 0

monners
monners

Reputation: 5302

If you only ever want to switch those two, you could wrap them in another flex container and simply switch ordering within. That way your outer flow won't have to be redefined, and you could set up the container to be reused in other areas where you need to achieve the same thing.

<div class="container">
  <div class="item one">One</div>
  <div class="item two">Two</div>
  <div class="item three">Three</div>
  <div class="switch">
    <div class="item four">Four</div>
    <div class="item five">Five</div>
  </div>
  <div class="item six">Six</div>
  <div class="item seven">Seven</div>
</div>


.item {
  flex: 1 0 100%;
  line-height: 39px;
  height: 40px;
  width: 100%;
  background: #cecece;
  margin-bottom: 10px;
  text-align: center;
}
.container {
  display: flex;
  flex-wrap: wrap;
}

.switch {
  display: flex;
  flex-wrap: wrap;
  flex: 1 0 100%;
}

@media (min-width: 400px) {
  .switch .item:nth-of-type(1) {
    order: 2;
  }
}

fiddle

Upvotes: 0

TripWire
TripWire

Reputation: 552

As far as I know if you reorder items, you need to explicitly order items after the re-ordered items. So you could probably do:

item:nth-of-type(3) {order:4;}
item:nth-of-type(4) {order:3;}
item:nth-of-type(5) {order:5;}
item:nth-of-type(6) {order:6;}

Upvotes: 0

Related Questions