Flexbox nested columns - css

I am trying to nest some flexbox columns inside a flexbox.
I have this HTML:
<div class="container">
<div class="row flex height">
<div class="col-md-6 red">
</div>
<div class="col-md-6 orange">
<div class="flex flex-columns">
<div class="row black flex">
<div class="col-md-3 yellow">
</div>
<div class="col-md-9 green">
</div>
</div>
<div class="row white flex">
<div class="col-md-6 blue">
</div>
<div class="col-md-6 indigo">
</div>
</div>
</div>
</div>
</div>
</div>
and my CSS is like this:
.container {
border: 1 px solid pink;
}
.height {
min-height: 500px;
}
.flex {
box-sizing: border-box;
display: flex;
}
.flex-columns {
display: flex;
flex-direction: column;
}
.row {
flex: 1;
}
.red {
background-color: red;
}
.orange {
background-color: orange;
}
.yellow {
background-color: yellow;
}
.green {
background-color: green;
}
.blue {
background-color: blue;
}
.indigo {
background-color: indigo;
}
.violet {
background-color: violet;
}
.black {
background-color: black;
}
.white {
background-color: pink;
}
Here is a diagram illustrating what I am trying to achieve:
and here is my codepen: http://codepen.io/r3plica/pen/PqWqKx?editors=110
Hopefully you can understand what I am trying to do, but I can't get it to work properly.
Can anyone help?

If I understand it well, you want
.flex-columns {
display: flex;
flex-direction: row;
}
.row {
flex: 1;
}
#import '//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css';
.flex {
min-height: 500px;
box-sizing: border-box;
display: flex;
}
.flex-columns {
box-sizing: border-box;
display: flex;
align-content: stretch;
}
.row {
flex: 1;
margin: 0; /* Remove stupid bootstrap margins */
}
.red { background-color: red; }
.orange { background-color: orange; }
.yellow { background-color: yellow; }
.green { background-color: blue; }
.blue { background-color: orange; }
.indigo { background-color: indigo; }
.violet { background-color: violet; }
.black { background-color: black; }
.white { background-color: white; }
<div class="container">
<div class="row flex">
<div class="col-md-6 red">
</div>
<div class="col-md-6 orange">
<div class="flex flex-columns">
<div class="row black"></div>
<div class="row violet"></div>
</div>
</div>
</div>
</div>

I modified your HTML and CSS to make the results fit the image (colors notwithstanding).
Added a padding to every div
Added flex-grow to some of the flex-items, to make them fill their parents (by adding the row class to them)
Removed div.flex.flex-columns and change its classes to its parent, so it changes to div.col-md-6.orange.flex.flex-columns. It's superflous and messing your layout.
Modify the flex-grows of the purple divs (in the image) to change their ratios
You can run the following snippet to see the results.
The inner divs still need some padding to really mimic the image, but I'm guessing that's not the main point of your question.
.container {
border: 1px solid pink;
}
div {
padding: 10px;
}
.height {
min-height: 500px;
}
.flex {
box-sizing: border-box;
display: flex;
}
.flex-columns {
display: flex;
flex-direction: column;
}
.row {
flex: 1;
}
.red {
background-color: red;
}
.orange {
background-color: orange;
}
.yellow {
background-color: yellow;
flex-grow: 2;
}
.green {
background-color: green;
flex-grow: 3;
}
.blue {
background-color: blue;
flex-grow: 3;
}
.indigo {
background-color: indigo;
flex-grow: 2;
}
.violet {
background-color: violet;
}
.black {
background-color: black;
}
.white {
background-color: pink;
}
<div class="container">
<div class="row flex height">
<div class="col-md-6 red row"></div>
<div class="col-md-6 orange row flex flex-columns">
<div class="row black flex">
<div class="col-md-3 yellow row"></div>
<div class="col-md-9 green row"></div>
</div>
<div class="row white flex">
<div class="col-md-6 blue row"></div>
<div class="col-md-6 indigo row"></div>
</div>
</div>
</div>
</div>

your .flex-column shouldn't have a flex-direction set:
.flex-columns {
box-sizing: border-box;
display: flex;
/* flex-direction: column; */
align-content: stretch;
}
add the following to your css:
.flex-columns > .row{
flex: 1 0 auto;
margin: 0; /* this is to reset the column padding/margins added by bootstrap */
}
forked pen - http://codepen.io/braican/pen/PqWqvr
#import '//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css';
.flex {
min-height: 500px;
box-sizing: border-box;
display: flex;
}
.flex-columns {
box-sizing: border-box;
display: flex;
/* flex-direction: column; */
align-content: stretch;
}
.flex-columns > .row{
flex: 1 0 auto;
margin: 0;
}
.red {
background-color: red;
}
.orange {
background-color: orange;
}
.yellow {
background-color: yellow;
}
.green {
background-color: blue;
}
.blue {
background-color: orange;
}
.indigo {
background-color: indigo;
}
.violet {
background-color: violet;
}
.black {
background-color: black;
}
.white {
background-color: white;
}
<div class="container">
<div class="row flex">
<div class="col-md-6 red">
</div>
<div class="col-md-6 orange">
<div class="flex flex-columns">
<div class="row black">
</div>
<div class="row white">
</div>
</div>
</div>
</div>
</div>

Related

Have child span the full height of a growing flex item

EDIT: This may be a problem with Safari 14.0.x for macOS.
I’m trying to make the .block element in the middle .flex-item span the full height of its parent, but it instead just collapses.
body {
height: calc(100vh - 2 * 4px);
margin: 4px;
}
div {
box-sizing: border-box;
border-width: 0.8vh;
border-style: solid;
padding: 2vh;
}
.flex {
height: 100%;
border-color: red;
display: flex;
flex-direction: column;
}
.flex-item {
border-color: blue;
}
.box {
height: 15vh;
border-color: green;
padding: 0;
}
.flex-item:last-child > .box {
height: 8vh;
}
.grow {
flex-grow: 1;
}
.grow > .box {
height: 100%;
}
<div class="flex">
<div class="flex-item">
<div class="box"></div>
</div>
<div class="flex-item grow">
<div class="box two"></div>
</div>
<div class="flex-item">
<div class="box"></div>
</div>
</div>
I could edit the last of the code to what’s below to make it work, but I’d rather not have one child be displayed as flex while the others are displayed as block. Is there another way I could go about doing this?
.grow {
flex-grow: 1;
display: flex;
flex-direction: column;
}
.grow > .box {
flex-grow: 1;
}
body {
height: calc(100vh - 2 * 4px);
margin: 4px;
}
div {
box-sizing: border-box;
border-width: 0.8vh;
border-style: solid;
padding: 2vh;
}
.flex {
height: 100%;
border-color: red;
display: flex;
flex-direction: column;
}
.flex-item {
border-color: blue;
}
.box {
height: 15vh;
border-color: green;
padding: 0;
}
.flex-item:last-child > .box {
height: 8vh;
}
.grow {
flex-grow: 1;
display: flex;
flex-direction: column;
}
.grow > .box {
flex-grow: 1;
}
<div class="flex">
<div class="flex-item">
<div class="box"></div>
</div>
<div class="flex-item grow">
<div class="box"></div>
</div>
<div class="flex-item">
<div class="box"></div>
</div>
</div>
You could set it as follow:
.grow {
flex-grow: 1;
height: 100%;
}
.grow > .box {
height: 100%;
}
This does seem to the trick for me in Safari.
If you don't want to use flexbox on the .grow element.

row / column disposal in CSS

I want to use CSS to have a header part a the top and blue, yellow and green parts at the bottom but aligned from left to right, like the following image:
But I can't adjust Blue - Yellow - Green as I want.
I tried the following code:
.container {
width: 100%;
height: 300px;
display: flex;
flex-direction: column;
}
.header {
flex: 1;
background-color: brown;
}
.group {
flex: 5;
background-color: grey;
flex-direction: row;
}
.blue {
flex: 1;
background-color: blue;
}
.yellow {
flex: 3;
background-color: yellow;
}
.green {
flex: 1;
background-color: green;
}
<div class="container">
<div class="header">
<h3>header</h3>
</div>
<div class="group">
<div class="blue">
<h3>blue</h3>
</div>
<div class="yellow">
<h3>yellow</h3>
</div>
<div class="green">
<h3>green</h3>
</div>
</div>
</div>
If you want the lower row to contract and expand but not wrap, you could do this:
<html>
<head>
<style>
.container {
width: 100%;
height: 300px;
display: flex;
flex-direction: column;
}
.header {
display:inline-block;
flex: 1;
background-color: brown;
}
.group {
text-align:center;
flex: 5;
background-color: grey;
flex-direction: row;
}
.blue {
display:inline-block;
flex: 1;
width:33%;
background-color: blue;
}
.yellow {
display:inline-block;
flex: 3;
width:32%;
background-color: yellow;
}
.green {
display:inline-block;
flex: 1;
width:31%;
background-color: green;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h3>header</h3>
</div>
<div class="group">
<div class="blue">
<h3>blue</h3>
</div>
<div class="yellow">
<h3>yellow</h3>
</div>
<div class="green">
<h3>green</h3>
</div>
</div>
</div>
</body>
</html>

Wrap children content respectively to main parent width

I wonder if there is a flex-way to create fluid like behaviour of the parent container: by moving red boxes n1 and n2 to the left of the blue box n3 and as a result moving the red box n3 to the left side of the container
.parent {
display: flex;
width: 525px;
flex-wrap: wrap;
background-color: green;
}
.child {
flex-wrap: wrap;
display: flex;
}
.box {
width: 100px;
height: 100px;
margin: 5px;
}
.blue .box {
background-color: blue;
}
.red .box {
background-color: red;
}
<div class='parent'>
<div class='child blue'>
<div class='box'>1</div>
<div class='box'>2</div>
<div class='box'>3</div>
</div>
<div class='child red'>
<div class='box'>1</div>
<div class='box'>2</div>
<div class='box'>3</div>
</div>
</div>
You can use display:contents (https://caniuse.com/#feat=css-display-contents) on .child elements making the boxes behaving as they was child of the .parent element.
.parent {
display: flex;
width: 555px;
flex-wrap: wrap;
background-color: green;
}
.child {
flex-wrap: wrap;
display: flex;
display:contents
}
.box {
width: 100px;
height: 100px;
margin: 5px;
}
.blue .box {
background-color: blue;
}
.red .box {
background-color: red;
}
<div class='parent'>
<div class='child blue'>
<div class='box'>1</div>
<div class='box'>2</div>
<div class='box'>3</div>
</div>
<div class='child red'>
<div class='box'>1</div>
<div class='box'>2</div>
<div class='box'>3</div>
</div>
</div>

ie 11: flex grow parent issue

I have such code:
https://plnkr.co/edit/ZAEzfAOCO0ZcSq2OR4Lp?p=preview
but this isn't working in ie, until I add height:0 (it's a very bad idea on parent element)
<body>
<div class="container">
<div class="container-item container-item-1"></div>
<div class="container-item container-item-2"></div>
<div class="container-item container-item-3"></div>
</div>
</body>
body, html {
min-height: 100%;
height: 100%;
}
.container {
width: 100%;
min-height: calc(100% - 80px);
margin: 30px;
padding: 20px;
border: 1px solid gray;
border-radius: 16px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1;
}
.container-item {
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1;
content: "someText";
border-bottom: 1px solid #cecece;
}
.container-item-1 {
background-color: red;
}
.container-item-2 {
background-color: orange;
}
.container-item-3 {
background-color: green;
}
everything works fine in chrome and ff
(my parents should expand to fit parent)
Important!
I need a flexible solution, my code can have a lot of nested div's (not a constant value) between body and content divs.
for example:
<body>
<div>
<div>
<div class="container">
<div class="container-item container-item-1"></div>
<div class="container-item container-item-2"></div>
<div class="container-item container-item-3"></div>
</div>
</div>
</div>
</body>
or
<body>
<div>
<h3>text</h3>
<div class="container">
<div class="container-item container-item-1"></div>
<div class="container-item container-item-2"></div>
<div class="container-item container-item-3"></div>
</div>
</div>
</body>
If you have an unknown or nested markup before the container, you could add an extra wrapper within it (here inner), to overcome IE's min-height bug.
Fiddle sample 1 -- Fiddle sample 2
Stack snippet sample 1
html, body {
margin: 0;
}
.container {
display: flex;
}
.container .inner {
width: 100%;
min-height: calc(100vh - 100px);
margin: 30px;
padding: 20px;
border: 1px solid gray;
border-radius: 16px;
display: flex;
flex-direction: column;
}
.container-item {
flex-grow: 1;
border: 1px solid #cecece;
}
.container-item-1 {
background-color: red;
}
.container-item-2 {
background-color: orange;
}
.container-item-3 {
background-color: green;
}
<div>
<h3>text</h3>
<div class="container">
<div class="inner">
<div class="container-item container-item-1">
</div>
<div class="container-item container-item-2">
</div>
<div class="container-item container-item-3">
</div>
</div>
</div>
</div>
Stack snippet sample 2
html, body {
margin: 0;
}
.container {
display: flex;
}
.container .inner {
width: 100%;
min-height: calc(100vh - 100px);
margin: 30px;
padding: 20px;
border: 1px solid gray;
border-radius: 16px;
display: flex;
flex-direction: column;
}
.container-item {
flex-grow: 1;
border: 1px solid #cecece;
}
.container-item-1 {
background-color: red;
}
.container-item-2 {
background-color: orange;
}
.container-item-3 {
background-color: green;
}
<div>
<div>
<div class="container">
<div class="inner">
<div class="container-item container-item-1">
</div>
<div class="container-item container-item-2">
</div>
<div class="container-item container-item-3">
</div>
</div>
</div>
</div>
</div>

How to position at the center one element with display flex

I have container with div elemenents
.container {
display: flex;
justify-content: space-between;
}
How to make one element positioned at the center on this block, and others to be space-between.
.container {
display: flex;
justify-content: space-between;
}
.container div {
height: 50px;
}
.one,
.four,
.seven {
background-color: red;
width: 200px;
}
.two,
.six {
background-color: green;
width: 100px;
}
.three,
.five {
background-color: yellow;
width: 150px;
}
.center {
width: 300px;
background-color: black;
}
<div class="container">
<div class="one"></div>
<div class="two"></div>
<div class="three"></div>
<div class="center"></div>
<div class="four"></div>
<div class="five"></div>
<div class="six"></div>
<div class="seven"></div>
</div>
jsFiddle
Based on how dynamic you want this to be, here is a suggestion where the items on the left and on the right side of the center element are wrapped.
The left and right get 50% each minus the width of the center (150px for each side), which will put the center in the middle.
Updated fiddle
Stack snippet
.container {
display: flex;
justify-content: space-between;
}
.container div {
height: 50px;
}
.left, .right {
display: flex;
justify-content: space-between;
flex-basis: calc(50% - 150px);
}
.one,
.four,
.seven {
background-color: red;
flex-basis: 200px;
}
.two,
.six {
background-color: green;
flex-basis: 100px;
}
.three,
.five {
background-color: yellow;
flex-basis: 150px;
}
.center {
flex-basis: 300px;
background-color: black;
}
<div class="container">
<div class="left">
<div class="one">
</div>
<div class="two">
</div>
<div class="three">
</div>
</div>
<div class="center">
</div>
<div class="right">
<div class="four">
</div>
<div class="five">
</div>
<div class="six">
</div>
<div class="seven">
</div>
</div>
</div>
By adding a pseudo to each side wrapper, we can also make it behave similar to how space-between work without the wrappers (though still with center centered).
In this fiddle demo (and below Stack snippet) I changed the width's so one easier can see how it behaves in full screen.
.container {
display: flex;
justify-content: space-between;
}
.container div {
height: 50px;
}
.left, .right {
display: flex;
justify-content: space-between;
flex-basis: calc(50% - 100px);
}
.left::after,
.right::before {
content: '';
}
.one,
.four,
.seven {
background-color: red;
flex-basis: 125px;
}
.two,
.six {
background-color: green;
flex-basis: 25px;
}
.three,
.five {
background-color: yellow;
flex-basis: 75px;
}
.center {
flex-basis: 200px;
background-color: black;
}
<div class="container">
<div class="left">
<div class="one">
</div>
<div class="two">
</div>
<div class="three">
</div>
</div>
<div class="center">
</div>
<div class="right">
<div class="four">
</div>
<div class="five">
</div>
<div class="six">
</div>
<div class="seven">
</div>
</div>
</div>

Resources