CSS Flexbox 2 columns with different heights - html

I have the following code:
.wrapper {
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
.a {
background-color: red;
width: 65%;
}
.b {
background-color: green;
width: 35%;
}
.c {
background-color: blue;
width: 65%;
height: 100px;
}
.d {
background-color: orange;
width: 35%;
}
.e {
background-color: teal;
width: 65%;
}
.f {
background-color: purple;
width: 35%;
}
<div class="wrapper container">
<div class="a">A</div>
<div class="b">B</div>
<div class="c">C</div>
<div class="d">D</div>
<div class="e">E</div>
<div class="f">F</div>
</div>
I am trying to make the F be right under D, like this:
The main reason I am doing this instead of 2 separate columns is because I want to be able to arrange the columns in mobile later by using order. Is this possible in Flexbox, or is there another way?

In order for a flex column to wrap, you need to define a fixed height on the container. Otherwise, without a breakpoint, the column has no reason to wrap. It will simply expand the container as a single column.
This problem is explained in more detail here:
Is it possible for flex items to align tightly to the items above them?
You're probably better off with a grid solution.
.wrapper {
display: grid;
grid-template-columns: 65% 35%;
grid-template-areas: " a b "
" c d "
" c f "
" c . "
" c . "
" e . " ;}
.a { grid-area: a; background-color: red; }
.b { grid-area: b; background-color: green; }
.c { grid-area: c; background-color: blue; height: 100px; }
.d { grid-area: d; background-color: orange; }
.e { grid-area: e; background-color: teal; }
.f { grid-area: f; background-color: purple; }
<div class="wrapper">
<div class="a">A</div>
<div class="b">B</div>
<div class="c">C</div>
<div class="d">D</div>
<div class="e">E</div>
<div class="f">F</div>
</div>
Browser support is now pretty strong for CSS Grid.
Also, the order property works in both Grid and Flex layouts. But you may not need order in Grid to re-arrange your layout for mobile screens. You can simply use grid properties.

Inspired from Easy-Masonry-Layout-With-Flexbox
Seems to do the job for me
<div id="masonry">
<img src="irina.jpg" alt>
<img src="daniella.jpg" alt>
<img src="karina.jpg" alt>
…
</div>
div#masonry {
display: -ms-flexbox;
-ms-flex-direction: column;
-ms-flex-wrap: wrap;
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 100vw;
font-size: 0;
}
div#masonry img {
width: 33.3%;
transition: .8s opacity;
}

Related

How can I make a div span 2 rows [duplicate]

This question already has answers here:
Make a div span two rows in a grid
(2 answers)
Closed 6 months ago.
I am trying to do exactly this:
Where my mark up is:
<div>
<div>A</div>
<div>B</div>
<div>C</div>
</div>
Is this possible with grid, bootstrap or flex? Without changing the order of elements?
I think it has a lot of way to do.
And one of that way is using grid. then use grid-template for solve this question
.container {
display: grid;
grid-template:
"a b"
"c b";
}
.a {
grid-area: a;
background: red;
}
.b {
grid-area: b;
background: blue;
}
.c {
grid-area: c;
background: green;
}
or using grid-area
.container {
display: grid;
}
.a {
background: red;
}
.b {
grid-area: 1 / 2 / 3;
background: blue;
}
.c {
background: green;
}
.wrapper {
height: 300px;
display: grid;
grid-template-columns: repeat(2, 50%);
}
.wrapper div {
color: white;
display: flex;
align-items: center;
justify-content: center;
}
.wrapper div:nth-child(1) {
background-color: green;
}
.wrapper div:nth-child(2) {
grid-row: 2 span;
background-color: blue;
}
.wrapper div:nth-child(3) {
background-color: red;
}
<div class="wrapper">
<div>A</div>
<div>B</div>
<div>C</div>
</div>
Is that something you wanted to achive ? "Grid" is kind of made for this kind of situations.
As for bootstrap - last version uses "flex" as default.
Using one more div will be the solution, do the following.
Hope it is useful.
https://codepen.io/Olmedo12/pen/WNdGOMB
HTML
<div class="container">
<div class="subcontainer">
<div class="box blue">BOX 1</div>
<div class="box red">BOX 3</div>
</div>
<div class="box green">
Box 2
</div>
<div>
CSS
.container {
display: flex;
}
.box {
width: 60px;
height: auto;
}
.red {
background: red;
}
.blue {
background: blue;
}
.green {
background: green;
}

aligning css grids in one line [duplicate]

This question already has an answer here:
Why are CSS named grid areas not in quotes?
(1 answer)
Closed 7 months ago.
I'm trying to create a grid layout with two boxes that I want to be in one line.
the result was :
.container {
display: grid;
grid-template-areas: "1 2 2";
}
.sidebar {
background-color: aqua;
grid-area: 1;
height: 50vh;
}
.content {
background-color: black;
grid-area: 2;
height: 50vh;
}
<div class="container">
<div class="sidebar"></div>
<div class="content"></div>
</div>
why it doesn't follow the template I designated
If you want to use numbers you need to prefix them with \3 but I don't really recommend
.container {
display: grid;
grid-template-areas: "1 2 2";
}
.sidebar {
background-color: aqua;
grid-area: \31;
height: 50vh;
}
.content {
background-color: black;
grid-area: \32;
height: 50vh;
}
<div class="container">
<div class="sidebar"></div>
<div class="content"></div>
</div>
I don't believe you can use unescaped numbers as grid area names.
Just use letters instead.
.container {
display: grid;
grid-template-areas: "a b b"
}
.sidebar {
background-color: aqua;
grid-area: a;
height: 50vh;
}
.content {
background-color: black;
grid-area: b;
height: 50vh;
}
<div class="container">
<div class="sidebar">
</div>
<div class="content"></div>
</div>

Prevent next row taking up height of tallest item in previous row with flexbox?

I made a layout with flexbox consisting of 2 columns. When everything is the same height it works fine:
https://codepen.io/anon/pen/rJZeJm
<div class="cont">
<div class="a">
A
</div>
<div class="b">B</div>
<div class="c">C</div>
</div>
* {
box-sizing: border-box;
}
.cont {
width: 400px;
background: gold;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
}
.a,
.b,
.c {
width: 45%;
padding: 10px;
}
.a {
background: red;
}
.b {
background: blue;
color: white;
}
.c {
background: orange;
}
However in reality div.b may be taller than div.a, but I don't want the height of div.a or the position of div.c to change:
https://codepen.io/anon/pen/KQxzoz
<div class="cont">
<div class="a">
A
</div>
<div class="b">
B
<br>
More B
</div>
<div class="c">C</div>
</div>
Can I achieve my desired layout with flexbox? Im sure grid could do this but I'm reluctant to use it as its still not properly supported in IE.
Flexbox can't do that by itself in a flexible way.
As you mentioned yourself, CSS Grid can do this, though since you didn't want that, this suggestion is based on the assumption that you at narrower screens want the b to be at the bottom.
By simply initially use float, and then at a certain break point, swap between float and display: flex, it is very easy to take advantage of both.
Additionally, using Flexbox's order property, one can easily position the elements in any desired order, and with this avoid script and get a reasonable level of browser support.
Updated codepen
Stack snippet
* {
box-sizing: border-box;
}
.cont {
background: gold;
overflow: hidden;
}
.a,
.b,
.c {
width: 45%;
padding: 10px;
float: left;
}
.a {
background: red;
}
.b {
background: blue;
color: white;
float: right;
}
.c {
background: orange;
}
#media (max-width: 500px) {
.a,
.b,
.c {
width: auto;
float: none;
}
.b {
order: 1;
}
.cont {
display: flex;
flex-direction: column;
}
}
<div class="cont">
<div class="a">
A
</div>
<div class="b">
B
<br>
More B
</div>
<div class="c">C</div>
</div>

Flexbox row with two columns, reordered for narrow screens

I am trying to create a responsive layout using flexbox where one pair of items (two and four) need to be stacked, next to section three when on a large screen, but then on narrow screens, the order needs to change so that they are stacked, one, two, three, four.
I've got a solution, but it isn't DRY, as you can see in the snippet I have duplicated section four.
Is it possible to achieve this using flexbox without the duplication?
.container {
display: flex;
flex-wrap: wrap;
width: 100%;
border: 1px solid red;
}
.section {
border: 1px solid green;
flex-grow: 1;
}
.one, .two, .four {
width: 100%;
}
.sub-container {
display: inline-flex;
flex-direction: column;
width: 50%;
}
.mobile-only {
display: none;
}
#media (max-width: 600px) {
.container {
flex-direction: column;
}
.sub-container {
width: 100%;
}
.section {
width: 100%;
}
.desktop-only {
display: none;
}
.mobile-only {
display: block;
}
}
<div class="container">
<div class="section one">One</div>
<div class="sub-container">
<div class="section two">Two</div>
<div class="section four desktop-only">Four</div>
</div>
<div class="section three">Three</div>
<div class="section four mobile-only">Four</div>
</div>
Flexbox isn't designed for building 2-dimensional grids (where columns and rows can intersect). So for your layout to work using flex properties, you're going to have to hack your way there.
Here's a more complete explanation of the problem:
Is it possible for flex items to align tightly to the items above them?
However, your layout is simple and easy with CSS Grid.
.container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-auto-rows: 50px;
grid-gap: 5px;
grid-template-areas: " one one "
" two three "
" four three ";
}
.one { grid-area: one; }
.two { grid-area: two; }
.three { grid-area: three; }
.four { grid-area: four; }
#media ( max-width: 600px ) {
.container {
grid-template-columns: 1fr;
grid-template-areas: " one "
" two "
" three"
" four ";
}
}
/* non-essential; just for demo */
.section {
border: 1px solid gray;
background-color: lightgreen;
display: flex;
align-items: center;
justify-content: center;
}
<div class="container">
<div class="section one">One</div>
<div class="section two">Two</div>
<div class="section three">Three</div>
<div class="section four">Four</div>
</div>
https://jsfiddle.net/9fyprm3u/
The Grid specification provides multiple methods for designing grids. In this case, I've use the grid-template-areas property which allows you to lay out grid items using ASCII art.
browser support

Changing stack order between different rows flexbox

Goodmorning. I am trying to change the stacking order in a flexbox situation, where there are 2 columns, but the first column contains a spot where the second column needs to be put in between. So when on mobile I need them to be ordered different than source order.
This is on large
col 1 col 2
----------==============
[A] [C]
[B]
Where A and B are in one column, and C is in the other
But on small breakpoint, it needs to be
[A]
[C]
[B]
Is this possible using just Flexbox?
So to clarify. The HTML structure is as such:
row
column
divA
divB
column
divC
Codepen example
.a { background-color: green; }
.b { background-color: red; }
.c { background-color: blue; }
.row {
display: flex;
flex-direction: column;
}
.column {
flex: 1;
}
#media (min-width: 768px) {
.row {
flex-direction: row;
}
}
<div class="row">
<div class="column">
<div class="a">A</div>
<div class="b">B</div>
</div>
<div class="column c">C</div>
</div>
Update
With original html and display: contents allows c to take full height without adding heights when in desktop. Also better solves original problem of how to change order of elements in two separate divs
.a {
background-color: green;
order: 1;
width: 100%;
}
.b {
background-color: red;
order: 3;
width: 100%;
}
.c {
background-color: blue;
order: 2;
}
.row {
width: 100%;
display: flex;
flex-direction: row;
flex-wrap: wrap; /* add this so you don't need the extra wrapper div */
}
.column {
width: 50%; /* start off width children being 50% width */
}
#media (max-width: 768px) {
.column {
width: 100%;
}
.column:first-child {
display: contents;
}
}
<div class="row">
<div class="column">
<div class="a">A</div>
<div class="b">B</div>
</div>
<div class="column c">C</div>
</div>
Original Answer
You can achieve what you want with media queries and order:
.a {
background-color: green;
order: 1;
}
.b {
background-color: red;
order: 3;
}
.c {
background-color: blue;
order: 2;
}
.row {
width: 100%;
display: flex;
flex-direction: row;
flex-wrap: wrap; /* add this so you don't need the extra wrapper div */
}
.row>div {
width: 50%; /* start off width children being 50% width */
}
#media (max-width: 768px) {
.row>div {
/* for small screens */
width: 100%;
}
}
<div class="row">
<div class="a">A</div>
<div class="b">B</div>
<div class="c">C</div>
</div>