0

I have a two-column layout consisting of a sidebar on the left and a map on the right. The sidebar has two boxes; one for a search input and one for a list of the results. So on desktop it looks like this:

+--------------+---------------------+
| search input |                     |
+--------------+           map       |
|  results     |                     |
|   ...        |                     |
+--------------+---------------------+

On mobile, I want everything to be displayed in a single column, but with the map between the search input and the results, so it's more of a structural change than a simple flex-direction/ordering change:

+------------------------------------+
|          search input              |
+------------------------------------+
|                                    |
|               map                  |
|                                    |
+------------------------------------+
|           results                  |
|             ...                    |
+------------------------------------+

Is this possible?

Gus Hogg-Blake
  • 2,393
  • 2
  • 21
  • 31
  • possible duplicate: http://stackoverflow.com/q/39644585/3597276 – Michael Benjamin Jan 14 '17 at 19:35
  • Using pure CSS...not until `display:contents` is more widely supported. ATM it's just Firefox i believe. – Paulie_D Jan 14 '17 at 19:53
  • If you can't set a fixed height on the container, this answer might be an option?: [desktop-and-mobile-flexbox-layouts-without-nested-containers](http://stackoverflow.com/questions/41455280/desktop-and-mobile-flexbox-layouts-without-nested-containers) – Asons Jan 14 '17 at 20:02
  • If the search input, map, and results containers are siblings, you can simply reorder them using the `order` property in the flexbox layout model. – Terry Jan 14 '17 at 21:15

1 Answers1

3

The condition for reordering without JavaScript is that all items are siblings:

<div class="wrap">
  <div            > 1. sidebar </div>
  <div class="map"> 2. map </div>
  <div            > 3. also sidebar </div>
  <div            > 4. still sidebar </div>
</div>

Before flexbox, this was achieved using floats:

body {margin: 0; padding: 0;}
.wrap {
  overflow: hidden;
  padding: 1rem;
  background-color: #999;
  min-height: 100vh;
  box-sizing: border-box;
}
.wrap > * {
  width: 25%;
  float: left;
  background-color: #eee;
  background-clip: content-box;  
  box-sizing: border-box;
  padding: 1rem;
  min-height: 6rem;
}
.map {
  float: right;
  width: 75%;
  min-height: calc(100vh - 2rem);
}
@media (max-width: 800px) {
  .map {
    min-height: 50vh;
  }
  .wrap > *{
    float: none;
    width: 100%;
  }
}
<div class="wrap">
  <div>1. sidebar</div>
  <div class="map">2. map</div>
  <div>3. also sidebar</div>
  <div>4. still sidebar</div>
</div>

Now you can do it with flexbox, using order:

body {margin: 0; padding: 0;}
.wrap {
  height: 100vh;
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  padding: 1rem;
  background-color: #999;
  box-sizing: border-box;
}
.wrap > * {
  width: 25%;
  float: left;
  background-color: #eee;
  background-clip: content-box;
  box-sizing: border-box;
  padding: 1rem;
  min-height: 6rem;
}
.map {
  order: 999;
  width: 75%;
  min-height: 100%;
}
@media (max-width: 800px) {
  .wrap {
     flex-wrap: nowrap;
     height: auto;
     min-height: 100vh;
   }
  .wrap > * {
    width: 100%;
  }
  .map{
    order: unset;
    width: 100%;
    min-height: 50vh;
  }
}

@media (max-height: 480px) {
  .wrap {
    height: 480px;
  }
}
<div class="wrap">
  <div>1. sidebar</div>
  <div class="map">2. map</div>
  <div>3. also sidebar</div>
  <div>4. still sidebar</div>
</div>
tao
  • 82,996
  • 16
  • 114
  • 150