Question: Desktop and mobile flexbox layouts without nested containers

Question

Desktop and mobile flexbox layouts without nested containers

Answers 3
Added at 2017-01-04 03:01
Tags
Question

I have 3 divs that must be in a certain order for the mobile layout, but I have to break out the 2nd div as a sidebar for the desktop layout. So for mobile:

=====
| div1 |
=====
| div2 |
=====
| div3 |
=====

And for desktop:

===== =====
| div1 | |         |
===== | div2 |
| div3 | |         |
===== =====

In the desktop layout, div 2 has a shaded background, so must be the full height of the parent. I can float div1 and div3 left and div2 right and achieve what I want, but then I need to use javascript to get div2 to fill the height of the parent. I'd like to use flexbox, but just can't figure out how to achieve the desktop effect without nesting div1 and div3, which breaks the mobile layout. Any thoughts?

Answers to

Desktop and mobile flexbox layouts without nested containers

nr: #1 dodano: 2017-01-04 03:01

Here's one way to do it with absolute positioning. Preview this snippet and you'll see your two layouts side by side.

To make it easy to see, I'm just using a .desktop class with the same HTML, but you could easily incorporate a media query instead to switch to that layout on mobile.

.wrapper {
  border: 1px dotted #333;
  position: relative;
  margin: 10px;
  width: 100px;
  float: left;
}

.wrapper div {
  height: 100px;
  width: 100px;
}

.div-1 { background: lightblue; }
.div-2 { background: turquoise; }
.div-3 { background: teal; }

/* alternate layout via class, or use media query: */
.wrapper.desktop {
  width: 300px;
}

.wrapper.desktop .div-2 {
  position: absolute;
  width: auto;
  height: auto;
  top: 0;
  bottom: 0;
  right: 0;
  left: 100px;
}
<div class="wrapper">
  <div class="div-1">Div 1</div>
  <div class="div-2">Div 2</div>
  <div class="div-3">Div 3</div>
</div>

<div class="wrapper desktop">
  <div class="div-1">Div 1</div>
  <div class="div-2">Div 2</div>
  <div class="div-3">Div 3</div>
</div>

nr: #2 dodano: 2017-01-04 19:01

Based on how you want nr2 to look like when in desktop layout, here is another option, using a pseudo element to create the illusion of them all fill their parent.

The great doing like this is no fixed height is needed and both columns will fill its parent no matter which is bigger

Sample 1

.parent {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.child {
  position: relative;
  padding: 10px;
  border: 2px solid white;
  box-sizing: border-box;
}
.nr1 {
  background-color: lightblue;
  order: -1;
}
.nr2 {
  background-color: lightgreen;
}
.nr3 {
  background-color: lightgray;
}
@media (max-width: 800px) {
  .parent {
    display: block;
  }
  .nr1, .nr3 {
    float:left;
    width: 50.1%;
  }
  .nr2 {
    float:right;
    width: 49.9%;
  }
  .nr3::after,
  .nr2::after {
    content: '';
    position: absolute;
    background-color: inherit;
    left: 0;
    top: 100%;
    width: 100%;
    height: 100vh;
  }
}
<div class="parent">
  <div class="child nr2"> 2 </div>
  <div class="child nr1"> 1 <br> 1 <br> 1 <br> 1 <br> 1 <br> 1 <br> </div>
  <div class="child nr3"> 3 </div>
</div>

Sample 2

.parent {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.child {
  position: relative;
  padding: 10px;
  border: 2px solid white;
  box-sizing: border-box;
}
.nr1 {
  background-color: lightblue;
  order: -1;
}
.nr2 {
  background-color: lightgreen;
}
.nr3 {
  background-color: lightgray;
}
@media (max-width: 800px) {
  .parent {
    display: block;
  }
  .nr1, .nr3 {
    float:left;
    width: 50.1%;
  }
  .nr2 {
    float:right;
    width: 49.9%;
  }
  .nr3::after,
  .nr2::after {
    content: '';
    position: absolute;
    background-color: inherit;
    left: 0;
    top: 100%;
    width: 100%;
    height: 100vh;
  }
}
<div class="parent">
  <div class="child nr2"> 2 <br> 2 <br> 2 <br> 2 <br> 2 <br> 2 <br> </div>
  <div class="child nr1"> 1 </div>
  <div class="child nr3"> 3 </div>
</div>

Sample 3

.parent {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.child {
  position: relative;
  padding: 10px;
  border: 2px solid white;
  box-sizing: border-box;
}
.nr1 {
  background-color: lightblue;
  order: -1;
}
.nr2 {
  background-color: lightgreen;
}
.nr3 {
  background-color: lightgray;
}
@media (max-width: 800px) {
  .parent {
    display: block;
  }
  .nr1, .nr3 {
    float:left;
    width: 50.1%;
  }
  .nr2 {
    float:right;
    width: 49.9%;
  }
  .nr3::after,
  .nr2::after {
    content: '';
    position: absolute;
    background-color: inherit;
    left: 0;
    top: 100%;
    width: 100%;
    height: 100vh;
  }
}
<div class="parent">
  <div class="child nr2"> 2 </div>
  <div class="child nr1"> 1 </div>
  <div class="child nr3"> 3 <br> 3 <br> 3 <br> 3 <br> 3 <br> 3 <br> </div>
</div>


This one uses a pseudo on the parent, to make nr2 look good having a gradient background

.parent {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.child {
  position: relative;
  padding: 10px;
  border: 2px solid white;
  box-sizing: border-box;
}
.nr1 {
  background-color: lightblue;
  order: -1;
}
.nr2 {
  background-color: lightgreen;
}
.nr3 {
  background-color: lightgray;
}
@media (max-width: 800px) {
  .parent {
    display: block;
  }
  .parent::before {
    content: '';
    position: absolute;
    background: linear-gradient(lightgreen, green);
    left: 50.1%;
    top: 2px;
    width: 49.9%;
    height: 100%;
  }
  
  .nr1, .nr3 {
    float:left;
    width: 50.1%;
  }
  .nr2 {
    float:right;
    width: 49.9%;
    border: none;
    background-color: transparent;
  }
  .nr3::after {
    content: '';
    position: absolute;
    background-color: inherit;
    left: 0;
    top: 100%;
    width: 100%;
    height: 100vh;
  }
}
<div class="parent">
  <div class="child nr2"> 2 <br> 2 <br> 2 <br> 2 <br> 2 <br> 2 <br> </div>
  <div class="child nr1"> 1 <br> 1 <br> 1 <br> </div>
  <div class="child nr3"> 3 <br> 3 <br> 3 <br> 3 <br> 3 <br> 3 <br> </div>
</div>

nr: #3 dodano: 2017-01-06 04:01

I actually thought of a simple solution that does exactly what I want. The tough thing about this is that the page displays a profile for a member of my client. There are almost 500 members and I have no control over the content that they put into their profile. So, no idea of the height of any of the divs and it varies all over the place. The issue with absolute positioning div2 is that if it has longer content than 1 & 3 combined, you lost the bottom of the div under the footer. I can't really use any fixed heights since the amount of content changes from member to member.

My fix was to add a 4th div that did nothing but provide the shaded background for the div2 sidebar. So, in desktop mode, div1 & div2 floated left, with div2 floated right, and div4 (with the shading) set to absolute with top and bottom set to 0 and a lower z-index than div2. In mobile mode, I hide div4 and set the widths of the others to 100% and it all just works.

Source Show
◀ Wstecz