SwammiM
SwammiM

Reputation: 493

Responsive flexbox and reordering subchildren

I need some help with responsive html.

I have a flexbox layout, with two columns. Each column contains two divs of varying height.

columns

On mobile, I set flex-direction to column, so it breaks into one column :

one-column

But as you might have guessed, I want the order to be ABCD. I realize I probably can't do that with my current setup, because AFAIK you can't order sub-children. But what are my options to get the desired result?

I could rearrange things with javascript, but I'd prefer a pure CSS approach, if possible.

Can this be achieved? Do I need CSS Grids to do this?

I've added a snippet to illustrate the issue. Also on codepen : https://codepen.io/Mudloop/pen/PowrKPV

(it doesn't have media queries for simplicity, just the same html twice with a different class).

* { box-sizing: border-box; }
body { background-color: #444; color: white; font-family: sans-serif; max-width:650px; }

.normal {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: flex-start;
  margin: 20px;
}
.normal > div {
  color: white;
  width: calc(50%);
}
.normal > div > div {
  background-color: #333;
  padding: 10px;
  margin: 10px;
}


.mobile {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  align-items: flex-start;
  margin:20px;
}

.mobile > div {
  color: white;
  width: 100%;
}
.mobile > div > div {
  background-color: #333;
  padding: 10px;
  margin: 10px;
}
<body>
  Desktop
  <div class="normal">
    <div>
      <div>A<br></div>
      <div>C<br><br><br><br><br></div>
    </div>
    <div>
      <div>B<br><br></div>
      <div>D<br><br><br></div>
    </div>
  </div>

  Mobile
  <div class="mobile">
    <div>
      <div>A<br></div>
      <div>C<br><br><br><br><br></div>
    </div>
    <div>
      <div>B<br><br></div>
      <div>D<br><br><br></div>
    </div>
  </div>
</body>

Upvotes: 3

Views: 1106

Answers (2)

Kosh
Kosh

Reputation: 18393

You might use multi-column layout for desktop.
And switch to flex (which allows to reorder elements) on mobile using media query.

Run the example below in the Full page mode and try to resize the window:
(I added some text to the blocks to make them more real-world)

* {
  box-sizing: border-box;
}

body {
  background-color: #444;
  color: white;
  font-family: sans-serif;
  max-width: 1280px;
  width: 100%
}

.normal {
  padding: 10px;
  border: solid 1px #ccc;
  margin: 20px;
  columns: 2 200px;
  column-fill: balance;
}

.normal>div {
  margin: 0 0 10px;
  padding: 10px;
  background-color: #333;
  page-break-inside: avoid;
}

@media (max-width:480px) {
  .normal {
    display: flex;
    flex-direction: column
  }
  .normal>div:nth-child(1) {
    order: 1
  }
  .normal>div:nth-child(2) {
    order: 3
  }
  .normal>div:nth-child(3) {
    order: 2
  }
  .normal>div:nth-child(4) {
    order: 4
  }
}
Desktop
<div class="normal">
  <div>A<br>Lorem ipsum, or lipsum as it is sometimes known, is dummy text used in laying out print, graphic or web designs.</div>
  <div>C<br>The purpose of lorem ipsum is to create a natural looking block of text (sentence, paragraph, page, etc.) that doesn't distract from the layout. A practice not without controversy, laying out pages with meaningless filler text can be very useful
    when the focus is meant to be on design, not content.</div>
  <div>B<br>It usually begins with:<br>“Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.”</div>
  <div>D<br> The passage is attributed to an unknown typesetter in the 15th century who is thought to have scrambled parts of Cicero's De Finibus Bonorum et Malorum for use in a type specimen book.</div>
</div>

Upvotes: 1

Scott O&#39;Toole
Scott O&#39;Toole

Reputation: 326

Yes, you can do this with using the order property on children inside of a container with display: flex, combined with media queries, without using grid. I'm not sure what the constraints are for your layout regarding the HTML structure, so I altered it a bit.

I used a max-height for the "desktop" layout to force the flex items to wrap with a column flow. Then, when the media query was triggered (you would set this to whatever mobile size you were supporting), the max height is removed, and the items inside can set themselves up in a column according to the order property you specify.

You can throw this in a codepen, play with the window size, and it should work.

<body>
  Desktop
  <div class="normal">
      <div id="a">A<br></div>
      <div id="c">C<br><br><br><br><br></div>
      <div id="b">B<br><br></div>
      <div id="d">D<br><br><br>
    </div>
  </div>

* { box-sizing: border-box; }
body { background-color: #444; color: white; font-family: sans-serif;  }

.normal {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  align-items: flex-start;
  margin: 20px;
  max-height: 200px;
}
.normal > div {
  color: white;
  width: calc(50%);
}
.normal > div {
  background-color: #333;
  padding: 10px;
  margin: 10px;
}

@media (max-width: 500px) {

  .normal {
    display: flex;
    flex-direction: column;
    flex-wrap: none;
    align-items: center;
    max-height: none;
  }

  #a {
    order: 1
  }

  #b {
    order: 2
  }

  #c {
    order: 3
  }

  #d {
    order: 4
  }

}

Upvotes: 0

Related Questions