ARTniyet ARTniyet - 2 months ago 17
CSS Question

Using flex order property to re-arrange items for desktop and mobile views

I have 3 divs inside a container. There are no nested divs.

I am using flex and

order
property.

On mobile, it is ok with
order
property.

But on larger screens it fails.

I did not use a container div for divs 2 and 3 in order to order them as 2,1,3 on mobile.

enter image description here

HTML FILE

<div class="container">
<div class="orange">1</div>
<div class="blue">2</div>
<div class="green">3</div>
</div>


CSS FILE

/*************** MOBILE *************/
.container
{
display: flex;
flex-wrap: wrap;

}
div.blue
{
order:1;
width: 100%;
}
div.orange
{
order:2;
width: 100%;
}
div.green
{
order:3;
width: 100%;

}
/***************************/
@media screen and (min-width:1200px)
{
.container
{
justify-content: space-between;
}
div.blue
{
order:2;
width: 36%;
}
div.orange
{
order:1;
width: 60%;
}
div.green
{
order:3;
width: 36%;
}
}

Answer

In your layout, using row wrap for the desktop view will be difficult, if not impossible, to implement with CSS. At a minimum, things would get overly complex. Why?

Because flexbox is not a grid system. It's a layout system designed to align content by distribution of space in the container.

In flexbox, items in a row wrap container must wrap to new rows. This means that div #3 cannot wrap beneath div #2. It must wrap beneath div #1.

Here's how items wrap in a flex container with row wrap:

enter image description here

If div #3 were to wrap under div #2, that wouldn't be a row, that would be a grid, and flex items are confined to a straight, unbending row.

As a result, white space created by items that aren't the tallest in the row is preserved in each column, creating an unsightly gap (see divs 2 & 3 below).

enter image description here

For your desired layout to work in row wrap, flex items would have to exit their row in order to close the gap – maybe with absolute positioning – which flexbox cannot do.

In this case, you can make the layout work with flexbox by using column wrap instead of row wrap.

You will need to define a height for the container, so the items know where to wrap.

/*************** MOBILE *************/

.container {
  display: flex;
  flex-direction: column;
  height: 200px;
}
div.orange {
  background-color: orange;
}
div.blue {
  order: -1;
  background-color: aqua;
}
div.green {
  background-color: lightgreen;
}
.container > div {
  width: 100%;
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}
/***************************/

@media screen and (min-width: 800px) {
  .container {
    flex-wrap: wrap;
  }
  div.orange {
    flex-basis: 100%;
    width: 50%;
  }
  div.blue {
    flex-basis: 50%;
    width: 50%;
    order: 0;
  }
  div.green {
    flex-basis: 50%;
    width: 50%;
  }
}
<div class="container">
  <div class="orange">1</div>
  <div class="blue">2</div>
  <div class="green">3</div>
</div>

jsFiddle

Here are two other options: (The second option is mostly FYI, as most browsers haven't completed implementation.)

  • Desandro Masonry

    Masonry is a JavaScript grid layout library. It works by placing elements in optimal position based on available vertical space, sort of like a mason fitting stones in a wall. You’ve probably seen it in use all over the Internet.

    source: http://masonry.desandro.com/

  • CSS Grid Layout Module Level 1

    This CSS module defines a two-dimensional grid-based layout system, optimized for user interface design. In the grid layout model, the children of a grid container can be positioned into arbitrary slots in a predefined flexible or fixed-size layout grid.

    source: https://drafts.csswg.org/css-grid/