Flex order not working as expected - html

I have a nav element with 3 child divs, with widths 25%, 50%, and 25% respectively, also flexbox order 1,2 and 3 respectively. In mobile view, I want to shift the second element down to next row taking full-width and first and third to stay in the first row consuming 50% widths each. I changed the second element's order to 3 and width 100%, also third element's order to 2 and 50% width. However, it is still not working as expected. Is it possible to achieve something like that using flexbox?
I have included a sample code
<nav>
<div class="a">
A
</div>
<div class="b">
B
</div>
<div class="c">
C
</div>
</nav>
and CSS
nav{
display:flex;
flex-direction:row;
}
.a,.b,.c{
border:1px solid blue;
text-align: center;
}
.a{
width:25%;
order:1;
}
.b{
width:50%;
order:2;
}
.c{
width:25%;
order:3;
}
#media screen and (max-width: 400px){
.a{
width:50%;
}
.b{
width:100%;
order:3;
}
.c{
width:50%;
order:2;
}
}
or use the fiddle
basically this is what I'm trying to achieve.
default view
on mobile

I updated your fiddle: https://jsfiddle.net/s9v926g9/1/
There are 2 things you need to add:
Add flex-wrap: wrap; to the nav element
This will make the elements wrap to a next line, instead of spacing themselves out over the available width.
Set the box sizing
Adding
*{
box-sizing: border-box;
}
to your css will make sure the borders are not messing up your flex-wrap.

You need to set flex-wrap: wrap on flex container and then you can just change order on mobile size and set flex: 0 0 100% on b element. Demo
nav {
display: flex;
flex-wrap: wrap;
}
.a, .b, .c {
border: 1px solid blue;
text-align: center;
}
.a, .c {
flex: 1;
}
.b {
flex: 2;
}
#media screen and (max-width: 400px) {
.b {
order: 2;
flex: 0 0 100%;
}
}
<nav>
<div class="a">A</div>
<div class="b">B</div>
<div class="c">C</div>
</nav>

Related

Flexbox wrap, choose what child drops to next line

It's possible to choose what child of flexbox should drop to the next line, instead of always dropping the last one?
Example:
Full-Size, no breaking:
Default behavior, breaking the last one.
Desired behavior, breaking the div from the middle to the other line:
Is this possible using flexbox?
column can approximate this in case you need equal width elements
.box {
column-width:max(30vw,150px);
}
.box > div {
padding:10px;
width:100%;
display:inline-block;
border:1px solid;
margin-bottom:5px;
box-sizing:border-box;
}
/* I need those extra elements to have correct layout */
.box > i {
display:block;
}
<div class="box">
<div>A</div><i></i>
<div>B</div><i></i>
<div>C</div>
</div>
Edited: You can use the order: n; property to order flexed items and flex shorthand property to make b element full width with flex: 0 0 100% and then change the order to order: 2
.flexbox {
display: flex;
flex-wrap: wrap;
}
.a, .b, .c {
flex: 1;
}
#media(max-width: 768px) {
.b {
flex: 0 0 100%;
order: 2;
}
}
<div class="flexbox">
<div class="a">A</div>
<div class="b">B</div>
<div class="c">C</div>
</div>

Table stretch to parent div, and columns to table, using css flexbox isn't working as expected

I have a div with a table on it. I simply want the table to occupy the whole div, then stretch the second column and its contained inputs, so that the inputs will be as large as possible (i.e. col1+col2 = div width).
All this is inside another div, so absolute measures such as 100% aren't an option.
In the following code, if I remove the flex-grow:1 from tr, nothing changes. But if then I remove the display:flex from t, the table won't stretch to the div anymore. Isn't it strange? I have tried including all these display:flex and flex-grow:1 down to td2, but it doesn't work, either.
And please don't tell me to avoid tables in formatting, because no other option works in all cases like tables do.
#d {
background-color:blue;
padding:2px;
width:400px;
display:flex;
}
#t {
background-color:red;
padding:2px;
flex-grow:1;
display:flex;
}
#tr {
background-color:green;
flex-grow:1;
}
<div id='d'>
<table id='t'>
<tr id='tr'>
<td id='td1'>col1</td>
<td id='td2'><input type='text'></td>
</tr>
</table>
</div>
Looks like flexbox and table hate each other. So I found out I should be using CSS Grid Layout instead.
.wrapper {
max-width:500px;
margin:0 auto;
}
.wrapper > div {
padding:2px;
margin:2px;
background-color: orange;
}
.wrapper {
display:grid;
grid-gap:2px;
grid-template-columns:auto 1fr;
background-color: green;
}
.one {
text-align:right;
align-self:center;
grid-column:1;
grid-row:1;
}
.two {
grid-column:2;
grid-row:1;
}
.three {
text-align:right;
align-self:center;
grid-column:1;
grid-row:2;
}
.four {
grid-column:2;
grid-row:2;
}
.wrapper > div > input {
width:100%;
box-sizing: border-box;
}
<div class="wrapper">
<div class="one">Line 1, with long text:</div>
<div class="two"><input></div>
<div class="three">Line 2:</div>
<div class="four"><input></div>
</div>

Display First DIV beneath Second DIV

say I have...
<div id="A"></div>
<div id="B"></div>
How can the end-user view div B on top of div A on their browser?
I'm trying to do this with CSS without editing the html.
You can use flex-box and order to acheive what you want
body {
display: flex;
flex-wrap:wrap;
}
#A {
width: 100%;
height:50px;
background: red;
color:white;
order: 2;
}
#B {
width: 100%;
height:50px;
background: black;
color:white;
order: 1;
}
<div id="A">A</div>
<div id="B">B</div>
You need to add display:flex; and flex-direction:column-reverse; to the parent of your two divs.
body{
display:flex;
flex-direction:column-reverse;
}
Or you can choose div's order manually with order property:
body {
display: flex;
}
#A {
order: 2;
}
#B {
order: 1;
}
Use CSS3 flex to change the positioning of flex elements and this can be done using order property,
The CSS order property specifies the order used to lay out flex items
in their flex container.
#box{
display:flex;
width:100%;
flex-direction:column;
}
.A{
order:2;
background:#111;
color:#fff;
}
.B{
order:1;
background:#111;
color:#fff;
}
<div id="box">
<div class="A">A</div>
<div class="B">B</div>
</div>
A way to do this in CSS:
The container must have display:flex attribute
Then :
#A{
order:2;
}
#B{
order:1;
}
You can also achieve this with jQuery
$('#B:parent').each(function () {
$(this).insertBefore($(this).prev('#A'));
});
It feels unclean to do it this way but here you go (no container element needed)
#A {
display: table-footer-group;
}
#B {
display: table-header-group;
}
<div id="A">A</div>
<div id="B">B</div>

Place div1 under div4 when div1 html code is on top of div4 [duplicate]

I am working on a responsive site and came across an interesting problem. I have some divs side by side. There could be anywhere from 2 to 6 or so of them. When the screen isn't wide enough to show all the content properly, the divs stack vertically. Simple enough to do with CSS.
The problem is, I need them to be in a different order depending on the layout. This is easy to do with 2 or 3 divs (Changing divs order based on width), but significantly more challenging when you add a fourth.
I could use position: absolute; and manually set the position, however this causes the parent to shrink and not contain them properly.
To make this even more complicated, I can't use JavaScript.
Working with two columns:
(untested)
HTML:
<div id="container">
<div class="column-half column-half-2">
First div on mobile, right div on desktop
</div>
<div class="column-half column-half-1">
Second div on mobile, left div on desktop
</div>
</div>
CSS:
.container {
width: 80%;
max-width: 1200px;
margin: 0 auto;
padding-bottom: 20px;
position: relative;
}
.column-half {
display: table-cell;
padding: 25px;
vertical-align: top;
width: 40%;
}
.column-half-1 {
float: left;
}
.column-half-2 {
float: right;
}
HTML, with 4 columns:
<div id="container">
<div class="column-quarter column-quarter-3">
First div on mobile, third div on desktop
</div>
<div class="column-quarter column-quarter-2">
Second div on mobile, second div on desktop
</div>
<div class="column-quarter column-quarter-1">
Third div on mobile, first div on desktop
</div>
<div class="column-quarter column-quarter-4">
Fourth div on mobile, fourth div on desktop
</div>
</div>
This is doable in CSS thanks to the wonderful flexbox spec. Using the order and flex-flow properties, we can achieve what you want. Unprefixed, IE11 and all evergreen browsers will support this. IE10 prefixes -ms-order and doesn't support flex-flow.
The solution takes into consideration all the constraints you listed:
Have a list of elements in a given order displayed as a row.
When the window is too small, change them to display in a column.
Change the order of the elements when they are displayed in a column.
Because of the limitations of Stack Snippets, you'll need to view the demo in Full page mode, and resize your browser to see the effect.
.container div {
width: 100px;
height: 50px;
display: inline-block;
}
.one { background: red; }
.two { background: orange; }
.three { background: yellow; }
.four { background: green; }
.five { background: blue; }
#media screen and (max-width: 531px) {
.container { display: flex; flex-flow: column; }
.five { order: 1; }
.four { order: 2; }
.three { order: 3; }
.two { order: 4; }
.one { order: 5 }
}
<div class="container">
<div class="one">I'm first</div>
<div class="two">I'm second</div>
<div class="three">I'm third</div>
<div class="four">I'm fourth</div>
<div class="five">I'm fifth</div>
</div>
Alternatively, here is a JSFiddle demo.
You can also simply use flex-flow: column-reverse without the order property assigned to each div, if you are so inclined against verbose CSS. The same demo restrictions apply; view this demo in full screen and resize the browser window accordingly.
.container div {
width: 100px;
height: 50px;
display: inline-block;
}
.one { background: red; }
.two { background: orange; }
.three { background: yellow; }
.four { background: green; }
.five { background: blue; }
#media screen and (max-width: 531px) {
.container { display: flex; flex-flow: column-reverse; }
}
<div class="container">
<div class="one">I'm first</div>
<div class="two">I'm second</div>
<div class="three">I'm third</div>
<div class="four">I'm fourth</div>
<div class="five">I'm fifth</div>
</div>
It's worth pointing out that flex-flow is a shorthand property encompassing both flex-direction and flex-wrap properties.

Change div order with CSS depending on device-width

I am working on a responsive site and came across an interesting problem. I have some divs side by side. There could be anywhere from 2 to 6 or so of them. When the screen isn't wide enough to show all the content properly, the divs stack vertically. Simple enough to do with CSS.
The problem is, I need them to be in a different order depending on the layout. This is easy to do with 2 or 3 divs (Changing divs order based on width), but significantly more challenging when you add a fourth.
I could use position: absolute; and manually set the position, however this causes the parent to shrink and not contain them properly.
To make this even more complicated, I can't use JavaScript.
Working with two columns:
(untested)
HTML:
<div id="container">
<div class="column-half column-half-2">
First div on mobile, right div on desktop
</div>
<div class="column-half column-half-1">
Second div on mobile, left div on desktop
</div>
</div>
CSS:
.container {
width: 80%;
max-width: 1200px;
margin: 0 auto;
padding-bottom: 20px;
position: relative;
}
.column-half {
display: table-cell;
padding: 25px;
vertical-align: top;
width: 40%;
}
.column-half-1 {
float: left;
}
.column-half-2 {
float: right;
}
HTML, with 4 columns:
<div id="container">
<div class="column-quarter column-quarter-3">
First div on mobile, third div on desktop
</div>
<div class="column-quarter column-quarter-2">
Second div on mobile, second div on desktop
</div>
<div class="column-quarter column-quarter-1">
Third div on mobile, first div on desktop
</div>
<div class="column-quarter column-quarter-4">
Fourth div on mobile, fourth div on desktop
</div>
</div>
This is doable in CSS thanks to the wonderful flexbox spec. Using the order and flex-flow properties, we can achieve what you want. Unprefixed, IE11 and all evergreen browsers will support this. IE10 prefixes -ms-order and doesn't support flex-flow.
The solution takes into consideration all the constraints you listed:
Have a list of elements in a given order displayed as a row.
When the window is too small, change them to display in a column.
Change the order of the elements when they are displayed in a column.
Because of the limitations of Stack Snippets, you'll need to view the demo in Full page mode, and resize your browser to see the effect.
.container div {
width: 100px;
height: 50px;
display: inline-block;
}
.one { background: red; }
.two { background: orange; }
.three { background: yellow; }
.four { background: green; }
.five { background: blue; }
#media screen and (max-width: 531px) {
.container { display: flex; flex-flow: column; }
.five { order: 1; }
.four { order: 2; }
.three { order: 3; }
.two { order: 4; }
.one { order: 5 }
}
<div class="container">
<div class="one">I'm first</div>
<div class="two">I'm second</div>
<div class="three">I'm third</div>
<div class="four">I'm fourth</div>
<div class="five">I'm fifth</div>
</div>
Alternatively, here is a JSFiddle demo.
You can also simply use flex-flow: column-reverse without the order property assigned to each div, if you are so inclined against verbose CSS. The same demo restrictions apply; view this demo in full screen and resize the browser window accordingly.
.container div {
width: 100px;
height: 50px;
display: inline-block;
}
.one { background: red; }
.two { background: orange; }
.three { background: yellow; }
.four { background: green; }
.five { background: blue; }
#media screen and (max-width: 531px) {
.container { display: flex; flex-flow: column-reverse; }
}
<div class="container">
<div class="one">I'm first</div>
<div class="two">I'm second</div>
<div class="three">I'm third</div>
<div class="four">I'm fourth</div>
<div class="five">I'm fifth</div>
</div>
It's worth pointing out that flex-flow is a shorthand property encompassing both flex-direction and flex-wrap properties.