Search code examples
htmlcssreactjssass

Merge 2 flex columns into 1 alternating children


I have a flex container with 2 columns.
Each column is also a flex container with a number of boxes inside.

<div class="flex-container">
  <div class="column left-column">
    <div class="box boxA">Box A</div>
    <div class="box boxB">Box B</div>
  </div>
  <div class="column right-column">
    <div class="box boxC">Box C</div>
    <div class="box boxD">Box D</div>
    <div class="box boxE">Box E</div>
  </div>
</div>

I want that, in mobile view, the 2 columns become 1.
Right now I achieve this by adding flex-direction: column to the flex-container, which makes the 2 columns be one on top of each other (vertically, not z-axis).

.flex-container {
  display: flex;
  gap: 10px;
  padding: 10px;
  max-width: 800px;
}

.column {
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: 10px;
}

.left-column {
  flex: 2;
}

.right-column {
  flex: 1;
}

.box {
  border: 1px solid lightgrey;
  border-radius: 8px;
  padding: 8px;
}

@media (max-width: 800px) {
.flex-container {
   flex-direction: column;
  }
}

But now I need additionally to rearrange the order of the boxes so that, in mobile view, it shows as A, C, D, E, B.

I don't think that can be achieved with CSS alone, since it requires "breaking" the flex columns.

Here's a sandbox with what I have at the moment: https://codepen.io/marcysutton/pen/ZYqjPj

Btw, this is in a React app, so I will probably have to rearrange the boxes programmatically.
I just preferred to do that with CSS, if possible.


Solution

  • Use display: contents at the lower width to "break" the wrapping divs and then order on .boxB.

    .flex-container {
      display: flex;
      gap: 10px;
      padding: 10px;
      max-width: 800px;
    }
    
    .column {
      display: flex;
      flex-direction: column;
      flex: 1;
      gap: 10px;
    }
    
    .left-column {
      flex: 2;
    }
    
    .right-column {
      flex: 1;
    }
    
    .box {
      border: 1px solid lightgrey;
      border-radius: 8px;
      padding: 8px;
    }
    
    @media (max-width: 800px) {
      .flex-container {
        flex-direction: column;
      }
      .column {
        display: contents;
      }
      .boxB {
        order: 2;
      }
    }
    <div class="flex-container">
      <div class="column left-column">
        <div class="box boxA">Box A</div>
        <div class="box boxB">Box B</div>
      </div>
      <div class="column right-column">
        <div class="box boxC">Box C</div>
        <div class="box boxD">Box D</div>
        <div class="box boxE">Box E</div>
      </div>
    </div>