2

I have three colored HTML div tags displayed inline-block like this:

enter image description here

Using only CSS, I want to respond with a media query such that the blue div actually rises over the red and green. The desired outcome will look like this:

enter image description here

I have composed the following HTML. As expected, my output is such that the blue div floats below the green and red. How can I stack blue on top by modifying my CSS in the above HTML?

<html>
<head>
  <style>
    div { height: 10%; }
    #red { width: 300px; background-color: red; display: inline-block; }
    #green { width: 300px; background-color: green; display: inline-block; }
    #blue { width: 300px; background-color: blue; display: inline-block; }
    @media screen and (max-width: 940px) {
      #red { width: 49%; }
      #green { width: 49%; }
      #blue { width: 100%; float: left; }
    }
  </style>
</head>
<body>
  <div id="container">
    <div id="red"></div>
    <div id="green"></div>
    <div id="blue"></div>
  </div>
</body>
</html>

EDIT: The height of the divs is dynamic, so modifying margins to force blue on top isn't really the solution I want.

EDIT: According to MDN, flex box is not supported in Safari. So flex box is not an option.

ThisClark
  • 14,352
  • 10
  • 69
  • 100
  • What sort of browser support do you need? Does your html order need to be the way it is in your code (red,green,blue)? – Jesse Kernaghan Jan 08 '15 at 21:10
  • What do you want to target with your media query? Is your question how to write a media query or how to make this change in CSS? – TylerH Jan 08 '15 at 21:11
  • @JesseKernaghan Order is the key part of the problem, so it does matter. Browser support is less important - is it possible to accomplish this without flex box? – ThisClark Jan 08 '15 at 21:12
  • @TylerH The media query is already written in the head of my HTML. I want the 3rd div over the 1st two as a result of the breakpoint I set at 940px. – ThisClark Jan 08 '15 at 21:14
  • @ThisClark if the blue div was 1st in the order it could be done without flexbox. As the current structure stands I believe you'd be relying on flexbox order as described here: https://developer.mozilla.org/en-US/docs/Web/CSS/order – Jesse Kernaghan Jan 08 '15 at 21:14
  • 1
    Height of those divs is dynamic based on their content, right? – Marcin Krawiec Jan 08 '15 at 21:17
  • Ok, so another question - can I wrap #red and #green in an additional div? – Marcin Krawiec Jan 08 '15 at 21:23
  • @MarcinKrawiec Yes, I think this is agreeable. – ThisClark Jan 08 '15 at 21:24
  • The flexbox is supported in Safari: http://caniuse.com/#feat=flexbox – Marcin Krawiec Jan 08 '15 at 21:37

4 Answers4

3

div { height: 50px; }
#red, #green, #blue{width: 300px;display: inline-block;} 

#red, #green{width: 49%}
#red { background-color: red;}
#green { background-color: green;}
#blue { 
    background-color: blue; 
    width: 100%;
}

@media screen and (max-width: 940px) {
    #blue { float: right}
    #red, #green,#blue{width: 32.9%;}
}
<div id="container">
    <div id="blue"></div>
    <div id="red"></div>
    <div id="green"></div>
</div>

Update:

div { height: 50px; }
#red, #green, #blue{width: 300px;display: inline-block;} 

#red, #green,#blue{width: 32.9%;}

#red { background-color: red;}
#green { background-color: green;}
#blue { 
    background-color: blue; 
    float: right
}

@media screen and (max-width: 940px) {
    #blue { width: 100%}
    #red, #green{width: 49%; margin-top: 4px}
}
<div id="container">
    <div id="blue"></div>
    <div id="red"></div>
    <div id="green"></div>
</div>
Gildas.Tambo
  • 22,173
  • 7
  • 50
  • 78
  • The results are opposite of what I want to achieve. The blue bar starts on top and the page responds at 940px to set 3 inline divs. I want to collapse to blue on top at 940px. – ThisClark Jan 08 '15 at 21:37
3

If you can slightly modify your html source (but of course the order of your divs is not changed) then it is doable:

div { height: 50px; }

.helper { width: 600px; display: inline-block;}

#red { width: 300px; background-color: red; display: inline-block; }
#green { width: 300px; background-color: green; display: inline-block; }
#blue { width: 300px; background-color: blue; display: inline-block; }

@media screen and (max-width: 940px) {

    #container   { display: table; width: 100% }
    .helper  { display: table-footer-group; }
    #blue { display: table-header-group; width: 100%; }
    
    
    #blue { 
        height: 25px;  
        /* proof that it can be different than the height of other divs */
    }
    #red { width: 50%; }
    #green { width: 50%; }
}
  <div id="container"><!-- 
       stripping whitespace
    --><div class="helper"><!--
        --><div id="red">test</div><!--
        --><div id="green">test</div><!--
    --></div><!--
    --><div id="blue">test</div><!--
  --></div>
Marcin Krawiec
  • 703
  • 3
  • 8
  • 1
    This looks good and is likely the answer I will choose. I think I found the source you are looking at - [Vertical reordering of blocks with CSS](http://tanalin.com/en/articles/css-block-order/) and [Use CSS to reorder DIVs](http://stackoverflow.com/questions/220273/use-css-to-reorder-divs) – ThisClark Jan 08 '15 at 21:52
  • It's also here: http://stackoverflow.com/questions/7425665/switching-the-order-of-block-elements-with-css ...and there: http://www.jtudsbury.com/thoughts/rearrange-div-order.php :) – Marcin Krawiec Jan 08 '15 at 21:54
1

I guess this could work ... but only if you know the height of the element :) :

* {
    padding: 0;
    margin: 0;
}

div {
    height: 50px;
}

#red {
    width: 300px;
    background-color: red;
    display: inline-block;
}

#green {
    width: 300px;
    background-color: green;
    display: inline-block;
}

#blue {
    width: 300px;
    background-color: blue;
    display: inline-block;
}

@media screen and (max-width: 940px) {
    #red {
        margin-top: 50px;
        width: 49%;
    }

    #green {
        margin-top: 50px;
        width: 49%;
    }

    #blue {
        width: 100%;
        position: absolute;
        top: 0;
        left: 0;
    }
}

Fiddle : http://jsfiddle.net/nj8sfnhb/1/

sodawillow
  • 12,497
  • 4
  • 34
  • 44
  • 1
    Don't forget a `position:relative` on the parent `div` or the red, blue, and green boxes may end up in an unexpected place – Alvaro Montoro Jan 08 '15 at 21:16
  • Thanks for your efforts and success in moving blue on top, however I'd like to get this done for a dynamic div height. I modified the source accordingly. – ThisClark Jan 08 '15 at 21:20
1

It is easier to reverse the order of your inline blocks for the normal state (by using float right), than what you ask to happen after the media query has enabled. Obviously this is only a solution if you are able to reverse the order of your coloured regions (i.e. their cascading order has no significance to the page like for SEO or for accessibility reasons), and the float rights don't end up causing you issues elsewhere on your page.

NOTE: The float left on the #container is used to force the regions not to jump to the right side of the page, but there are other ways of achieving this depending on the context of the rest of the page.

html, body { height: 100%; }
#container { height: 100%; float:left; }
#container > div { height: 10%; }

#red { width: 300px; background-color: red; display: inline-block; float: right; }
#green { width: 300px; background-color: green; display: inline-block; float: right; }
#blue { width: 300px; background-color: blue; display: inline-block; float: right; }

@media screen and (max-width: 940px) {
  #container { float: none; }
  #red { width: 50%; display: block; }
  #green { width: 50%; display: block; }
  #blue { width: 100%; display: block; clear: both; float: left; }
}
<div id="container">
  <div id="blue"></div>
  <div id="green"></div>
  <div id="red"></div>
</div>
Pebbl
  • 34,937
  • 6
  • 62
  • 64