I'm stuck on problem with stretching flexes.
I have flexbox div with items. These items can stretch to full width and have min-width property, so that 3-4 elements can fit in large screens, and 1-2 in small.
I want to make their widths equal, but the problem is that wrapped items are wider if their quantity is less than on top elements.
Attached below my current result and expected behavior. How can I make it?
.items {
display: flex;
justify-content: center;
flex-wrap: wrap;
width: 100%;
}
.item {
min-width: 400px;
border: 1px solid black;
margin: 0;
height: 200px;
flex-grow: 1;
}
<div class="items">
<div class="item">1</div>
<div class="item">1</div>
<div class="item">1</div>
<div class="item">1</div>
<div class="item">1</div>
</div>
Thanks!
Update 02.05.2016
Thanks to #vals I came up with percentage width solution for different screen sizes. (But it seems I'm having some tiny problem with 33% width elements, in which 1% empty space is left around them xD)
.items {
display: flex;
justify-content: center;
flex-wrap: wrap;
width: 100%;
box-sizing: border-box;
align-items: center;
}
#media only screen and (max-width: 820px) {
.item {
width: 100%;
}
}
#media only screen and (min-width: 821px) and (max-width: 1220px) {
.item {
width: 50%;
}
}
#media only screen and (min-width: 1221px) and (max-width: 1620px) {
.item {
width: 33%;
}
}
#media only screen and (min-width: 1621px) and (max-width: 2020px) {
.item {
width: 25%;
}
}
.item {
box-sizing: border-box;
border: 1px solid black;
margin: 0;
height: 200px;
}
<div class="items">
<div class="item">1</div>
<div class="item">1</div>
<div class="item">1</div>
<div class="item">1</div>
<div class="item">1</div>
</div>
This is a complex case, you need media queries adapted to you specific layout and number of elements present.
I have color-coded the different media queries result to help identify them
And also, three extra divs inside the items element to help with the dimensions
.items {
display: flex;
justify-content: center;
flex-wrap: wrap;
width: 100%;
}
.item {
min-width: 400px;
border: 1px solid black;
margin: 0;
height: 100px;
flex-grow: 2;
}
.filler1, .filler2, .filler3 {
height: 0px;
background-color: lightgreen;
}
#media only screen and (max-width: 820px) {
/* one item per line */
.filler2, .filler3 {display: none;}
.item {background-color: yellow;}
}
#media only screen and (min-width: 821px) and (max-width: 1220px) {
/* 2 items per line */
.item:nth-last-child(4) {
order: 9;
background-color: red;
}
.filler1 {
margin-right: 100%;
}
.filler2 {
min-width: 200px;
flex-grow: 1;
order: 4;
}
.filler3 {
min-width: 200px;
flex-grow: 1;
order: 14;
}
}
#media only screen and (min-width: 1221px) and (max-width: 1620px) {
.item:nth-last-child(4), .item:nth-last-child(5) {
order: 9;
background-color: green;
}
.filler1 {
margin-right: 100%;
}
.filler2 {
min-width: 200px;
flex-grow: 1;
order: 4;
}
.filler3 {
min-width: 200px;
flex-grow: 1;
order: 14;
}
}
#media only screen and (min-width: 1621px) and (max-width: 2020px) {
.item:nth-last-child(4) {
order: 9;
background-color: lightblue;
}
.filler1 {
margin-right: 100%;
}
.filler2 {
min-width: 400px;
flex-grow: 2;
order: 4;
}
.filler3 {
min-width: 400px;
flex-grow: 2;
order: 14;
}
}
<div class="items">
<div class="item">1</div>
<div class="item">1</div>
<div class="item">1</div>
<div class="item">1</div>
<div class="item">1</div>
<div class="filler1"></div>
<div class="filler2"></div>
<div class="filler3"></div>
</div>
Related
I edited literally a few lines from the code taken from this question link
#wrap {
margin: 20px auto;
width: 80%;
}
.separator {
margin-top: 30px;
}
.row {
height: 30px; margin-bottom: 10px; background-color: green;
}
.left,
.right {
width: 33%; height: 30px; line-height: 30px;
display: inline-block;
text-align: center;
background-color: grey;
}
.left { margin-right: 10px; }
.right { margin-left: 10px; }
.center {
min-height: 30px; line-height: 30px;
text-align: center;
background-color: blue;
display: inline-block;
width: 30%;
}
<div id="wrap">
<div class="left">left</div>
<div class="center">center</div>
<div class="right">right</div>
<div class="separator"></div>
<div class="left">left</div>
<div class="center">center</div>
<div class="right">right</div>
</div>
when the sizes of the windows becomes too small, for example on mobile, it will become a mess. When this happens, how can I reallocate items vertically, one items for line, where the left will be the first, the center the second, and so.
I'm actually using this in React, just to know.
With display grid
You can use grid-template-areas on the grid parent selectors and grid-areas on the grid children selectors to place the elements in the order you want them to be displayed in the document despite their order in the HTML. You just change the grid properties in your media query.
#cont {
display: grid;
grid-auto-columns: 1fr;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: auto;
grid-template-areas:
"left-1 center-1 right-1"
"left-2 center-2 right-2";
gap: .5rem;
}
.box {
height: 100px;
background: blue;
margin: 0.5rem;
}
.left-1 {
grid-area: left-1;
}
.left-2 {
grid-area: left-2;
}
.center-1 {
grid-area: center-1;
}
.center-2 {
grid-area: center-2;
}
.right-1 {
grid-area: right-1;
}
.right-2 {
grid-area: right-2;
}
/* mobile */
#media screen and (max-width: 700px) {
#cont {
display: grid;
grid-auto-columns: auto;
grid-template-columns: auto;
grid-template-rows: auto;
grid-template-areas:
"left-1"
"left-2"
"center-1"
"center-2"
"right-1"
"right-2";
gap: .5rem;
}
}
<div id="cont">
<div class="left-1 box">left</div>
<div class="center-1 box">center</div>
<div class="right-1 box">right</div>
<div class="left-2 box">left</div>
<div class="center-2 box">center</div>
<div class="right-2 box">right</div>
</div>
You could do the following without using display grid and just adding a media query:
You however do not have control of re-ordering the elements like you do with grid or flex display, you could use box-ordinal-group to change the order of the elements, however it has been taken out of the standard with the introduction of flex - order and grid.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#cont {
width: calc(100% - 5px);
height: auto;
margin: 5px;
}
.box {
min-width: calc(33.3% - 5px);
height: 100px;
background: blue;
display: inline-block;
}
.box~.box {
margin-top: 5px;
}
#media screen and (max-width: 700px) {
#cont {
width: calc(100% - 5px);
margin: 5px;
}
.box {
min-width: calc(100% - 5px);
height: 100px;
}
}
<div id="cont">
<div class="box">left</div>
<div class="box">center</div>
<div class="box">right</div>
<div class="box">left</div>
<div class="box">center</div>
<div class="box">right</div>
</div>
Using flex box with order
~ Change the visual order of your content when using Flexbox.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#cont {
display: flex;
flex-wrap: wrap;
}
.box {
min-width: calc(33.3% - 10px);
height: 100px;
background: blue;
display: inline-block;
margin: 5px;
}
#media screen and (max-width: 700px) {
#cont {
width: calc(100% - 10px);
margin: 5px;
}
.box {
min-width: calc(100% - 10px);
height: 100px;
}
.box:nth-of-type(1) {
order: 1;
}
.box:nth-of-type(2) {
order: 3;
}
.box:nth-of-type(3) {
order: 5;
}
.box:nth-of-type(4) {
order: 2;
}
.box:nth-of-type(5) {
order: 4;
}
.box:nth-of-type(6) {
order: 6;
}
}
<div id="cont">
<div class="box">left row 1</div>
<div class="box">center row 1</div>
<div class="box">right row 1</div>
<div class="box">left row 2</div>
<div class="box">center row 2</div>
<div class="box">right row 2</div>
</div>
You can use CSS Flexbox to position the items side-by-side on large screens, and use a media query to detect mobile devices and align the items vertically.
#wrap {
margin: 20px auto;
width: 80%;
}
.row {
display: flex;
}
/* mobile */
#media screen and (max-width: 700px) {
.row {
flex-direction: column;
}
}
.box {
width: 100%;
height: 100px;
background: blue;
margin: 0.5em;
}
<div id="wrap">
<div class="row">
<div class="box">left</div>
<div class="box">center</div>
<div class="box">right</div>
</div>
<div class="row">
<div class="box">left</div>
<div class="box">center</div>
<div class="box">right</div>
</div>
</div>
I have a sidebar nav which collapses to make way for more content in a flex layout. When the user clicks to collapse the nav the content area div .ca expands to fill the space and the flex layout reflows using media queries.
See it in action here.
I have applied a CSS transition to each moving element but the .ca div jumps when the nav is opened and closed. This seems to be related to the widths of the units in the flex layout – .songgrid-unit.
The unit has a width value in px but the media queries set a min-width value in % to override this, so as to avoid large empty spaces between break points:
html:
<div class="navbar open ease">
<div class="nav-toggle">
<div class="nt-wrap">
<div class="nt-bar ease" id="ntb-top"></div>
<div class="nt-bar ease" id="ntb-bot"></div>
</div>
</div>
</div>
<div class="ca ease">
<div class="songgrid ease">
<div class="songgrid-unit ease">
<!-- post content -->
</div>
<div class="songgrid-unit ease">
<!-- post content -->
</div>
<div class="songgrid-unit ease">
<!-- post content -->
</div>
</div>
</div>
CSS:
.navbar {
position: fixed;
display: flex;
flex-direction: column;
justify-content: space-between;
width: 214px;
height: 100vh;
left: 0;
top: 0;
box-sizing: border-box;
padding: 48px 8px 48px 32px;
background-color: #282828;
border-right: solid 1px #555;
z-index: 20;
}
.navbar.closed {
left: -214px;
}
.ca {
position: relative;
width: 100%;
padding: 48px 32px 48px 280px;
box-sizing: border-box; /*keep padding inside width*/
}
.ca.fullwidth {
width: 100%;
padding: 48px 32px 48px 64px;
}
.songgrid {
flex: 1;
display: flex;
justify-content: flex-end;
flex-wrap: wrap;
}
.songgrid-unit {
width: 280px;
box-sizing: border-box;
padding: 0 16px 48px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
/*adjust no. of cols as per screen width in both container widths*/
#media only screen and (max-width: 623px) {
.ca.fullwidth .songgrid-unit {
min-width: 100%;
}
}
#media screen and (min-width: 624px) and (max-width: 904px) {
.songgrid-unit {
min-width: 100%;
}
.ca.fullwidth .songgrid-unit {
min-width: 50%;
}
}
#media screen and (min-width: 905px) and (max-width: 1184px) {
.songgrid-unit {
min-width: 50%;
}
.ca.fullwidth .songgrid-unit {
min-width: 33%;
}
}
#media screen and (min-width: 1185px) and (max-width: 1464px) {
.songgrid-unit {
min-width: 33%;
}
.ca.fullwidth .songgrid-unit {
min-width: 25%;
}
}
#media screen and (min-width: 1465px) and (max-width: 1744px) {
.songgrid-unit {
min-width: 25%;
}
.ca.fullwidth .songgrid-unit {
min-width: 20%;
}
}
#media only screen and (min-width: 1745px) and (max-width: 1949px) {
.songgrid-unit {
min-width: 20%;
}
.ca.fullwidth .songgrid-unit {
min-width: 16.66667%;
}
}
#media only screen and (min-width: 1950px) {
.songgrid-unit {
min-width: 16.66667%;
}
.ca.fullwidth .songgrid-unit {
min-width: 14.285%;
}
}
.ease {
transition: all 0.4s ease-in 0s;
-webkit-backface-visibility: hidden;
}
jQuery:
$(".nav-toggle").click(function(){
$(".navbar").toggleClass("open closed");
$(".ca").toggleClass("fullwidth");
});
If I remove the media queries the transitions work fine, but the min-width values are breaking the effect.
Why is this happening and how can I fix it? Thanks.
It's hard to tell because the code on the site you linked is a bit different from what you posted here. But it seems to me like the .ca div isn't actually jumping, it just looks like it is because as the items inside the grid change in size the number of items per row changes. The jump happens when the items either take up more space so that one fewer can fit in a row, or take up less space so one more can fit per row.
I played with the code you posted here a bit just to demonstrate what I think is happening. I hid the nav and added some outlines around the songgrid-container & individual songgrid items, and then I slowed down the transition a bit. So you can press the blue box and see what the transition looks like in slow motion. It looks like the widths are all transitioning fine, it just jumps when the layout inevitably changes.
Unfortunately I don't have a super easy solution to this, it's not really something you can control with a basic CSS transition. But maybe look at a library like this: https://isotope.metafizzy.co/
I don't actually think the media queries have anything to do with it, but I may also just be completely misunderstanding the effect you are seeing!
$(".nav-toggle").click(function(){
// $(".navbar").toggleClass("open closed");
$(".ca").toggleClass("fullwidth");
});
.navbar {
position: fixed;
display: flex;
flex-direction: column;
justify-content: space-between;
width: 214px;
height: 100vh;
left: 0;
top: 0;
box-sizing: border-box;
padding: 48px 8px 48px 32px;
background-color: #282828;
border-right: solid 1px #555;
z-index: 20;
left: -214px;
}
.nav-toggle {
width: 50px;
height: 50px;
background-color: blue;
position: absolute;
right: -50px;
}
.navbar.closed {
left: -214px;
}
.ca {
position: relative;
width: 100%;
padding: 48px 32px 48px 280px;
background: lightblue;
box-sizing: border-box; /*keep padding inside width*/
}
.ca.fullwidth {
width: 100%;
padding: 48px 32px 48px 64px;
}
.songgrid {
flex: 1;
display: flex;
justify-content: flex-end;
flex-wrap: wrap;
outline: 2px solid blue;
}
.songgrid-unit {
width: 280px;
box-sizing: border-box;
padding: 0 16px 48px;
display: flex;
flex-direction: column;
justify-content: space-between;
background: rgba(255,255,255,.5);
outline: 2px solid gray;
}
/*adjust no. of cols as per screen width in both container widths*/
#media only screen and (max-width: 623px) {
.ca.fullwidth .songgrid-unit {
min-width: 100%;
}
}
#media screen and (min-width: 624px) and (max-width: 904px) {
.songgrid-unit {
min-width: 100%;
}
.ca.fullwidth .songgrid-unit {
min-width: 50%;
}
}
#media screen and (min-width: 905px) and (max-width: 1184px) {
.songgrid-unit {
min-width: 50%;
}
.ca.fullwidth .songgrid-unit {
min-width: 33%;
}
}
#media screen and (min-width: 1185px) and (max-width: 1464px) {
.songgrid-unit {
min-width: 33%;
}
.ca.fullwidth .songgrid-unit {
min-width: 25%;
}
}
#media screen and (min-width: 1465px) and (max-width: 1744px) {
.songgrid-unit {
min-width: 25%;
}
.ca.fullwidth .songgrid-unit {
min-width: 20%;
}
}
#media only screen and (min-width: 1745px) and (max-width: 1949px) {
.songgrid-unit {
min-width: 20%;
}
.ca.fullwidth .songgrid-unit {
min-width: 16.66667%;
}
}
#media only screen and (min-width: 1950px) {
.songgrid-unit {
min-width: 16.66667%;
}
.ca.fullwidth .songgrid-unit {
min-width: 14.285%;
}
}
.ease {
transition: all 3s ease-in 0s;
-webkit-backface-visibility: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<body>
<div class="navbar open ease">
<div class="nav-toggle">
click
</div>
</div>
<div class="ca ease">
<div class="songgrid ease">
<div class="songgrid-unit ease">
content
</div>
<div class="songgrid-unit ease">
content
</div>
<div class="songgrid-unit ease">
content
</div>
</div>
</div>
</body>
</html>
With some help getting onto the right path from the reply from #sparrow here I've found that the transitions can be rendered much smoother by applying further flex properties to the items creating the columns in the grid.
Updating the CSS for the .songgrid-unit class as follows fixes the issue:
.songgrid-unit {
width: 280px;
box-sizing: border-box;
padding: 0 16px 48px;
display: flex;
flex-grow: 1; /*new line*/
flex-shrink: 1; /*new line*/
flex-basis: auto; /*new line*/
flex-direction: column;
justify-content: space-between;
}
With thanks to #sparrow and the authors over at this thread.
Is it possible to pull out a flex-item in the middle and stretch it to 100% width as a second row in HTML on resize?
I have the follow flex-items wrapped in a flex-box
Item-A Item-B Item-C Item-D Item-E
<div class="d-flex flex-wrap">
<div>Item-A</div>
<div>Item-B</div>
<div>Item-C</div>
<div>Item-D</div>
<div>Item-E</Div>
</div>
On smaller devices, I want the Item-B to be pulled out of the row and display as a second row but inside the parent container. Is it possible to do with CSS flex?
Note: I am using bootstrap as CSS framework
Use flex-basis: 100% to make your item full width, and order: 1 to place it after all the other items in the container. In the snippet below I've set this to happen on devices smaller than 500px:
.flex-container {
display: flex;
flex-wrap: wrap;
}
.item {
flex: 1;
outline: 1px dashed tomato;
text-align: center;
}
#media only screen and (max-width: 500px) {
.item-b {
flex-basis: 100%;
order: 1;
}
}
<div class="flex-container">
<div class="item item-a">a</div>
<div class="item item-b">b</div>
<div class="item item-c">c</div>
<div class="item item-d">d</div>
<div class="item item-e">e</div>
</div>
You can use order and media queries to achieve the results.
* {
box-sizing: border-box;
}
.container {
display: flex;
flex-wrap: wrap;
}
.container > div {
border: solid 1px black;
width: 25%;
}
.item3 {
order: 5;
width: 100%;
flex-shrink: 0;
flex-grow: 1;
}
.item4 {
order: 3;
}
.item5 {
order: 4;
}
#media only screen and (min-width: 600px) {
.container {
flex-wrap: no-wrap;
}
.item3 {
order: 3;
flex-grow: 0;
}
.item4 {
order: 4;
}
.item5 {
order: 5;
}
}
<div class="container">
<div class="item1">Item1</div>
<div class="item2">Item2</div>
<div class="item3">Item3</div>
<div class="item4">Item4</div>
<div class="item5">Item5</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/
I have looked into Flexbox to achieve a responsive layout like pictured below. Unfortunately I still have not figured out how to achieve a desktop layout like Figure 1 which rearranges itself to Figure 2 on viewports smaller than 414 pixel.
Figure 1 (desktop viewports)
Figure 2 (mobile viewports)
(scaled version)
Click here for image in original size
My code so far :
.flexbox {
display: -webkit-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
flex-wrap: wrap;
width: 100%;
margin: 0;
flex-direction: row;
}
.content-flexbox.one {
flex-basis: calc(66% - 1rem);
order: 2;
}
.content-flexbox.two {
flex-basis: calc(30% - 1rem);
order: 1;
}
.content-flexbox.three {
order: 3;
}
.content-flexbox.four {
order: 4;
}
.content-flexbox {
margin: 1rem;
-webkit-box-flex: 1;
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
}
#media only screen and (max-width: 959px) {
.flexbox {
-flex-direction: column;
padding-top: 1rem;
}
.content-flexbox {
margin: 1rem;
flex: 1;
flex-basis: 100%;
}
.content-flexbox.one {
flex-basis: 100%;
order: 1;
}
.content-flexbox.two {
flex-basis: 100%;
order: 2;
}
}
<div class="flexbox">
<div class="content-flexbox one">
<h1 class="posttitle">Lorem ipsum</h1>
<h2 class="subtitle">dolor sit amet</h2>
</div>
<div class="content-flexbox two">
<img src="http://placehold.it/300x300" />
</div>
<div class="content-flexbox three">
<span>Lorem ipsum dolor</span>
</div>
<div id="container-voting" class="content-flexbox four">
<div class="inner-container set">
<span>Lorem ipsum dolor</span>
</div>
<div class="inner-container get">
<span>Lorem ipsum dolor</span>
</div>
</div>
</div>
My question
Is this even possible with flexbox? Is there a better alternative more suited for this layout?
You’re looking for the experimental grid syntax. Flexbox is good for smaller, widget or component layout systems. Grid is for overall page layout, and it’s awesome.
Thing is, grid is only supported in IE, Edge, and the upcoming Safari browsers right now, but Firefox and Chrome support is allegedly just around the corner, and you can start trying it out today by enabling the right developer flag in those browsers.
Here is some sample code, but again, it will only work if your browser supports the new grid syntax.
*{
box-sizing: border-box;
}
.flexbox{
width: 320px;
display: grid;
grid-template-columns: calc(50% - 0.5ch) calc(50% - 0.5ch);
grid-gap: 1ch;
}
.one{
order: 2;
background-color: red;
}
.two{
grid-column: 1 / 3;
order: 1;
background-color: green;
}
.three{
order: 3;
background-color: pink;
}
.four{
display: grid;
grid-column: 1 / 3;
grid-gap: 1ch;
order: 4;
background-color: lavender;
}
.inner-container{
background-color: violet;
}
#media screen and (min-width: 500px){
.flexbox{
width: 500px;
grid-template-columns: calc(33.333% - 0.333ch) calc(33.333% - 0.333ch) calc(33.333% - 0.333ch);
}
.one{
grid-row: 1 / 3;
order: 1;
}
.two{
order: 2;
grid-column: 2 / 4;
}
.three{
order: 3;
}
.four{
grid-column: 3 / 4;
order: 4;
}
}
<div class="flexbox">
<div class="content-flexbox one">
<h1 class="posttitle">Lorem ipsum</h1>
<h2 class="subtitle">dolor sit amet</h2>
</div>
<div class="content-flexbox two">
<img src="http://placehold.it/300x300" />
</div>
<div class="content-flexbox three">
<span>Lorem ipsum dolor</span>
</div>
<div id="container-voting" class="content-flexbox four">
<div class="inner-container set">
<span>Lorem ipsum dolor</span>
</div>
<div class="inner-container get">
<span>Lorem ipsum dolor</span>
</div>
</div>
Although this question explicitly asked for a flexbox approach, there is another way to achive it using simple floats.
A media query allows to rearange the elements in the desired order on viewports less than 414px wide:
.wrap {
background: #d0d0d0;
padding: 1%;
}
.wrap:after {
content: '';
display: block;
clear: both;
}
.el {
float: left;
margin: 1%;
}
.el1 {
width: 31.33%;
padding-bottom: 31.33%;
background: #FF7676;
}
.el2 {
float: right;
width: 64.66%;
padding-bottom: 14.66%;
background: #C2FF76;
}
.el3 {
width: 31.33%;
padding-bottom: 14.66%;
background: #FF9BF7;
}
.el4 {
width: 31.33%;
padding-bottom: 6.33%;
background: #9BA4FF;
}
#media (max-width: 414px) {
.el2, .el4 {
width: 98%;
padding-bottom: 31.33%;
}
.el1, .el3 {
width: 48%;
padding-bottom: 48%;
}
}
<div class="wrap">
<div class="el el2"></div>
<div class="el el1"></div>
<div class="el el3"></div>
<div class="el el4"></div>
<div class="el el4"></div>
</div>
Note that I used padding-bottom to keep the aspect ratio of the elements in this example (more info in this answer).
I don't know what content you intend to put in the blocks but you will need to use absolute positionnig for it if you want to stick with the "padding technique". For plain text content, you can check this fiddle.
The problem is that, if you want to be able to rearrange all items, they must be flex items of the same flex container. But Flexbox does not provide any direct way to make an element occupy more than one flex line.
However, you can use multiple containers and display: contents:
The element itself does not generate any boxes, but its children and
pseudo-elements still generate boxes as normal. For the purposes of
box generation and layout, the element must be treated as if it had
been replaced with its children and pseudo-elements in the document
tree.
/* Desktop */
.container {
display: flex;
flex-wrap: wrap;
}
.container > * {
flex-grow: 1;
}
.item {
margin: 2px;
}
.column {
flex-direction: column;
}
.fill {
width: 100%;
}
/* Mobile */
#media (max-width: 414px) {
.container > .container {
display: contents;
}
.i2 {
order: -1;
}
.i4 {
width: 100%;
}
}
/* Pretty */
.i1 { background: #FF7676; }
.i2 { background: #C2FF76; }
.i3 { background: #FF9BF7; }
.i4 { background: #9BA4FF; }
<div class="container">
<div class="item i1">1</div>
<div class="container">
<div class="item i2 fill">2</div>
<div class="item i3">3</div>
<div class="container column">
<div class="item i4">4a</div>
<div class="item i4">4b</div>
</div>
</div>
</div>
The only problem is that display: contents is not widely supported yet, but you can see it working on Firefox.
I don't think this is possible to do with pure css, but you could use some js and change html structure on resize with wrapAll() and unwrap(). You also need to use media queries to change order and some css when window is < 414px.
$(window).on("resize", function() {
var windowW = $(window).width();
if (windowW < 414) {
if ($('.right, right-inner').length) $('.two, .four').unwrap();
if (!$('.top').length) $('.one, .two, .three').wrapAll('<div class="top"></div>');
} else {
if ($('.top').length) $('.one, .two, .three').unwrap();
if (!$('.right, .right-inner').length) {
$('.three, .four').wrapAll('<div class="right-inner"></div>');
$('.two, .right-inner').wrapAll('<div class="right"></div>');
}
}
}).resize();
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body,
html {
margin: 0;
padding: 0;
font-family: sans-serif;
}
.flexbox {
display: flex;
min-height: 100vh;
color: white;
font-size: 50px;
}
.one {
flex: 1;
background: #FF7676;
margin: 10px;
}
.right {
flex: 2;
display: flex;
flex-direction: column;
margin: 10px;
}
.two {
height: 40%;
display: flex;
margin-bottom: 20px;
margin-right: 10px;
}
.two img {
width: 100%;
margin: 0;
}
.right-inner {
display: flex;
flex: 2;
}
.three,
.four {
flex: 1;
}
.three {
background: #FF9BF7;
margin-right: 10px;
}
.four {
display: flex;
flex-direction: column;
}
.set,
.get {
background: #9BA4FF;
flex: 1;
margin: 5px;
}
.set {
margin-top: 0;
}
.get {
margin-bottom: 0;
}
#media(max-width: 414px) {
.flexbox {
flex-direction: column;
}
.flexbox > * {
flex: 1;
margin: 10px;
}
.get,
.set {
margin: 0;
margin-bottom: 10px;
}
.two {
order: -1;
flex: 0 0 100%;
margin-bottom: 0;
}
.two img {
height: 100px;
}
.one,
.three {
width: 50%;
margin: 0;
}
.one {
margin-right: 10px;
}
.top {
display: flex;
flex-wrap: wrap;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<div class="flexbox">
<div class="content-flexbox one">
<span class="posttitle">1</span>
</div>
<div class="right">
<div class="content-flexbox two">
<img src="http://placehold.it/300x300/C2FF76" />
</div>
<div class="right-inner">
<div class="content-flexbox three">
<span>3</span>
</div>
<div id="container-voting" class="content-flexbox four">
<div class="inner-container set">
<span>4a</span>
</div>
<div class="inner-container get">
<span>4b</span>
</div>
</div>
</div>
</div>
</div>
I see that you can make two containers with floats and like mentioned before use liquid style page with width %. If you aproche mobile viewport use media querys to declair breakpoints.