Flexbox - two small items next to one large - css

I need to have a layout that looks like this on mobile
-----
| 1 |
-----
| 2 |
-----
| 3 |
-----
And like this on desktop:
---------
| | 1 |
| 2 |---|
| | 3 |
| |----
| |
-----
I decided to use flexbox, my code so far:
<div class="row">
<div class="col-xl secound">2</div>
<div class="col-sm first">1<br>2<br>3<br>4</div>
<div class="col-xl third">3</div>
</div>
.row {
display: flex;
flex-flow: row wrap;
}
.col-sm,
.col-xl {
width: 100%;
}
.col-sm {
background: yellow;
}
.col-xl {
&.secound {
background: #ccc;
}
&.third {
background: #aaa;
}
}
#media (min-width: 700px) {
.col-sm {
width: 25%;
background: yellow;
order: 1;
}
.col-xl {
width: 75%;
&.secound {
background: #ccc;
order: 2;
}
&.third {
background: #aaa;
order: 3;
}
}
}
Unfortunately, I can't slide column "3" under "1". What should I do?
Codepen: http://codepen.io/tomekbuszewski/pen/PbprJP?editors=1100

You can try using float for desktop, and using flexbox with order set for mobile.
jsFiddle
.item-1 {background:aqua;}
.item-2 {background:gold;}
.item-3 {background:pink;}
.row {
overflow: hidden;
}
.item {
width: 50%;
}
.item-2 {
float: left;
}
.item-1,
.item-3 {
overflow: hidden;
}
#media (max-width: 768px) {
.row {
display: flex;
flex-direction: column;
}
.item {
width: auto;
float: none;
}
.item-1 {
order: -1;
}
}
<div class="row">
<div class="item item-2">2<br><br><br></div>
<div class="item item-1">1</div>
<div class="item item-3">3</div>
</div>

You could align .third on the right by using flex property justify-content.
You're CSS would look something like this:
.row{
display: flex;
flex-flow: row wrap;
justify-content: flex-end;
}
.row > div{
flex: 0 0 50%;
}
For changing order you can use the order property:
.first{ order: 1; }
.second{ order: 2; }
.third{ order: 3; }
#media (min-width: 700px){
.first{ order: 2; }
.second{ order: 1; }
.third{ order: 3; }
}
Check the fiddle
On CSS-tricks you can find a great guide for using Flex properties.

There are few things I've given sizes too just for the sake of the demo but it will still work without the sizes.
You will need to give your container a size but that can be 100vh/100vw or even percentage rather than actual pixels.
body {
margin: 0;
}
.container {
display: flex;
flex-wrap: wrap;
flex-direction: column;
height: 600px;
width: 100%;
}
.item-1,
.item-2,
.item-3 {
width: 100%;
font-size: 80px;
color: #fff;
text-align: center;
}
.item-1 {
line-height: 100px;
height: 100px;
background: #00bcd5;
}
.item-2 {
line-height: 200px;
height: 200px;
background: #8bc24a;
}
.item-3 {
line-height: 300px;
height: 300px;
background: #fec107;
}
#media (min-width: 700px) {
.item-1,
.item-2,
.item-3 {
width: 50%;
}
.item-1,
.item-3 {
order: 1;
}
.item-2 {
height: 100%;
line-height: 1em;
}
}
<div class="container">
<div class="item-1">1</div>
<div class="item-2">2</div>
<div class="item-3">3</div>
</div>
Hope this is what you're looking for.

You could use float: right for all three elements instead. Together with the appropriate width definitions in media queries, this should work.

Grid:
/* Column */
.item {
width: 100%;
}
/* Wrap */
.row {
display: flex;
flex-flow: column wrap;
}
/* Responsive */
#media screen and (min-width: 700px){
.row {
flex-flow: row wrap;
justify-content: flex-end;
}
.item { width: 50%;}
.item-1 { order: 2; }
.item-2 { order: 1; }
.item-3 { order: 3; }
}
/* Custom style */
.item {
color: #fff;
display: block;
height: 200px;
text-align: center;
line-height: 200px;
font-size: 3rem;
}
.item-1 {
background: #00bcd5;
}
.item-2 {
background:#8bc24a;
}
.item-3 {
background:#fec107;
}
<div class="row">
<div class="item item-1">1</div>
<div class="item item-2">2</div>
<div class="item item-3">3</div>
</div>
grid with hook:
/* Column */
.item {
width: 100%;
}
/* Wrap */
.row {
display: flex;
flex-flow: column wrap;
}
.sub-row {
display: none;
}
.item-1 { order: 1; }
.item-2 { order: 2; }
.item-3 { order: 3; }
/* Responsive */
#media screen and (min-width: 500px){
.row {
flex-flow: row wrap;
justify-content: flex-end;
}
.sub-row {
width: 50%;
display: flex;
flex-flow: column wrap;
}
.sub-row .item { width: 100%;}
.item { width: 50%;}
.hidden { display: none; }
.item-2 { order: 1; }
.sub-row { order: 2; }
}
/* Custom style */
.item {
color: #fff;
text-align: center;
line-height: 200px;
font-size: 3rem;
}
.item-1 {
background: #00bcd5;
}
.item-2 {
background:#8bc24a;
}
.item-3 {
background:#fec107;
}
<div class="row">
<div class="item item-2">2</div>
<div class="sub-row">
<div class="item item-1">1</div>
<div class="item item-3">3</div>
</div>
<div class="item hidden item-1">1</div>
<div class="item hidden item-3">3</div>
</div>

How about using absolute position?
In your media query change the .row class to this:
.row {
position: relative;
align-items: flex-end;
}
And your .item-2 to:
.item-2 { order: 1; position: absolute; top: 0; left: 0; }
/* Column */
.item {
width: 100%;
}
/* Wrap */
.row {
display: flex;
flex-flow: column wrap;
}
/* Responsive */
#media screen and (min-width: 700px){
.row {
position: relative;
align-items: flex-end;
}
.item { width: 50%;}
.item-1 { order: 2; }
.item-2 { order: 1; position: absolute; top: 0; left: 0; }
.item-3 { order: 3; }
}
/* Custom style */
.item {
color: #fff;
display: block;
text-align: center;
line-height: 200px;
font-size: 3rem;
}
.item-1 {
background: #00bcd5;
}
.item-2 {
background:#8bc24a;
}
.item-3 {
background:#fec107;
}
<div class="row">
<div class="item item-1">1</div>
<div class="item item-2">2
<br>2</div>
<div class="item item-3">3</div>
</div>
Revised Codepen

Related

flex setting items below each other [duplicate]

This question already has answers here:
Is it possible for flex items to align tightly to the items above them?
(5 answers)
Closed 4 years ago.
i'm trying to get to the layout from middle to left as shown in the picture.
How can i make the grey div to push itself up using flex? Should i just use fixed position for it? Thought about changing the html to create container div for the orange and grey boxes, but I want to see how to do it without changing the html.
#import 'general.css';
#import 'reg.css';
#import "768.css" screen and (min-width : 992px);
#import "992.css" screen and (min-width : 1200px);
/*general*/
body, html{
margin: 0;
padding:0;
height: 100%;
}
* {
box-sizing: border-box;
}
/*reg*/
.container{
background-color: red;
text-align: center;
display: flex;
height: 100%;
flex-wrap: wrap;
}
.box{
height: 10%;
width: 100%;
}
header{
background-color: black;
color: white;
width: 100%;
order:1;
}
footer{
background-color: navy;
color: white;
width: 100%;
order:5;
}
.main-content{
background-color: dodgerblue;
height: 60%;
width: 100%;
order:2;
}
.grey{
background-color: grey;
order:4;
}
.orange{
background-color: orangered;
order:3;
}
/*768*/
.box{
height: 11%;
}
.main-content{
height: 67%;
}
.grey{
width: 30%;
order:3;
}
.orange{
background-color: orangered;
width: 70%;
order:4;
}
/*992*/
.main-content{
width: 85%;
order:3;
align-self: flex-end;
height: 80%;
}
.grey{
width: 15%;
order:4;
align-self: flex-start;
height:20% ;
}
.orange{
width:15%;
order:2;
align-self: flex-start;
height: 60%;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="css/index.css">
<title>Document</title>
</head>
<body>
<div class="container">
<header class="box">this is the header</header>
<div class="main-content box">this is main content</div>
<div class="orange box">this is the orange</div>
<div class="grey box">this is the grey</div>
<footer class="box">this is the footer</footer>
</div>
</body>
</html>
I don’t see any solution only using flex because boxes will flow in lines. So as you mentioned, using a positioning for the grey box would be the only way to achieve this.
This is a solution using grid though:
body, html {
height: 100%;
padding:0;
margin: 0;
}
* {
box-sizing: border-box;
}
.container {
display: grid;
grid-template-areas:
"a"
"b"
"c"
"d"
"e";
grid-template-rows: 1fr 60% 1fr 1fr 1fr;
height: 100%;
background-color: red;
}
.box {
display: flex;
justify-content: center;
align-items: center;
}
header {
grid-area: a;
color: white;
background-color: black;
}
.main-content {
grid-area: b;
background-color: dodgerblue;
}
.orange {
grid-area: c;
order: 4;
background-color: orangered;
}
.grey {
grid-area: d;
background-color: grey;
}
footer {
grid-area: e;
color: white;
background-color: navy;
}
#media ( min-width: 768px ) {
.container {
grid-template-areas:
"a a"
"b b"
"d c"
"e e";
grid-template-rows: 15% 4fr 1fr 15%;
grid-template-columns: 15% 1fr;
}
#media ( min-width: 992px ) {
.container {
grid-template-areas:
"a a"
"c b"
"d b"
"e e";
grid-template-rows: 15% 4fr 1fr 15%;
grid-template-columns: 15% 1fr;
}
}
<div class="container">
<header class="box">this is the header</header>
<div class="box main-content">this is main content</div>
<div class="box orange">this is the orange</div>
<div class="box grey">this is the grey</div>
<footer class="box">this is the footer</footer>
</div>
You can use the order style of flex children to affect what order they are rendered inside of a flex parent, however this does require some wrapping divs so you'd have to change your HTML slightly, otherwise you must use CSS grid. Snippet with working example of your images below:
:root {
--min-height: 80px;
}
* {
border-sizing: border-box;
padding: 0;
margin: 0;
}
html, body, .container {
height: 100%;
}
body {
padding: 10px;
}
div {
border-radius: 10px;
}
.container {
display: flex;
flex-direction: column;
}
.container > div {
margin-bottom: 10px;
}
.container > div:last-child {
margin: 0;
}
.main-content > div {
margin-bottom: 10px;
}
.main-content > div:last-child {
margin: 0;
}
.side-content > div {
margin-bottom: 10px;
}
.side-content > div:last-child {
margin: 0;
}
.header, .footer, .content {
min-height: var(--min-height);
}
.teal.content {
min-height: calc(5 * var(--min-height));
}
.black {
background: rgb(30, 32, 42);
}
.teal {
background: rgb(74, 161, 162);
}
.orange {
background: rgb(253, 170, 82);
}
.gray {
background: rgb(203, 187, 172);
}
.navy {
background: rgb(61, 94, 109);
}
#media screen and (min-width: 768px) {
.side-content {
display: flex;
flex-direction: row;
}
.side-content > div {
margin: 0;
}
.side-content > div:last-child {
margin-right: 10px;
}
.orange {
flex: 2 0 auto;
order: 1;
}
.gray {
flex: 1 0 auto;
order: 0;
}
}
#media screen and (min-width: 992px) {
.main-content {
display: flex;
flex-direction: row;
}
.main-content > div {
margin: 0;
}
.main-content > div:last-child {
margin-right: 10px;
}
.side-content {
order: 0;
flex: 1 0 auto;
flex-direction: column;
margin-right: 10px;
}
.side-content > div:last-child {
margin: 0;
}
.side-content > div:first-child {
margin-bottom: 10px;
}
.orange {
order: 0;
margin-bottom: 10px;
}
.teal {
order: 1;
flex: 7 0 auto;
}
}
<div class="container">
<div class="black header"></div>
<div class="main-content">
<div class="teal content"></div>
<div class="side-content">
<div class="orange content"></div>
<div class="gray content"></div>
</div>
</div>
<div class="navy footer"></div>
</div>

Responsive flexbox layout: reordering elements

I'm trying to achieve a responsive layout as outlined in the image, left side would be mobile, right side desktop. This would be relatively easy using flexbox if I could set a fixed height for the wrapper, but because the content is dynamic this is not possible.
Another solution would be to use position absolute on element C, but this seems very hacky, I'm hoping to find a more elegant solution.
Here is a framework for the code:
.wrapper {
display: flex;
flex-direction: column;
}
#media(min-width: 800px) {
.wrapper {
flex-direction: row;
flex-wrap: wrap;
}
}
.section {
display: flex;
justify-content: center;
align-items: center;
font-size: 36px;
}
.section-a {
background: green;
height: 200px;
}
#media(min-width: 800px) {
.section-a {
flex-basis: 33%;
}
}
.section-b {
background: yellow;
height: 400px;
}
#media(min-width: 800px) {
.section-b {
flex-basis: 66%;
}
}
.section-c {
background: blue;
height: 200px;
}
#media(min-width: 800px) {
.section-c {
flex-basis: 33%;
}
}
<div class="wrapper">
<div class="section section-a">A</div>
<div class="section section-b">B</div>
<div class="section section-c">C</div>
</div>
Thanks for the help!
You can achieve this by using grid. I have simplified your code and removed unwanted css
.wrapper {
display: grid;
grid-gap: 10px;
grid-template-columns: 1fr 1fr;
grid-template-rows: [row1-start] auto [row2-start] auto [row2-end];
}
.section {
padding: 20px;
display: flex;
align-items: center;
}
.section-a {
height: 50px;
background-color: green;
}
.section-b {
grid-row: row1-start / row2-end;
grid-column: 2/-1;
background-color: yellow;
}
.section-c {
background-color: blue;
height: 180px;
}
<div class="wrapper">
<div class="section section-a">A</div>
<div class="section section-b">B</div>
<div class="section section-c">C</div>
</div>
Working fiddle here
Edit: it's an attempt, as I misunderstood OP's question. My answer has a given .wrapper height.
A solution using flex with the following properties:
order
flex-basis
This code applies for your desktop layout:
.wrapper {
width: 100%;
height: 100vh;
display: flex;
flex-flow: column wrap;
}
.section {
width: 50%;
border: 1px solid black;
box-sizing: border-box;
}
.section-a {
height: 25vh; // for example
}
.section-b {
order: 3;
flex-basis: 100%;
}
.section-c {
flex-grow: 1;
}
<div class="wrapper">
<div class="section section-a">A</div>
<div class="section section-b">B</div>
<div class="section section-c">C</div>
</div>

Getting correct grid with Flexbox

Can someone point me out how can I get a grid with Flexbox that is similar to the picture below. I have green column already done but have problem doing red section.
The problem is that I need to have an access to Flex Order just re-order it on mobile resolutions.
What I have already:
JSFiddle
HTML
* {
box-sizing: border-box;
}
main,
div {
display: flex;
padding: 1rem;
}
.desktop {
flex-direction: column;
flex-wrap: wrap;
height: 400px;
width: 100%;
}
.desktop div {
flex: 1;
}
div.orange {
background-color: #FFAD77;
width: 30%;
flex: 0 0 50%;
}
div.yellow {
flex: 0 0 100%;
width: 40%;
background-color: #FFE377;
}
div.purple {
flex: 0 0 50%;
width: 30%;
background-color: #FF77C8;
}
div.green {
background-color: green;
width: 30%;
}
#media(max-width: 480px) {
.desktop div {
flex: 1;
width: 100%;
}
div.orange {
order: 1;
}
div.yellow {
order: 2;
}
div.purple {
order: 3;
}
div.green {
order: 2;
}
}
<div class="desktop">
<div class="yellow">lorem1</div>
<div class="orange">lorem2</div>
<div class="purple">lorem3</div>
<div class="green">lorem4</div>
</div>
Please adjust the width, remove border and other things are per your requirement.
.redouter {
height: 200px;
border: 1px solid green;
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
.red {
background: red;
width: 50%;
min-height: 20px;
text-align: center;
color: white;
font-size: 30px;
}
.one {
border: 2px solid white;
}
.two {
border: 5px solid white;
min-height: 150px;
}
.three {
min-height: 144px;
border: 3px solid white;
}
.four {
min-height: 10px;
border: 3px solid white;
}
#media(max-width: 480px) {
.redouter {
height: 100%;
}
.red {
flex: 1;
width: 100%;
}
.one {
order: 1;
}
.two {
order: 2;
}
.three {
order: 3;
}
.four {
order: 2;
}
}
.desktop {
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 300px;
width: 100%;
}
.yellow,
.green,
.purple,
.orange {
flex: 1;
}
div.orange {
background-color: #FFAD77;
width: 30%;
flex: 0 0 50%;
}
div.yellow {
flex: 0 0 100%;
width: 40%;
background-color: #FFE377;
}
div.purple {
flex: 0 0 50%;
width: 30%;
background-color: #FF77C8;
}
div.green {
background-color: green;
width: 30%;
}
#media(max-width: 480px) {
.desktop div {
flex: 1;
width: 100%;
}
div[orange] {
order: -1;
flex: 2;
}
div[yellow] {
flex: 5;
}
div[purple] {
flex: 1;
}
div[purple] {
flex: 6;
}
}
<div class="desktop">
<div class="yellow">lorem 1</div>
<div class="orange">lorem 2</div>
<div class="purple">lorem 3</div>
<div class="green">lorem 4</div>
</div>
<div class="redouter">
<div class="red one">1</div>
<div class="red two">2</div>
<div class="red three">3</div>
<div class="red four">4</div>
</div>

CSS Flexbox: how to change the width of the element

I'm using Flexbox in CSS. In the next link, you can see three squares lying one above the other: http://codepen.io/CrazySynthax/pen/PbLjMO
The first square is the smallest and the last square is the biggest. My question is how to draw these squares that their height will be identical, but their width will differ, so they will look like this:
---
------
---------
This is the code:
<div class="container">
<div class="square"> </div>
<div class="square"> </div>
<div class="square"> </div>
</div>
html, body {
width: 100%;
height: 100%;
margin:0;
padding:0;
displax: flex;
}
.container{
height: 100%;
width: 100%;
display: flex;
flex-flow:column wrap;
justify-content:space-around;
}
.square {
flex:1 1 auto;
background-color:gray;
border:solid;
margin: 1em;
}
.square:nth-child(1) {
flex-grow: 1
}
.square:nth-child(2) {
flex-grow: 2
}
.square:nth-child(3) {
flex-grow: 5
}
Add a class to each div with desired width & leave flex-grows in 1 to maintain same height:
html, body {
width: 100%;
height: 100%;
margin:0;
padding:0;
displax: flex;
}
.container{
height: 100%;
width: 100%;
display: flex;
flex-flow:column wrap;
justify-content:space-around;
}
.square {
flex:1 1 auto;
background-color:gray;
border:solid;
margin: 1em;
width: 200px
}
.square:nth-child(1) {
flex-grow: 1;
}
.square:nth-child(2) {
flex-grow: 1;
}
.square:nth-child(3) {
flex-grow: 1;
}
/*added classes*/
.one {
width: 150px;
}
.two {
width: 250px;
}
.three {
width: 350px;
}
#media (max-width: 350px) {
.one {
width: auto;
}
.two {
width: auto;
}
.three {
width: auto;
}
}
<div class="container">
<div class="square one"></div>
<div class="square two"></div>
<div class="square three"></div>
</div>
EDIT: For responsive beyond 350px or whatever add a #media query (make sure it's set at the end of the CSS sheet or later than the custom width .one .two & .three):
Test resizing window on external JSFiddle
#media (max-width: 350px) {
.one {
width: auto;
}
.two {
width: auto;
}
.three {
width: auto;
}
}

Writing flexbox code for 2-column and 3-column on desktop and mobile (wrap)

I'm having a real hard time figuring out this CSS flexbox solution. Basically there are 2 issues, one with a 2-column and another with a 3-column layout.
2-Column:
This, I think, may be pretty straightforward:
3-Column:
This is probably a bit more advanced:
The container class is, well, .container, and the children are just .left, .right, and .middle. Not sure if it's relevant, but the width of .container is 100% of viewport. I should probably add that using Bootstrap is not possible, due to reasons out of my control.
Here's how you do it for the three columns. I'm only adding that, because it's a bit more tricky:
.container {
display: flex;
flex-wrap: wrap;
flex-direction: row;
justify-content: flex-start;
align-items: stretch;
}
.left {
order: 1;
background: red;
flex-basis: 100%;
height: 300px
}
.middle {
order: 3;
background: green;
flex-basis: 100%;
height: 300px;
}
.right {
order: 2;
background: yellow;
flex-basis: 100%;
height: 300px;
}
#media screen and (min-width:600px) {
.container {
flex-wrap: nowrap;
}
.left {
flex-basis: 200px;
order: 1;
}
.middle {
flex-basis: 1;
order: 2;
}
.right {
flex-basis: 200px;
order: 3;
}
}
<div class="container">
<div class="left"></div>
<div class="middle"></div>
<div class="right"></div>
</div>
And the fiddle http://jsfiddle.net/2touox81/
As you can see, you can set column order for flex items.
Hope this helps.
I will assume desktop means screen wider than 600px, mobile less.
The 2-column layout is very simple:
body {
display: flex; /* Magic begins */
flex-wrap: wrap; /* Allow multiple lines */
}
#left, #right {
flex: 1 300px; /* Initial width of 600px/2
Grow to fill remaining space */
min-width: 0; /* No minimal width */
}
body {
display: flex;
flex-wrap: wrap;
text-align: center;
font-weight: bold;
}
#left, #right {
flex: 1 300px;
min-width: 0;
background: #f55;
padding: 15px 0;
}
#right {
background: #57f;
}
<div id="left">Left</div>
<div id="right">Right</div>
The 3-column is only a bit more complex:
body {
display: flex; /* Magic begins */
}
#left, #right, #middle {
min-width: 0; /* No minimal width */
}
#left, #right {
flex-basis: 200px; /* Initial width */
}
#middle {
flex: 1; /* Take up remaining space */
}
#media screen and (max-width: 600px) { /* Mobile */
body {
flex-direction: column; /* Column layout */
}
#left, #right {
flex-basis: auto; /* Unset previous 200px */
}
#middle {
order: 1; /* Move to the end */
}
}
body {
display: flex;
text-align: center;
font-weight: bold;
}
#left, #right, #middle {
min-width: 0;
padding: 15px 0;
}
#left, #right {
flex-basis: 200px;
background: #f55;
}
#right {
background: #57f;
}
#middle {
flex: 1;
background: #5f6;
}
#media screen and (max-width: 600px) {
body {
flex-direction: column;
}
#left, #right {
flex-basis: auto;
}
#middle {
order: 1;
}
}
<div id="left">Left</div>
<div id="middle">Middle</div>
<div id="right">Right</div>

Resources