26

My page is split into 3 slices, as shown in this JFiddle.

In my full source code, I have media queries to help manage sizing between mobile and desktop. When someone accesses the site on mobile mode, Logo should appear at the top, and Items should appear below it. (I set display: none on my picture div to hide it)

Problem:

I can't change the positioning of the divs in HTML, or it'll disturb my current 3 slice layout. Absolute positioning is not an option, since most of my site is already dynamically sized, and I wouldn't want absolute positioning to interfere on a resolution I haven't tested on. This means calculating the margin sizes would be out of the question aswell.

So, absolute positioning is not allowed, nor is changing the orders of the divs. The result I'm looking for would be similar to this, exception without repositioning the divs.

My question is not about media queries, or how to size for mobile using media queries. I am only asking about how to get the layout I want with the restrictions in place (no absolute positing, no calculating margins, no changing div order).

Other questions I looked at:

Reposition div above preceding element - First answer suggests repositioning divs, which I cannot do. Second answer relies on calculating the position, which could interfere with other dynamically sizing elements.

Move The First Div Appear Under the Second One in CSS - Suggests I use absolute positioning, which I cannot do

Community
  • 1
  • 1
Vince
  • 14,470
  • 7
  • 39
  • 84
  • Are there any more styles to that which influence the three column layout? changing the order of the HTML does not disturb that for me with the fiddle you've given. http://jsfiddle.net/u5r2bmj5/ – Laura Dec 09 '14 at 07:49
  • It's hard to say without seeing your media query CSS, but I'm inclined to say that you will need to remove the floats. – EternalHour Dec 09 '14 at 07:51
  • Are you trying to do something like this? [Fiddle](http://jsfiddle.net/venkateshwar/Lqo7qher/6/) (_resize to check_) – Mr_Green Dec 09 '14 at 08:03
  • How about using [flex](https://developer.mozilla.org/en-US/docs/Web/CSS/flex) that has [order property](https://developer.mozilla.org/en-US/docs/Web/CSS/order)? [Example](http://jsfiddle.net/vucko/p7tbsykh/) – Vucko Dec 09 '14 at 08:04
  • @Vucko unfortunately it's not very well supported on mobiles (see [flex - Browser Compatibility](https://developer.mozilla.org/en-US/docs/Web/CSS/flex#AutoCompatibilityTable) - switch to Mobile tab) – benomatis Dec 09 '14 at 08:25
  • 1
    @webeno I would disagree - [caniuse](http://caniuse.com/#feat=flexbox) – Vucko Dec 09 '14 at 08:26
  • @Vucko You would disagree with what? the official documentation (that you linked yourself...)? – benomatis Dec 09 '14 at 08:31
  • 1
    @webeno I would disagree that it's "not very well supported on mobiles". As you can see from the [caniuse](http://caniuse.com/#feat=flexbox) link, only opera mini doesn't support the flexible box layout module. – Vucko Dec 09 '14 at 08:36
  • @Vucko hm... strange, I guess Mozilla hasn't updated their doc then for a while... – benomatis Dec 09 '14 at 08:44

3 Answers3

49

Flexbox layout is your friend here. display: flex can be used to interchange the elements position on the layout.

#container { display:flex; flex-direction: column; text-align:center;}
#items { order: 2 }
#logo { order: 1 }
#picture { display: none; }
<div id="container">
    <div id="items">Items</div>
    <div id="logo">Logo</div>
    <div id="picture">Picture</div>
</div>

display: flex works only in modern browsers. Check caniuse.

A test on my android mobile shows it working on Firefox and Chrome, but not on the stock Android browser.

Mr_Green
  • 40,727
  • 45
  • 159
  • 271
Alohci
  • 78,296
  • 16
  • 112
  • 156
  • Sorry, I didn't get this. why can't we just use `display: block` here without using `flex`? – Mr_Green Dec 09 '14 at 08:10
  • @Mr_Green - Because `display:block` doesn't allow simple reordering of elements. – Alohci Dec 09 '14 at 08:13
  • There is only one problem: its apparent lack of support on mobile (https://developer.mozilla.org/en-US/docs/Web/CSS/flex#AutoCompatibilityTable - click the Mobile tab) – benomatis Dec 09 '14 at 08:31
  • @Alohci please explain in your answer about the interchange of the order and compatibiltiy. TBH, your solution seems unreasonable at first glance. – Mr_Green Dec 09 '14 at 08:40
2

I tried to solve the solution using transform: translateY property in percentage value.

Note: This works if and only if the two containers have same height. or if the height is already known, then you can set the transform: translateY value according to the height.

CSS

@media (max-width: 700px) {
    #container > div {
        width: auto;
        display: block;
        float: none;
    }
    #container #picture {
        display: none;
    }
    #logo {
        transform: translateY(-100%);
    }
    #items {
        transform: translateY(100%);
    }
}

Working Fiddle

Mr_Green
  • 40,727
  • 45
  • 159
  • 271
0

Probably the easiest is if you play with minus margins. Note that the below sizes (width and side margins) may need to be adjusted to your specific needs.

#container * {
    width: 95vw;
    text-align: center;
}

#items {
    width: 50%; /* #picture is hidden so we split the screen into 2 */
    float: left;
    margin-top:30px; /* has to be smaller than the absolute of #logo */
    margin-left:25%; /* half of the element's width */
}

#logo {
    width: 50%; /* #picture is hidden so we split the screen into 2 */
    float: right;
    margin-top:-40px; /* its absolute has to be greater than the one of #items */
    margin-right:25%; /* half of the element's width */
}

#picture {
    width: 33%;
    float: right;
    display:none; /* Hiding #picture as you said you would */
}
<div id="container">
    <div id="items">Items</div>
    <div id="logo">Logo</div>
    <div id="picture">Picture</div>
</div>
benomatis
  • 5,536
  • 7
  • 36
  • 59