Flexbox - move middle element to the next line (without media query) - css

What I want to achieve (but without the media query):
JsFiddle
#media all and (max-width: 600px) {
#wrapper {
flex-wrap:wrap;
height: 100px;
}
.center {
width: 100%;
order: 3;
}
.left{
width: 50%;
}
.right {
width:50%;
order:2;
}
}
I have 3 elements inside a wrapper, all shrinked. At desktop size, there is some space left over, however when I resize my window to a smaller dimension, at some point, elements run out of space. When that happens, I want to put the middle element to the next line. I have a solution, where the third element goes to the next line, and JSFiddle solution, where the second element goes to the next line, but always at the same static width.
So is it possible to put the middle element to the next line, when all three shrinked elements run out of space?

You can definitely wrap the line without media queries by using flex-wrap, flex-grow, flex-shrink and flex-basis to specify a minimum width that any given item should have:
#wrapper{
display: flex;
width: 100%;
height: 50px;
align-items: center;
text-align: center;
flex-wrap: wrap;
}
.right{
width: 20%;
background-color: blue;
order: 3;
flex-grow: 1;
flex-shrink: 0;
flex-basis: 200px;
}
But it's not possible to change the flex-order based solely on whether the elements "fit". For that you definitely need a media query.

Related

Flex responsive max-width with space-between

I am adding 3 columns that are 400px wide max and adding space between them using space-between.
.wrap {
display: flex;
flex-wrap: wrap;
align-content: stretch;
justify-content: space-between;
}
.item {
width: 100%;
max-width: 400px;
}
When I make the screen size smaller, the items are not responsive. They just collapse below each other. If I remove flex-wrap I start getting more than 3 columns per row and they are below 400px.
How can I get 3 responsive columns with space between in flex?
Percent for the width can't be used because the space between items has to look the same at any screen size.
You should drop width: 100% if you do not want them to occupy the whole width of the parent. And since you are using flex on the parent, you might as well use flex properties on the children and have these:
.item {
flex-basis: 33%; /* <-- Added in lieu of the width */
max-width: 400px;
margin: 0px 5px; /* <-- Added to give left/right margins */
}
If you only have those 3 children in the parent, then you could also do this:
.item {
flex-grow: 1; /* <-- Lets them grow equally */
flex-shrink: 1; /* <-- Lets them shrink equally. OPTIONAL as 1 is the default */
max-width: 400px;
margin: 0px 5px; /* <-- Added to give left/right margins */
}
The shorthand for the last one is this:
.item {
flex: 1; /* <-- Lets them grow/shrink equally */
max-width: 400px;
margin: 0px 5px; /* <-- Added to give left/right margins */
}
Also, if you only have those 3 children in the parent, you may want to remove flex-wrap: wrap; from .wrapper if you do not want the children elements to wrap. It will not happen in this case, since the children have percentage widths which add up to 100%. But it could be confusing and it contradicts with your intent.
If you want three columns, change the width property to 33% in your .item declaration instead of 100%.
JSFiddle example
Currently, all your "columns" are fighting to be 100% of the parent node. Here's a great explanation of using css flex from css-tricks.com.

CSS Flexbox height

I'm trying to make a chat layout. So i have 3 divs, activeUSer - top, messages middle (has to fill the space between 1 and 3), actions - bottom
Now, I've put flex-direction row. and it works fine. I needed the bottom div to grow if the input grows (if you have 2 or more lines of writing)
It worked ok untill I added display:flex to the Actions div (bottom). I needed another flex layout for input and buttons. Now it does not care for the padding i've set on the last div
Here is my codepen https://codepen.io/capraruioan/pen/XKWxrV
#content {
height: 300px;
display: flex;
flex-direction: column;
}
.activeUser {
height: 66px;
background-color: yellow;
}
.Messages {
flex: 1 1 100%;
}
.Actions {
flex-grow: 1;
display: flex;
padding-top: 2px;
padding-bottom: 20px;
}
.aa { //the inputbox
border: 1px solid black;
min-height: 10px
}
fixed it by letting display default on the 3rd div and placing a div with display flex inside

flex-box stretching issue

I have a problem with flex-box. I want a one column with two rows where there are 2 columns on the second row. However I want to use just one wrapper element for it (I do not want to wrap the second row into a div). The issue is that I want only the second row elements to strech.
Here it is https://jsfiddle.net/x8g0wupg/
HTML
<div id="wrap">
<header>text</header>
<div id="a">text</div>
<div id="b">text</div>
</div>
CSS
#wrap {
display: flex;
flex-flow: row wrap;
height: 500px;
border: 3px solid yellow;
}
header {
background-color: white;
width: 50px;
flex: 1 100%;
height: 40px;
}
#a {
background-color: green;
flex-grow: 1;
}
#b {
background-color: red;
flex-grow: 1;
}
I managed to make them the way I want them to be positioned however the first column element just doesnt want to shring to the height I have set to him instead of it it leaves a empty space to the vertical 50% of the wrapper.
Is there any way to do it without extra wrapper for the second row?
Thank you!
A bit hackish, with align-self: flex-end; and a negative top margin on the parent.
See https://jsfiddle.net/C14L/1rj3kdkb/

Why does "flex-wrap: wrap" break "align-items"?

(I'm using Chrome v.39+)
I'm trying to use the flex-wrap property to stack child divs both horizontally and vertically, but I'm seeing some very strange behaviors. For example, if there's 3 child divs and the last is given a width of 100% (causing it to wrap) there will be unwanted gaps introduced.
Sometimes I can force the first 2 divs to honor align-items: stretch by giving them height: 100% or height: calc(100% - 1px), other times they won't stretch passed the mysterious gap, and sometimes they'll even disappear all together if I try to force them to stretch.
Here's a simplified example of the problem. They grey shouldn't be visible.
Why are these gaps appearing in flex-wrapped divs and how can I prevent them?
The gray area is still visible at the bottom because you set a height on the parent container.
If you don't want to see that gray area, remove the height from the container and add a fixed height that you require on one of the elements in the first row
DEMO
.a {
width: 300px;
display: flex;
flex-wrap: wrap;
position: relative;
top: 100px;
left: 200px;
background-color: #999;
}
.b {
height: 150px;
background-color: #00ff00;
}
.c {
background-color: #0000ff;
}
.d {
background-color: #ff0000;
}
.b {
flex-grow: 1;
flex-shrink: 0;
}
.c {
width: 5px;
flex-shrink: 0;
}
.d {
width: 100%;
height: 10px;
flex-shrink: 0;
}
<div class='a'>
<div class='b'></div>
<div class='c'></div>
<div class='d'></div>
</div>
Note: If you want to avoid fixed dimensions - just remove the height:10px from the red div.
This will ensure that there are no gaps and that each row has equal height
DEMO

Responsive web design scenario

I am designing a 3 column web page layout like below.
To make it responsive I specified widths in %, min width in pixels and float:left. Now If I resize the page, all 3 DIVs (1,2, and 3) get resized first then 3rd DIV moves below of 1st DIV. If I resize more then 2nd DIV moves to below of 1st and 3rd moves below to 2nd.
This is because of float property. But I want to modify it in such a way that 3rd DIV should be moved first (as it is already being) then 1st DIV should be moved instead of 2nd DIV. 2nd DIV must be on the top.
How can I do this?
Reordering can be done with Flexbox. You will, however need 1 media query.
http://codepen.io/cimmanon/pen/fwqed
body {
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
-ms-flex-flow: row wrap;
flex-flow: row wrap;
}
div {
-webkit-flex: 1 1 20em;
-ms-flex: 1 1 20em;
flex: 1 1 20em;
}
#media (max-width: 40em) {
.a, .c {
-ms-flex-order: 1;
-webkit-order: 1;
order: 1;
}
}
.a {
background: orange;
}
.b {
background: yellow;
}
.c {
background: grey;
}
Reordering can also be done with relative positioning (see: https://stackoverflow.com/questions/16307621/reordering-elements-at-specific-browser-widths).
Sorry I had some missed some details on how it should look earlier, here is another solution with some simple jQuery/javascript:
http://jsfiddle.net/jzxww/4/
This solution has Column 1 move to the bottom instead of to the middle.
Here is the code broken down
function resizeHandlr(){
trigger = $("#superwrap").width(); // get width of wrapper
$("#supersize").html("superwrap size: " + trigger + "px");
if (trigger > 600){
// if greater than 600px, make all widths 33.33% so they are responsive;
} else if ( (trigger < 600) && (trigger > 400)){
// if between 600 and 400px, make top columns 50% and bottom one 100%
// move column1 back to top of wrapper (if coming from < 400px)
} else if (trigger < 400) {
// if wrapper is less than 400px, make all widths 100%
// also MOVE column 1 to the bottom of wrapper
}
}
try this
//css
.left-col{float:left;width:33%}
.right-col{float:right;width:33%}
.main-col{margin: 0 33%}
//html
<div class="left-col"> some text </div>
<div class="right-col"> some text </div>
<div class="main-col"> some text </div>
I got pretty close to a 2,3,1. Check it out: http://jsfiddle.net/3QFaa/
New HTML Markup
<div id="superwrap">
<div id="muahaha">
<div id="col2">2</div>
<div id="col3">3</div>
</div>
<div id="col1">1</div>
CSS
#superwrap { position: relative; width: 100%; background-color: orange; min-width: 200px;}
#muahaha {top: 0px; width:66.66%; float: right; min-width: 200px; }
#muahaha:after {
content: "";
display: table;
clear: both;}
#col2, #col3 { float: left;}
#col1 { background-color: cyan; width: 33.33%; min-width: 200px;}
#col2 {background-color: yellow; width: 50%; min-width: 200px;}
#col3 { background-color: green; width: 50%; min-width: 200px;}
Thanks #sebastianG for the fiddle.
Only problem with this is, as you notice, col1 does not drop until it hits the very far right edge of #superwrap
Another nearly-perfect version:
If col1 does not have to be centered immediately:
http://jsfiddle.net/XDTEW/
Added float: left to col1
I also think you will be better using #media queries for different screen size scenarios.

Resources