I'm looking to make two columns of equal height that reverse their stacking at an 845px breakpoint. How should I code my css for regular view vs the 845px #media?
What are the benefits and or shortcomings of either method?
You can do it with the Flexbox:
.parent {
display: flex;
height: 300px;
}
.parent > .child-1 {
flex: 1;
background: red;
}
.parent > .child-2 {
flex: 1;
background: blue;
}
#media screen and (max-width: 845px) {
.parent {
flex-direction: column;
}
.parent > .child-1 {
order: 2;
}
}
<div class="parent">
<div class="child-1"></div>
<div class="child-2"></div>
</div>
This can be accomplished with flex and the order property. The basic idea is to stack the items, using their default DOM order (col 1 before col 2), then in a media query use the order property to swap the order so col 2 is to the left of col 1. Like this:
.container {
display: flex;
flex-direction: column;
}
.col {
flex: 1;
display: flex;
flex-basis: 200px;
flex-direction: column;
border-width: 1px;
border-style: solid;
justify-content: center;
text-align: center;
margin: 10px;
font-family: Arial;
}
.col--1 {
border-color: red;
color: red;
}
.col--2 {
border-color: blue;
color: blue;
}
#media screen and (min-width: 845px) {
.container {
flex-direction: row;
}
.col--1 {
order: 2;
}
.col--2 {
order: 1;
}
}
<div class="container">
<div class="col col--1">
COL 1<br/> DIV
</div>
<div class="col col--2">
COL 2<br/> DIV
</div>
</div>
Related
This question already has answers here:
Force flex item to span full row width
(2 answers)
Closed 3 years ago.
I have the following markup:
<div class="container">
<div class="logo"></div>
<div class="search"></div>
<div class="button"></div>
</div>
CSS (desktop):
.container {
display: flex;
}
On a desktop view they're displayed in a row, like that:
But on mobile view, i want them to re-reorder:
I've tried the following styles:
// here's media query for mobile devices
.container {
flex-direction: column;
flex-wrap: wrap;
align-items: stretch // so my items would be filling width
}
.logo {
order: 1;
flex: 1 0 50%;
}
.search {
order: 2;
flex: 0 1 100%;
}
.button {
order: 1;
flex: 1 0 50%;
}
But my results are:
Is this even possible with a flexbox?
You should look into "flex-grow" which allows flex items to grow if necessary in order to take up as much space as is available in its container. If all flex-items (in your case: .logo, .search, .button) have a flex-grow value of 1, the remaining space in .container will be distributed to its children equally.
Also, you should use
flex-direction: row;
in your case if you want them to stretch horizontally
Check out this fiddle for reference! https://jsfiddle.net/hgs5w19y/2/
You need to use flex-grow (great resource for understanding flexbox: https://css-tricks.com/snippets/css/a-guide-to-flexbox/)
HTML
<div class="container">
<div class="logo">Logo</div>
<div class="search">Search</div>
<div class="button">Button</div>
</div>
CSS
.container {
background-color: #ccc;
display: flex;
width: 300px;
flex-wrap: wrap;
text-align: center;
}
.container > div {
background-color: grey;
margin: 10px 20px;
padding: 10px 20px;
}
.logo {
order: 1;
flex-grow: 1;
}
.search {
order: 2;
flex-grow: 2;
}
.button {
order: 1;
flex-grow: 1;
}
No need of direction nor so many rules, just set a breakpoint and reset .search behavior
.container {
display: flex;
flex-wrap: wrap;
}
.container>div {
flex: 1;
}
div.search {
order: 1;
flex-basis: 100%;
}
#media screen and (min-width:731px) {
div.search {
order: 0;
flex: 1
}
}
/* demo purpose */
.container {
background: gray;
}
.container>div {
padding: 1em;
margin: 1em;
background: lightgray;
}
.container>div:before {
content: attr(class);
color: black;
}
<div class="container">
<div class="logo"></div>
<div class="search"></div>
<div class="button"></div>
</div>
breakpoint value is to be updated to yours (here set at 731 for the demo) , to see behavior, run the snippet in full page, or play with the demo https://codepen.io/gc-nomade/pen/mYXZdY
I'm trying to make a horizontal card using flexbox without having nested divs.
For example, what I have right now is this:
.card {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.card-img {
width: 37%;
}
.card-content {
width: 63%;
}
<div class='card'>
<div class='card-img'>
<img src='example' />
</div>
<div class='card-content'>
<div class='card-number'>
</div>
<div class='card-type'>
</div>
</div>
</div>
This layout works for now, but when the viewport resizes, I want the horizontal card to change into a vertical one (which it already does). However, I want to re-order the card-img, card-number, and card-type using flex order.
How could I get this same horizontal layout while using this type of div layout?
Edit:
Sorry for the confusing wording, what I was aiming to do was to create a horizontal layout that works like the image except with 3 separate divs, not 2 divs with 1 being a nested div. Sorry!
.card {
display: flex;
}
.card-img {
flex: 0 0 37%;
border: 1px dashed red;
}
.card-number {
flex: 0 0 30%;
border: 1px dashed red;
}
.card-type {
flex: 1 0 30%;
border: 1px dashed red;
}
img {
width: 100%;
}
.card > div {
display: flex;
align-items: center;
justify-content: center;
}
#media (max-width: 500px) {
.card { flex-direction: column; }
.card-img { order: 3; }
.card-number { order: 2; }
.card-type { order: 1; }
}
<div class='card'>
<div class='card-img'>
<img src="http://i.imgur.com/60PVLis.png">
</div>
<div class='card-number'>555</div>
<div class='card-type'>Orange</div>
</div>
https://jsfiddle.net/7y8sarwn/
I'm trying to build media query, which will be working like on the sketch. Any suggestion?
.container {
display: flex;
flex-direction: row;
justify-content: space-between;
background-color: lightblue;
width: 100%;
padding: .5rem;
box-sizing: border-box;
}
.name {
background-color: white;
padding: 1rem;
margin: .25rem;
flex-basis: 40px
}
.options {
display: flex;
flex-direction: row;
}
.option {
background-color: white;
padding: 1rem;
margin: .25rem;
flex-basis: 80px;
}
.action {
background-color: white;
padding: 1rem;
margin: .25rem;
}
#media (max-width: 350px){
.name {order: 1}
.action {order: 2}
.options {order: 3}
.container {
flex-direction: column;
flex-wrap: wrap;
}
}
<div class="container">
<div class="name">Lorem ipsum</div>
<div class="options">
<div class="option">2</div>
<div class="option">3</div>
<div class="option">4</div>
</div>
<div class="action">
5
</div>
</div>
I have already started, but I'm not really satisfied :). I need something more stable, as I will want to use it here later.
https://codepen.io/danzawadzki/pen/mwPYMz
At this moment I'm changing order and flex-direction in media query, but it's not good enough. Box number 1 will contain name of the segment, so it should have fixed width. There will be multiple items like that in one column, so I would prefer to keep it looks clean with same proportions.
Use this may be it will work for you
#media (max-width: 350px){
.options {order: 3; flex:0 0 100%;}
.container {
flex-wrap: wrap;
}
}
If you change your #media and remove flex-direction: column and add flex-basis: 100% to the option, it will flow as your image shows
#media (max-width: 350px){
.options {
order: 1; flex-basis: 100%;
}
.container {
flex-wrap: wrap;
}
}
Note, I also removed the .name and .action rules, as they are not necessary
Fiddle demo
Stack snippet
.container {
display: flex;
flex-direction: row;
justify-content: space-between;
background-color: lightblue;
width: 100%;
padding: .5rem;
box-sizing: border-box;
}
.name {
background-color: white;
padding: 1rem;
margin: .25rem;
flex-basis: 40px
}
.options {
display: flex;
flex-direction: row;
}
.option {
background-color: white;
padding: 1rem;
margin: .25rem;
flex-basis: 80px;
}
.action {
background-color: white;
padding: 1rem;
margin: .25rem;
}
#media (max-width: 350px){
.options {
order: 1; flex-basis: 100%;
}
.container {
flex-wrap: wrap;
}
}
<div class="container">
<div class="name">Lorem ipsum</div>
<div class="options">
<div class="option">2</div>
<div class="option">3</div>
<div class="option">4</div>
</div>
<div class="action">
5
</div>
</div>
Updated
By setting .options { flex-grow: 1; } and .option { flex: 1 1 80px; }, you can have the options/option elements to fill the remaining space on wider screens
Fiddle demo 2
Stack snippet 2
.container {
display: flex;
flex-direction: row;
justify-content: space-between;
background-color: lightblue;
width: 100%;
padding: .5rem;
box-sizing: border-box;
}
.name {
background-color: white;
padding: 1rem;
margin: .25rem;
flex-basis: 40px
}
.options {
flex-grow: 1;
display: flex;
}
.option {
background-color: white;
padding: 1rem;
margin: .25rem;
flex: 1 1 80px;
}
.action {
background-color: white;
padding: 1rem;
margin: .25rem;
}
#media (max-width: 350px){
.options {
order: 1; flex-basis: 100%;
}
.container {
flex-wrap: wrap;
}
}
<div class="container">
<div class="name">Lorem ipsum</div>
<div class="options">
<div class="option">2</div>
<div class="option">3</div>
<div class="option">4</div>
</div>
<div class="action">
5
</div>
</div>
I have a flexbox that has 2 boxes on the left and 1 box on the right. I need for the box on the right to wedge between the two boxes on the left.
[EDIT:Clarification]Box 3 should fully expand to consume the same space as boxes 1 and 2 on the left side.[/EDIT]
.rowParent {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
align-content: stretch;
align-items: stretch;
}
.flexChild {
flex: 1;
-webkit-align-self: auto;
-ms-flex-item-align: auto;
align-self: auto;
}
.flexChild2 {
flex: 1 100%;
-webkit-align-self: auto;
-ms-flex-item-align: auto;
align-self: auto;
}
#columnChild41158 {
background-color: green;
order: 1;
}
#columnChild61714 {
background-color: red;
order: 3;
}
#rowChild24054 {
background-color: blue;
order: 2;
}
#media (min-width: 1000px) {
.columnParent {
-webkit-box-orient: vertical;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
.flexChild2 {
-webkit-box-flex: 1;
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
}
}
<div id="container" class="flexChild rowParent">
<div id="rowChild71124" class="flexChild2 columnParent">
<div id="columnChild41158" class="flexChild">1</div>
<div id="columnChild61714" class="flexChild">2</div>
</div>
<div id="rowChild24054" class="flexChild">3</div>
</div>
Here's a codepen of what I am trying to do:
http://codepen.io/ants/pen/rLYVPa
Currently it is:
1 3
2
Once the browser is under 1000px I want it to stack as 100% width items but as:
1
3
2
I tried using order but that doesn't seem to work.
I don't think there is other way to do this unless you set fixed height on flex container. To change order of elements you can't have nested elements in you HTML.
* {
box-sizing: border-box;
margin: 0;
}
.content {
display: flex;
height: 100vh;
flex-direction: column;
flex-wrap: wrap;
}
.box {
flex: 0 0 50%;
width: 50%;
border: 1px solid black;
}
.last {
flex: 1;
background: lightblue;
}
#media(max-width: 768px) {
.box {
flex: 1;
width: 100%;
}
.last {
order: 2;
}
.second {
order: 3;
}
}
<div class="content">
<div class="box first">1</div>
<div class="box second">2</div>
<div class="box last">3</div>
</div>
If you can remove the extra wrapper div to make all flex items at the same level, you can do it with flex-flow: column nowrap; and flex-flow: row wrap; in the media queries, plus order and width tricks.
.rowParent {
display: flex;
flex-flow: column nowrap;
}
.flexChild {
width: 100%;
}
.flexChild2 {
order: 1;
}
#media (min-width: 1000px) {
.rowParent {
flex-flow: row wrap;
}
.flexChild {
width: 50%;
}
}
.flexChild1 { background-color: lightgreen; }
.flexChild2 { background-color: lightpink; }
.flexChild3 { background-color: lightblue; }
<div class="rowParent">
<div class="flexChild flexChild1">1</div>
<div class="flexChild flexChild2">2</div>
<div class="flexChild flexChild3">3</div>
</div>
I am trying to achieve a flexbox based transition from this (mobile):
To this (desktop):
However I am struggling to stack the two side panels vertically, my own code generates the main, search and other in a single row. I have not inserted webkit code for the sake of brevity.
Code:
p {
padding: 10px;
}
.flex-container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.header {
flex: 1 0 100%;
background-color: pink;
}
.search {
flex: 1 100%;
background-color: yellow;
}
.main {
flex: 1 100%;
background-color: lightblue;
}
.other {
flex: 1;
background-color: Red;
}
#media (min-width: 600px) {
.flex-container {} .search {
flex: 1 0;
order: 2
}
.main {
flex: 3 0;
order: 1;
}
.other {
flex: 1 0;
order: 3
}
}
<div class="flex-container">
<div class="header">
<p>header</p>
</div>
<div class="search">
<p>search</p>
</div>
<div class="main">
<p>main</p>
</div>
<div class="other">
<p>other</p>
</div>
</div>
jsFiddle: https://jsfiddle.net/azizn/d2pmdvc4/
The problem here is that you can't really do that with Flexbox if your main elements (#main, #search and #other) are siblings unless you know the fixed height value of #search (hacky solution with position: absolute):
#header, .flex div {
padding: 1em;
box-sizing: border-box;
border: 1px solid red;
margin-bottom: 1em; }
.flex {
display: flex;
flex-direction: column;
position: relative; }
#main { min-height: 300px; order: 2; }
#other { order: 3; }
/* desktop version */
#media (min-width:768px) {
.flex { flex-direction: row; flex-wrap: wrap; }
#main { width: 60%; }
#search { order: 2; width: 40%; height: 100px }
#other { width: 40%; position: absolute; top: 100px; right: 0; }
}
<div id="header">header</div>
<div class="flex">
<div id="main">main</div>
<div id="search">search</div>
<div id="other">other</div>
</div>
jsFiddle: https://jsfiddle.net/azizn/uhwzyr9b/
So logically you could try to wrap #search and #other inside another container but then you couldn't position #content between them because Flexbox can alter order of siblings only... The only workaround for that is probably JavaScript.
Edit: You can achieve your layout by using good old floats instead of Flexbox:
#header, #main, #search, #other {
padding:1em;
box-sizing:border-box;
border:1px solid red;
margin-bottom:1em;
}
#main { min-height: 300px; }
#media (min-width:768px) {
.container { overflow: auto; }
#main { width: 60%; float: left; }
#search { width:40%; float: right; }
#other { width:40%; float: right; }
}
<div id="header">header</div>
<div class="container">
<div id="search">search</div>
<div id="main">main</div>
<div id="other">other</div>
</div>
jsFiddle: https://jsfiddle.net/azizn/g5vxtbed/