How to change side by side divs to stack on mobile? - html

I am trying to get my 2 divs (which are side by side) to change to stacked divs when viewed on mobile as shown in the fiddle, but I would like "two to be on top and "one" to be second.
Here is the code - http://jsfiddle.net/d3d4hb3t/
.one {
border: 1px solid green;
width: 29%;
float: left;
height: 100px;
}
.two {
border: 1px solid blue;
width: 69%;
float: right;
height: 100px;
}
#media (max-width: 767px) {
.one {
width: 100%;
}
.two {
width: 100%;
}
}
<div class="one">one</div>
<div class="two">two</div>
I know the simple solution would be to swap divs one and two around, but since the code I have is complicated, I was hoping there was an easier solution using just CSS.

Update
Added a flexbox approach below:
UPATED JSFIDDLE
.wrap {
display: flex;
}
.one {
width: 30%;
border: 1px solid green;
}
.two {
width: 70%;
border: 1px solid blue;
}
#media (max-width: 767px) {
.wrap {
flex-direction: column-reverse;
}
.one,
.two {
width: auto;
}
}
<div class="wrap">
<div class="one">1</div>
<div class="two">2</div>
</div>
Original answer
If you're stuck with the markup, you can still use the magic css table layout to change the order of the 2 divs. I updated it all, just to keep the consistency.
How those display values work, from MDN:
display: table; - behaves like <table> element.
display: table-cell; - behaves like <td> element.
display: table-header-group; - behaves like <thead> element.
display: table-footer-group; - behaves like <tfoot> element.
UPDATED JSFIDDLE
.wrap {
display: table;
border-collapse: collapse;
width: 100%;
}
.one,
.two {
display: table-cell;
}
.one {
width: 30%;
border: 1px solid green;
}
.two {
width: 70%;
border: 1px solid blue;
}
#media (max-width: 767px) {
.one {
display: table-footer-group;
width: 100%;
}
.two {
display: table-header-group;
width: 100%;
}
}
<div class="wrap">
<div class="one">1</div>
<div class="two">2</div>
</div>

Considering that you don't want swap them.
Here is the fiddle: https://jsfiddle.net/c8x49afg/
Just use position relative for divs pulling the second up and pushing the first down.
.one {
border: 1px solid green;
width: 29%;
float: left;
height: 100px;
}
.two {
border: 1px solid blue;
width: 69%;
float: right;
height: 100px;
}
#media (max-width:767px) {
.one {
position: relative;
top: 110px;
width: 100%;
}
.two {
position: relative;
top: -100px;
width: 100%;
}
}
<div class="wrapper">
<div class="one">
one
</div>
<div class="two">
two
</div>
</div>

I have needed to do this exact thing when working in an enterprise CMS where the source order could not be changed on mobile.
The solution I have used is to set a general container for the two Divs and make that display as a table. You can then set the Div you want to show first as display:table-group-header and set the one to show after it as display:table-group-footer
If you want to keep the colored borders, you may have to introduce an inner div for each that holds your content.
I have created a Fiddle that shows it in action:
http://jsfiddle.net/0brc4xc7/

Related

Inline block increase spacing between elements and keep the alignment

I have a problem to increase the space between elements within an inline block container. I found a trick to do that but it works only for the first line...
By the way, I have n number of elements and a specific container width.
The code:
<!DOCTYPE html>
<html>
<head>
<style>
.container {
background-color: blue;
height: 300px;
width: 620px;
display: inline-block;
}
.container div + div {
margin-left: 33px;
}
.child1 {
width:200px;
height: 100px;
display:inline-block;
background-color: red;
}
.child2 {
width: 200px;
height: 100px;
display: inline-block;
background-color: green;
}
.child3 {
width: 200px;
height: 100px;
display: inline-block;
background-color: yellow;
}
</style>
</head>
<body>
<div class="container">
<div class="child1"></div>
<div class="child2"></div>
<div class="child3"></div>
</div>
</body>
</html>
The Result:
(Note: It has to support all browsers, +IE7)
Thank you very much!
Use the nth-child selector to select every three child!
https://jsfiddle.net/25x4ga0g/1/
.container div:nth-child(2n + 1) {
margin-left: 0px;
}
More about nth-child selector
Use margin-right instead of margin-left.
.container div {
margin-right: 33px;
}
.container {
background-color: blue;
height: 300px;
width: 620px;
display: inline-block;
}
.container div {
margin-right: 33px;
}
.child1 {
width: 200px;
height: 100px;
display: inline-block;
background-color: red;
}
.child2 {
width: 200px;
height: 100px;
display: inline-block;
background-color: green;
}
.child3 {
width: 200px;
height: 100px;
display: inline-block;
background-color: yellow;
}
<div class="container">
<div class="child1"></div>
<div class="child2"></div>
<div class="child3"></div>
</div>
Did you try this ?
div+div:last-of-type{
margin:0px;
}
Insert this snippet in the style part and it should be ok. It will work for the last div only .
To do this you can use something fantastic called Flexbox.
First, set the container to display: flex. Then use flex-wrap: wrap so if you add more elements, they will appear on a new row below. Also make sure to use align-content: flex-start so the elements will start from the left.
Finally add a margin-left and margin-bottom to all your child-divs so they will have space between them. Because we are use Flexbox, your problem with the margin will now be eliminated.
If you want the divs to fit perfectly in the container instead, just remove the margins of the child-divs and set the parent to justify-content: space-between.
CSS Code:
.container {
display: flex;
flex-wrap: wrap;
align-content: flex-start;
width: 620px;
height: 300px;
background-color: blue;
}
.container div {
margin-right: 33px;
margin-bottom: 5px;
}
.child1 {
width: 200px;
height: 100px;
display:inline-block;
background-color: red;
}
.child2 {
width: 200px;
height: 100px;
display: inline-block;
background-color: green;
}
.child3 {
width: 200px;
height: 100px;
display: inline-block;
background-color: yellow;
}
Working Fiddle
Read more about Flexbox
An alternate solution if you don't want to use Flexbox, you could just select every third children and then set the margin-left to 0:
.container div:nth-child(3n) {
margin-left: 0;
}
Hope that helped

Re-sizing and re-ordering elements between desktop and mobile layouts

I'd like to achieve the following with CSS only (left is mobile layout, right is desktop after breakpoint):
The challenge here obviously is that from a float point of view the element order changes: on mobile the green item is the second, but on desktop it's the first.
Is this possible to achieve with pure CSS? Possibility would be flex-box but I don't have enough experience to recreate this layout.
#container {
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 400px; /* 1 */
}
.box {
width: 50%;
}
.box1 {
background-color: lightgreen;
height: 400px;
}
.box2 {
background-color: orangered;
height: 200px;
}
.box3 {
background-color: aqua;
height: 200px;
}
#media (max-width: 600px) {
#container { height: auto; } /* 2 */
.box { width: 100%; }
.box2 { order: -1; } /* 3 */
}
/* purely decorative styles */
.box {
border: 1px solid #ccc;
display: flex;
justify-content: center;
align-items: center;
font-size: 1.5em;
}
* { box-sizing: border-box; }
<div id="container">
<div class="box box1"><span>1</span></div>
<div class="box box2"><span>2</span></div>
<div class="box box3"><span>3</span></div>
</div>
jsFiddle
Notes:
Without a fixed height in a column wrap container, flex items don't know where to wrap. So, for your larger screen, define a height which forces the second item to a new column.
Now you're in a mobile layout and wrapping is no longer necessary. The container needs to be twice the height of the desktop layout. Release the height.
Tell the red box to re-position itself first on the list. (The initial order value for flex items is 0.)
Yes you can do this if you can set fixed height on flex-container. You just need to use flex-direction: column and flex-wrap: wrap and then change order with media-queries.
.content {
display: flex;
flex-wrap: wrap;
flex-direction: column;
}
.a {
height: 200px;
background: #00FF02;
}
.b {
height: 100px;
background: red;
}
.c {
height: 100px;
background: blue;
}
#media(min-width:768px) {
.content {
height: 200px;
}
.content > div {
width: 50%;
}
}
#media(max-width:768px) {
.b {
order: -1;
}
}
<div class="content">
<div class="a">A</div>
<div class="b">B</div>
<div class="c">C</div>
</div>
There is also no-flex solution, fiddle (just replace media-query min-width with whatever breakpoint you consider phone width ends):
HTML:
<div class="div1"></div>
<div class="div2"></div>
<div class="div3"></div>
CSS:
div {
width: 50%;
}
.div1 {
background-color: red;
float: right;
height: 200px;
}
.div2 {
background-color: green;
float: left;
height: 400px;
}
.div3 {
background-color: blue;
float: right;
height: 200px;
}
#media (max-width: 500px) {
.div1, .div2, .div3 { width: 100%;}
}

Moving a flex item from inside a column of items to its own column

If I have a flex container with three children with flex-direction: column, and I want to move the middle child to the right while keeping the first and third child to the left, how would I do that?
Is flexbox even the correct approach or is something else more appropriate?
This is my attempt:
.container {
display: flex;
flex-flow: row wrap;
#media (max-width: 840px) {
flex-flow: column wrap;
}
}
.red,
.green,
.blue {
width: 50%;
#media (max-width: 840px) {
width: 100%;
}
}
.red {
background-color: red;
height: 100px;
}
.green {
background-color: green;
height: 300px;
}
.blue {
background-color: blue;
height: 100px;
}
<div class="container">
<div class="red"></div>
<div class="green"></div>
<div class="blue"></div>
</div>
http://codepen.io/dye/pen/mOeZma
It's close, but not quite there. When green div moves to the right, there's a big gap between red and blue.
Any advice would be appreciated. Thank you!
Let me start by saying I like flexbox. It can take some time to get your head around all the little things it can do.
If I understood the question I think this does what you want (you'll need to press the full-screen button to see it in all it's glory, as I included the less that 840px stuff).
body {
margin: 0
}
.container {
display: flex;
flex-wrap: wrap;
flex-direction: column;
height: 400px
}
.blue,
.green,
.red {
width: 50vw
}
.red {
height: 100px;
background: red
}
.green {
height: 200px;
order: 1;
background: green
}
.blue {
background: #00f;
height: 300px
}
#media (max-width: 840px) {
.container {
height: auto
}
.blue,
.green,
.red {
width: 100vw
}
.green {
order: 0
}
}
<div class="container">
<div class="red"></div>
<div class="green"></div>
<div class="blue"></div>
</div>
I've manually set the height of the container to trigger the wrapping, and I've giving green a positive order so it's at the bottom of the list. Though when it's small and all in one column I've taken the order away so it is in the middle again.
I hope this helps, and never give up on flexbox ;-)
The answer is no. Flexbox doesn't have the flexibility that you want especially when you are building a dynamic.
If this is static
.container {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-flow: row wrap;
-ms-flex-flow: row wrap;
flex-flow: row wrap;
}
.holder {
width: 50%;
}
.holder .red, .holder .blue {
width: 100%;
}
.red,
.green,
.blue {
width: 50%;
}
.red {
background-color: red;
height: 100px;
}
.green {
background-color: green;
height: 300px;
}
.blue {
background-color: blue;
height: 100px;
}
<div class="container">
<div class="holder">
<div class="red"></div>
<div class="blue"></div>
</div>
<div class="green"></div>
</div>
So, the answer might be in javascript.
I prefer to just use masonry.
http://masonry.desandro.com/
Instructions are straight-forward. It is easy to setup.
.green{
float: right;
}
.red,
.green,
.blue {
width: 50%;
display: inline-block;
}
.red {
background-color: red;
height: 100px;
}
.green {
background-color: green;
height: 300px;
}
.blue {
background-color: blue;
height: 100px;
}
<body>
<div class="container">
<div class="red"></div>
<div class="green"></div>
<div class="blue"></div>
</div>
</body>
Ive removed the flex box and float it instead. much simpler i think
Add order property to .green class.
.green {
background-color: green;
height: 300px;
order: 1;
}
and you can order all the elements as well.
.red {
background-color: red;
height: 100px;
order: 1;
}
.green {
background-color: green;
height: 300px;
order: 3;
}
.blue {
background-color: blue;
height: 100px;
order: 2;
}
Maybe you just should turn on flex for container only for max width: 840px? For higher resolutions you can make container display block and float first and third div to left and second to right, that's all.
.container {
#media (max-width: 840px) {
display: flex;
flex-flow: column wrap;
}
}
.red,
.green,
.blue {
width: 50%;
#media (max-width: 840px) {
width: 100%;
}
}
.red {
background-color: red;
height: 100px;
#media (min-width: 841px) {
float: left;
}
}
.green {
background-color: green;
height: 300px;
#media (min-width: 841px) {
float: right;
}
}
.blue {
background-color: blue;
height: 100px;
#media (min-width: 841px) {
float: left;
}
}
http://codepen.io/anon/pen/QGjegM
Neither of these directly answer your question but may be of use to those in the future who find their way here with similar questions..
1. On the possibility that you are wanting to keep the two left blocks the same height as the right (green) here is how you could do that (i added two wrappers, additional code)
note: the jquery is just for demonstration purposes
// the jquery is just to adjust height for vertical flex demonstration
$('adjustorator').click(function() {var heights = Array(100, 150, 200, 250, 300, 350, 450, 500);var height = heights[Math.floor(Math.random()*heights.length)]; $('.green').css('height', height)});
.container {
display: flex;
width: 100%;
}
.left, .right {
display: flex;
flex-wrap: wrap;
width: 50%;
}
.red, .blue, .green {
width: 100%;
}
.red {
background-color: red;
}
.blue {
background-color: blue;
}
.green {
background-color: green;
height: 400px;
}
// scaffolding below, ignore
body { position: relative; }
adjustorator { display: flex; position: fixed; bottom: 0; left: 50%;transform: translateX(-50%); padding: 4px 8px 2px 8px; font-variant: small-caps; color: hsla(0, 0%, 80%, 1); background-color: hsla(0, 0%, 20%, 1); border-radius: 5px 5px 0px 0px; cursor: pointer;}
adjustorator:hover { background-color: hsla(200, 40%, 40%, 1); }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="container">
<div class="left">
<div class="red"></div>
<div class="blue"></div>
</div>
<div class="right">
<div class="green"></div>
</div>
</div>
<!-- scaffolding, ignore -->
<adjustorator>adjust height</adjustorator>
fiddle
https://jsfiddle.net/Hastig/42qzzhdu/
2 I'll also leave my original (non-) answer for those who come here in the future, looking for a solution to a similar question
align-self: flex-end; added to .green
fiddle
https://jsfiddle.net/Hastig/42qzzhdu/1/

Flexbox: Move header and footer to sidebar with flexbox

My content layout consists of three sections: header, content and footer. For small devices I want to keep this order, on desktop I would like to move header and footer to the sidebar.
Implemented using floats: http://codepen.io/anon/pen/jqrZby
Markup
<div class="page">
<div class="top"></div>
<div class="content"></div>
<div class="bottom"></div>
</div>
CSS
.page {
border: 2px solid black;
padding: 1em;
}
.page:after {
content: "";
display: block;
clear: both;
}
.page > * {
margin-bottom: 1em;
}
.top {
border: 2px solid red;
height: 100px;
}
.content {
border: 2px solid blue;
height: 400px;
}
.bottom {
border: 2px solid green;
height: 200px;
}
#media screen and (min-width: 800px) {
.content {
width: 66%;
float: left;
}
.top, .bottom {
width: 33%;
float: right;
}
}
I'm trying to find a solution using flexbox with a fixed spacing between content and sidebar. Anybody got an idea if this is possible?
Without changing the stucture and using flexbox you need to use flex-direction:column.
First we build it "mobile first" because it follows the actual order of the div structure we have already.
Then, at the appropriate media query we need to make the container wrap...often this will require a fixed height (be it viewport or px value)...then we can re-order the elements (using, ahem, order) and impose our required widths.
Codepen Demo
* {
box-sizing: border-box;
}
.page {
border: 2px solid black;
display: flex;
flex-direction: column;
height: 400px;
padding: 1em;
}
.top {
border: 2px solid red;
height: 100px;
width: 100%;
order: 1;
margin-bottom: 1em;
}
.content {
border: 2px solid blue;
height: 400px;
order: 2;
}
.bottom {
border: 2px solid green;
height: 200px;
order: 3;
margin-top: 1em;
}
#media screen and (max-width: 800px) {
.page {
flex-wrap: wrap;
justify-content: space-between;
}
.top {
order: 2;
}
.top,
.bottom {
width: 33%;
}
.content {
order: 1;
flex: 0 0 100%;
width: 66%;
margin-right: 1em;
}
}
<div class="page">
<div class="top">top</div>
<div class="content">content</div>
<div class="bottom">bottom</div>
</div>

2 divs fill horizontal space

I have 2 div's in parent wrapper. I would like to make the following:
these 2 divs share 100% space in width, so there is no gap between them, everything is red color.
When you scale the wrapper down, div b falls into new line below div a (this behaves as it should), but in this case I want both divs to be 100% width, so they make 2 lines of red color.
Is it possible to do this just with css (no tables!) and no additional elements?
Making wrapper background color red to compensate for this is not the solution.
<div class="wrapper">
<div class="a">left</div>
<div class="b">right</div>
</div>
http://jsfiddle.net/EAkLb/75/
Just change the CSS to width:50%; for both a and b, add a media query to set them to 100% at smaller viewports.
.wrapper{
position: relative;
max-width: 400px;
height:30px;
background-color: #fff;
}
.a{
float: left;
background-color: red;
text-align: left;
width:50%;
height:30px;
}
.b{
float: right;
background-color: red;
text-align: right;
width:50%;
height:30px;
}
#media screen and (max-width: 500px) {
.a, .b {
width: 100%;
}
}
<div class="wrapper">
<div class="a">left</div>
<div class="b">right</div>
</div>
Flexbox can do that:
JsFiddle demo
.wrapper {
position: relative;
max-width: 400px;
height: 30px;
background-color: #fff;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.a {
background-color: red;
text-align: left;
flex: 0 0 110px;
height: 30px;
}
.b {
background-color: red;
text-align: right;
flex: 0 0 120px;
height: 30px;
}
#media screen and (max-width: 400px) {
.a,
.b {
flex: 1 0 100%;
}
}
<div class="wrapper">
<div class="a">left</div>
<div class="b">right</div>
</div>
Consider you are using CSS media queries, you can simply change the width and the css float property of your divs. It's not the modern way, but it's work.
.wrapper{
position: relative;
max-width: 400px;
height:30px;
background-color: #fff;
}
.a, .b {
float: left;
width: 50%;
}
.a{
background-color: red;
text-align: left;
height:30px;
}
.b{
background-color: red;
text-align: right;
height:30px;
}
#media screen and ( max-width: 400px ) {
.a, .b {
float: none;
width: 100%;
}
}
The beauty of flex is that mediaqueries can often be avoided.
Using a combination of flex with min-width and flex-wrap we can achieve the desired effect without a media query.
.wrapper{
position: relative;
max-width: 400px;
height:30px;
background-color: #fff;
display: flex;
flex-wrap: wrap;
}
.child {
flex-grow: 1;
background-color: red;
height:30px;
}
.a{
min-width:110px;
text-align: left;
}
.b{
min-width:120px;
text-align: right;
}
<div class="wrapper">
<div class="child a">left</div>
<div class="child b">right</div>
</div>
Here's a JSFiddle.
My solution uses also Flex - but I use a min-width attr. to tell the flex container when to switch to 2 lines
.wrapper{
position: relative;
max-width: 100%;
height:30px;
background-color: #fff;
display: flex;
flex-wrap:wrap ;
}
.a,.b {
background-color: red;
width:50%;
min-width:130px;
height:30px;
flex-grow:1;
flex-shrink:0;
flex-basis:50%
}
.b {
background-color:green;
text-align:right;
}
fiddle
use the slider to make the window smaller
I used green as back for the 'b' element