Flexbox based table - html

I want to build a table with multiple columns with dynamic data. This leads to inability to use base <table> since it would change its columns width when content changes. Also I need to implement an option to hide some columns via JS.
Therefore I've decided to build a flexbox based table. However, I struggle with how to deal with column width when I hide some columns.
For example I have next table
.table {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
width: 100%;
min-height: 200px;
}
.row {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.table-head {
color: #a4a;
font-weight: 500;
}
.table-cell {
padding: 10px;
flex-grow: 1;
width: 100%;
overflow: hidden;
}
.table-cell:nth-child(1) {
width: 20%;
}
.table-cell:nth-child(2) {
width: 10%;
}
.table-cell:nth-child(3) {
width: 30%;
}
.table-cell:nth-child(4) {
width: 20%;
}
.table-cell:nth-child(5) {
width: 20%;
}
<div class="table">
<div class="row">
<div class="table-cell table-head">
Name
</div>
<div class="table-cell table-head">
Phone number
</div>
<div class="table-cell table-head">
Email
</div>
<div class="table-cell table-head">
Address
</div>
<div class="table-cell table-head">
Country
</div>
</div>
<div class="row">
<div class="table-cell">Peter</div>
<div class="table-cell">123123</div>
<div class="table-cell">peter#example.com</div>
<div class="table-cell">asdsad</div>
<div class="table-cell">empty</div>
</div>
<div class="row">
<div class="table-cell">Bob</div>
<div class="table-cell">123124</div>
<div class="table-cell">bob#bob.com</div>
<div class="table-cell">sadsads</div>
<div class="table-cell">empty</div>
</div>
</div>
And I want to hide 4th column. Since there some extra space has been created the rest columns should take it and become bigger.
How do I make columns to take their width and have some ratio? For example the address column should be bigger than country column. Also there could be a case when there is only one column left so that it should take 100% width.
I've tried to use flex-grow to make width, however I ended up with the problem that my columns even are not equal (head row had its own proportions and body it own) thus even no table layout when there is no columns hidden.

use flex:1 or 2, 3,... instead of width
.table {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
width: 100%;
min-height: 200px;
}
.row {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.table-head {
color: #a4a;
font-weight: 500;
}
.table-cell {
padding: 10px;
flex:1;
overflow: hidden;
}
.table-cell:nth-child(1) {
flex:3;
}
.table-cell:nth-child(2) {
flex:3;
}
.table-cell:nth-child(3) {
flex:3;
}
.table-cell:nth-child(4) {
flex:6;
}
.table-cell:nth-child(5) {
flex:2;
}
<div class="table">
<div class="row">
<div class="table-cell table-head">
Name
</div>
<div class="table-cell table-head">
Phone number
</div>
<div class="table-cell table-head">
Email
</div>
<div class="table-cell table-head">
Address
</div>
<div class="table-cell table-head">
Country
</div>
</div>
<div class="row">
<div class="table-cell">Peter</div>
<div class="table-cell">123123</div>
<div class="table-cell">peter#example.com</div>
<div class="table-cell">asdsad</div>
<div class="table-cell">empty</div>
</div>
<div class="row">
<div class="table-cell">Bob</div>
<div class="table-cell">123124</div>
<div class="table-cell">bob#bob.com</div>
<div class="table-cell">sadsads</div>
<div class="table-cell">empty</div>
</div>
</div>
i remove fourth table-cell with jquery:
$(document).ready(function(){
$('.table-cell:nth-child(4)').fadeOut(1000);
})
.table {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
width: 100%;
min-height: 200px;
}
.row {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.table-head {
color: #a4a;
font-weight: 500;
}
.table-cell {
padding: 10px;
flex:1;
overflow: hidden;
}
.table-cell:nth-child(1) {
flex:3;
}
.table-cell:nth-child(2) {
flex:3;
}
.table-cell:nth-child(3) {
flex:3;
}
.table-cell:nth-child(4) {
flex:6;
}
.table-cell:nth-child(5) {
flex:2;
}
<div class="table">
<div class="row">
<div class="table-cell table-head">
Name
</div>
<div class="table-cell table-head">
Phone number
</div>
<div class="table-cell table-head">
Email
</div>
<div class="table-cell table-head">
Address
</div>
<div class="table-cell table-head">
Country
</div>
</div>
<div class="row">
<div class="table-cell">Peter</div>
<div class="table-cell">123123</div>
<div class="table-cell">peter#example.com</div>
<div class="table-cell">asdsad</div>
<div class="table-cell">empty</div>
</div>
<div class="row">
<div class="table-cell">Bob</div>
<div class="table-cell">123124</div>
<div class="table-cell">bob#bob.com</div>
<div class="table-cell">sadsads</div>
<div class="table-cell">empty</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>

Related

Flexbox under overflow not taking full width

I've simplified my HTML/CSS in a jsfiddle of what I'm trying to achieve without success.
I cannot make the .problem take full width. The content is represented by the blue background while the box itself is red.
I'm trying to make all the scrollable content have full width and a blue background since I guess the background not appearing after the scrollable content is a problem of width.
What I've taken a look so far:
Flexbox not full width
Flexbox: how to get divs to fill up 100% of the container width without wrapping?
Fill 100% width of scrolling flex container
To clarify: giving .problem a fixed width does give me the effect I want but not the solution since the content is dynamic and I cannot know its width.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
position: relative;
}
html,
body {
width: 100%;
height: 100%;
}
.bg {
display: flex;
background-color: gray;
width: 100%;
height: 100%;
}
.usable {
display: flex;
height: 90%;
width: 100%;
background-color: white;
}
.box {
position: absolute;
top: 0;
left: 0;
height: 200px;
width: 300px;
display: flex;
align-items: flex-start;
align-content: flex-start;
flex-direction: column;
background-color: red;
}
.top {
display: flex;
height: 20px;
background-color: yellow;
width: 100%;
}
.bottom {
width: 100%;
flex: 0 1 100%;
overflow: auto;
}
.contents {
height: 100%;
display: flex;
flex-direction: column;
}
.forms {
flex: 0 1 100%;
}
.problem {
display: flex;
height: 100%;
background-color: blue;
}
.row {
display: flex;
align-items: center;
}
.cell {
align-self: stretch;
flex: 1 0 100px;
}
<div class="bg">
<div class="usable">
<div class="box">
<div class="top">
Top
</div>
<div class="bottom">
<div class="contents">
<div class="forms">
<div class="problem">
<div class="data">
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 00:21:06</div>
<div class="cell">test1</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:42:26</div>
<div class="cell">test2</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:42:26</div>
<div class="cell">test3</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:42:37</div>
<div class="cell">test4</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:42:37</div>
<div class="cell">test5</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:42:37</div>
<div class="cell">test6</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:42:37</div>
<div class="cell">test7</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:42:58</div>
<div class="cell">test8</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:42:58</div>
<div class="cell">test9</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
<div class="row">
<div class="cell">2020-06-28 01:34:46</div>
<div class="cell">2020-08-13 13:43:11</div>
<div class="cell">test10</div>
<div class="cell"></div>
<div class="cell">Basic User</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
The problem is that the container with the blue background is taking the width of the parent and not the content, to solve this you can change its property "display" to "inline-flex".
Then if you change the "flex" property of the .cell class to a "width" property the width you set will count for the parent and it will reach the blue container making it fill all the content.
.problem {
display: inline-flex;
height: 100%;
background-color: blue;
}
.cell {
align-self: stretch;
width: 100px;
}
To allow elements to grow according to content, you can replace 'width' by 'min-width'.
This makes sure your box is a certain size for styling purposes but allows it to grow.
Then you can use 'max-width' to limit the amount it can grow.
So, change 'width: 100%' by 'min-width: 100%'.
You can find more here: https://css-tricks.com/boxes-fill-height-dont-squish/

How do I correctly nest a flexbox to achieve a form layout?

I am looking to achieve the following layout:
Here is how I'm picturing it (with grids):
Black bar is the nav (we can ignore this)
A title and subtitle (purple) - these should be aligned and take up approx 70% of width - I think I've done this
A form which has 3 columns (should take up 70ish percent of the 70%, I don't want inputs to be too wide)
Column 1: Heading + text pairs
Column 2: it will have some icon/character - these must be perfectly aligned
Column 3: Heading + input boxes - these must be the same width
Here is my starting HTML:
.title-container {
display: flex;
justify-content: center;
background: red;
}
.title-item {
flex-basis: 75%;
}
.data-container {
display: flex;
justify-content: center;
background: blue;
}
.column-items {
flex-basis: 70%;
display: flex;
flex-direction: row;
}
.column-1-item {
background: green;
flex-grow: 0.5;
}
.column-2-item {
background: yellow;
flex-grow: 0.1;
align-self: center;
}
.column-3-item {
background: orange;
flex-grow: 1;
}
<div class="title-container">
<div class="title-item">
<h2>Title</h2>
<p>This is some text</p>
</div>
</div>
<div class="data-container">
<div class="column-items">
<div class="column-1-item">
<p>Heading1</p>
<p>SomeText</p>
</div>
<div class="column-2-item">
<p>--></p>
</div>
<div class="column-3-item">
<p>Heading1</p>
<input type="text" name="lname">
</div>
</div>
</div>
I have tried to expand on this, but no matter what I try, I end up further away from my design making me think there is something wrong with my initial design (and flex understanding). If I add additional 'row', it breaks my layout. I also think my data-container is wrongly setup, since this will take up far more space than I want it to
Here is a code pen.
Could someone help get me closer to my design?
I would wrap your entire html in a wrapper class so that you can get the general layout of the page like so:
<div class="wrapper">
<div class="title-container">
<h2>Title</h2>
<p>
Subtitle should be aligned with title
</p>
</div>
<div class="form-container">
<div class="item">
<div class="column">
<p>Heading1</p>
<p>Some Text</p>
</div>
<div class="column">
<p>-></p>
</div>
<div class="column">
<p>Heading1</p>
<p>[ input textfield ]</p>
</div>
</div>
<div class="item">
<div class="column">
<p>Heading3</p>
<p>Some Text</p>
</div>
<div class="column">
<p>-></p>
</div>
<div class="column">
<p>Heading2</p>
<p>[ input textfield ]</p>
</div>
</div>
<div class="item">
<div class="column">
<p>Heading3</p>
<p>Some Text</p>
</div>
<div class="column">
<p>-></p>
</div>
<div class="column">
<p>Heading3</p>
<p>[ input textfield ]</p>
</div>
</div>
<div class="item">
<div class="column"></div>
<div class="column"></div>
<div class="column submit-button">
<p>[ Button ]</p>
</div>
</div>
</div>
</div>
Then you can specify the width for the title-container and form-container with the width property. Making each of the item classes in the form container have a display: flex property lets you format the children column classes to have flex-grow: 1 so they can fill up the available space. The css then looks like:
.wrapper {
display: flex;
flex-direction: column;
align-items: center;
outline: 1px solid red;
}
.title-container {
width: 70%;
outline: 1px solid red;
}
.form-container {
width: 50%;
outline: 1px solid red;
}
.item {
display: flex;
outline: 1px solid red;
}
.column {
/* flex-grow: 1; */
flex: 1 1 0px;
outline: 1px solid red;
}
.submit-button {
display: flex;
align-items: flex-end;
justify-content: flex-end;
}
Alternately you can remove the flex-grow: 1 property from the column class and add justify-content: space-between to the item class to get a result similar to your example.
Here is the codepen.
Your .data-container just needs a flex-direction: column; because you want the .column-items to stack.

Element alignment: Remove margin with modifier class not working

I have a wrapper with two boxes in it. The boxes are each to other. In the boxes there is a title (optional) and a content. I have two cases. First case: One of the boxes has a title the other hasn't. Second case: Both boxes have a title. If you take a look on the example for the second case (both titles), the boxes and titles are aligned on the bottom of the wrapper, and the titles are also aligned. There is also an example for the first case (one box without title). Because of the missing title, the alignment isn't correct yet. Here is a screenshot of the problem:
So what I tried is, to figure out the missing space for the first case, which was 21px. After this I select in CSS the second box and add the missing space. For the second case with both title, I tried to add a modifier class on the box and remove the margin-top. So default there would be a space on the second box if no title (this title is optional) and if both titles are avalable, a class should remove it again. Thats the part of the code:
.box + .box {
margin-top: 21px;
}
.box--with-title {
margin-top: 0;
}
Now with my idea it doesn't work. The first case is solved, but my class is not removing the margin. So now the alignment for the second case is wrong. Any ideas how to solve that the class is removing the margin or is there a bether way to do this with pure CSS? Hope this is clear enough.
.wrapper {
display: flex;
justify-content: space-betweet;
width: 500px;
background-color: lightgray;
;
margin-top: 36px;
}
.box {
display: flex;
flex-direction: column;
width: 50%;
}
.box__content {
width: 120px;
height: 100px;
background-color: lightcoral;
}
.box+.box {
margin-top: 21px;
}
.box--with-title {
margin-top: 0;
}
<div class="wrapper">
<div class="box">
<h3>I have a title!</h3>
<div class="box__content"></div>
</div>
<div class="box">
<h3></h3>
<div class="box__content"></div>
</div>
</div>
<div class="wrapper">
<div class="box">
<h3>I have a title!</h3>
<div class="box__content"></div>
</div>
<div class="box box--with-title">
<h3>I have also a title!</h3>
<div class="box__content"></div>
</div>
</div>
Simply use align-items:flex-end on the container and no need to consider margin:
flex-end
The cross-end margin edge of the flex item is flushed with
the cross-end edge of the line. ref
.wrapper {
display: flex;
justify-content: space-between;
align-items:flex-end;
width: 500px;
background-color: lightgray;
;
margin-top: 36px;
}
.box {
display: flex;
flex-direction: column;
width: 50%;
}
.box__content {
width: 120px;
height: 100px;
background-color: lightcoral;
}
<div class="wrapper">
<div class="box">
<h3>I have a title!</h3>
<div class="box__content"></div>
</div>
<div class="box">
<div class="box__content"></div>
</div>
</div>
<div class="wrapper">
<div class="box">
<h3>I have a title!</h3>
<div class="box__content"></div>
</div>
<div class="box box--with-title">
<h3>I have also a title!</h3>
<div class="box__content"></div>
</div>
</div>
By the way your intial code was almost good, you are simply facing a specificity issue which make the rule of .box--with-title not being considered. You may do something like this instead:
.wrapper {
display: flex;
justify-content: space-betweet;
width: 500px;
background-color: lightgray;
;
margin-top: 36px;
}
.box {
display: flex;
flex-direction: column;
width: 50%;
}
.box__content {
width: 120px;
height: 100px;
background-color: lightcoral;
}
.box+.box {
margin-top: 21px;
}
.box.box--with-title {
margin-top: 0;
}
<div class="wrapper">
<div class="box">
<h3>I have a title!</h3>
<div class="box__content"></div>
</div>
<div class="box">
<h3></h3>
<div class="box__content"></div>
</div>
</div>
<div class="wrapper">
<div class="box">
<h3>I have a title!</h3>
<div class="box__content"></div>
</div>
<div class="box box--with-title">
<h3>I have also a title!</h3>
<div class="box__content"></div>
</div>
</div>

Layout a flex box similar to a table?

I'm working with a framework developed in-house which depends on a certain structure to our HTML. And one of the tricky things is that each row needs its own container with its own classes and data attributes.
So here's the problem. Without drastically changing the DOM, how can I make the flex box below render essentially like an HTML table would? Or is a table the only way? The solution will have to work in both IE11 and Chrome.
I'm trying to make it look like this...
Column A | Column B | Column C
1 | 2 | 3
section {
display: flex;
flex-wrap: wrap;
}
section .col {
flex: 1 1 auto;
}
section .line-break {
flex-basis: 100%;
width: 0px;
height: 0px;
overflow: hidden;
}
<html>
<head>
</head>
<body>
<section>
<header>
<div class="col">Column A</div>
<div class="col">Column B</div>
<div class="col">Column C</div>
</header>
<div class="line-break"></div>
<div class="row">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
</div>
</section>
</body>
</html>
header, .row {
display: flex; /* aligns all child elements (flex items) in a row */
}
.col {
flex: 1; /* distributes space on the line equally among items */
}
<section>
<header>
<div class="col">Column A</div>
<div class="col">Column B</div>
<div class="col">Column C</div>
</header>
<div class="row">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
</div>
</section>
If the content you are going to present is of type tabular data, then a table is the proper way.
HTML 5.1 W3C Recommendation, 1 November 2016, 4.9 Tabular data
Given that you can't, or don't want to, alter the markup, this can be done using CSS Table, and with that easily swap between any display type such as flex, block, etc., or even float, using media query etc.
I also removed the <div class="line-break"></div> element, since you don't need, though if it is rendered by a component or similar, leaving it as is won't cause any problem.
Using CSS Table
section {
display: table;
width: 100%;
}
section > * {
display: table-row;
}
section .col {
display: table-cell;
}
<html>
<head>
</head>
<body>
<section>
<header>
<div class="col">Column A</div>
<div class="col">Column B</div>
<div class="col">Column C</div>
</header>
<div class="row">
<div class="col">1</div>
<div class="col">2</div>
<div class="col">3</div>
</div>
</section>
</body>
</html>
If you still need, or have to, use Flexbox, this answer of mine mention the difference between CSS Table and Flexbox on two important features:
Can flexbox handle varying sizes of columns but consistent row height?
Updated, a sample showing some useful Flexbox stuff, with varying width's and span columns.
Using Flexbox
.tbl {
display: flex;
flex-direction: column;
}
.row {
display: flex;
min-height: 50px;
}
.cell {
flex: 4;
border: 1px solid red;
}
.cell:nth-child(1) {
flex: 1;
}
.cell:nth-child(2) {
flex: 2;
}
.cell.span4-5 {
flex: 8 24px; /* col 4,5 flex-grow/border/padding */
}
.cell.span3-4 {
flex: 8 24px; /* col 3,4 flex-grow/border/padding */
}
.cell.span3-5 {
flex: 12 36px; /* col 3,4,5 flex-grow/border/padding */
}
.row:first-child .cell {
display: flex;
justify-content: center; /* center horiz. */
align-items: center; /* center vert. */
}
.row .cell {
padding: 5px;
box-sizing: border-box;
}
<div class="tbl">
<div class="row">
<div class="cell">ID </div>
<div class="cell">Nr </div>
<div class="cell">Header 1 </div>
<div class="cell span4-5"> Header 2 </div>
</div>
<div class="row">
<div class="cell">1</div>
<div class="cell">2</div>
<div class="cell">Content</div>
<div class="cell">Content</div>
<div class="cell">Content</div>
</div>
<div class="row">
<div class="cell">2</div>
<div class="cell">3</div>
<div class="cell span3-5">Content</div>
</div>
<div class="row">
<div class="cell">1</div>
<div class="cell">2</div>
<div class="cell span3-4">Content</div>
<div class="cell">Content</div>
</div>
</div>
This code works for me:
* {
box-sizing: border-box;
}
body, html {
height: 100%;
margin: 0;
}
#container {
width: 400px;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
background-color: lightgrey;
padding: 10px;
}
.shelf {
flex: 1 1 auto;
width: 100%;
margin-bottom: 10px;
border: 1px solid black;
background-color: lightgreen;
display: flex;
flex-direction: row;
}
.shelf:last-child {
margin-bottom: 0;
}
.labelbox {
flex: 0 0 35%;
}
.valuebox {
flex: 0 0 65%;
}
<div id="container">
<div class="shelf">
<div class="labelbox">Name: </div> <div class="valuebox">Barry Carter</div>
</div>
<div class="shelf">
<div class="labelbox">DOB:</div><div class="valuebox">10/12/1980</div>
</div>
<div class="shelf">
<div class="labelbox">
Description:
</div>
<div class="valuebox">
This content goes on and on and will force the height to expand. And the label box to the left will
"move" with it. There need not be much of a relation other than that their parent div/flex-container is
getting taller as well.
</div>
</div>
<div class="shelf">
<div class="labelbox">Group:</div><div class="valuebox">Advanced</div>
</div>
<div class="shelf">
<div class="labelbox">End Date:</div><div class="valuebox">2020-09-20</div>
</div>
</div>
Use CSS Grid. You can style any table the way you like.
Keep in mind If your table is more than 700 rows, the fram rate will start to drop, no matter what js framework you use. react, angular, vue or vanila JS. the scrolling will get real laggy.
And the maximum you row can use is 1000. More than that the extra row will create bad graphic. But you wont reach 1000 anyway, because at 700th row, the scrolling speed, starts to get bad.
If somehow you need to display more than 1000 rows, you will visualized lib. Every js framework has a lib to do so. Basically, it will render the rows in the view port. The rows that not in the view port will not be rendered. They will only be rendered when user scrolls.
This is year 2021, chances you read this answer in the future, the browsers vendor might probably fix the performance of 1000 rows, they might even extend that limit. So try it out.

How to use `flex: grow` on floating content?

I have a header with 2 rows of 2 Foundation columns of content, as below:
<div class="wrapper">
<div class="header row">
<div class="large-6 columns">
HEADER
</div>
<div class="large-6 columns">
menu
</div>
</div>
<div class="row">
<div class="large-5 none show-for-medium columns info">
Some information to the left
</div>
<div class="large-7 columns">
<div class="image-container">
<div class="image">
image to the right
</div>
</div>
</div>
</div>
</div>
The .header height is dynamic and not set. I want the .image element to take up 100% of the remaining vertical space.
eg:
To that affect I have tried using flex and flex-grow, eg:
.wrapper {
display: flex;
flex-direction: column;
min-height: 100vh;
width: 100%;
}
.image-container {
flex-grow: 1;
}
but had no luck, see fiddle: https://jsfiddle.net/9kkb2bxu/46/
Would anyone know how I could negate the dynamic height of the header from the 100vh of the image container?
.wrapper {
display: flex;
flex-direction: column;
min-height: 100vh;
width: 100%;
border: 1px solid black;
background-color: #ccc;
}
.row {
width: 100%;
}
.header {
background-color: green;
}
.info {
background-color: yellow;
border: 1px solid #ccc;
}
.image-container {
border: 1px solid black;
display: flex;
}
.image {
background-color: red;
flex-grow: 1;
width: 100%;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.1/css/foundation.min.css" rel="stylesheet"/>
<div class="wrapper">
<div class="header row">
<div class="large-6 columns">
<h1>
HEADER
</h1>
</div>
<div class="large-6 columns">
<h1>
menu
</h1>
</div>
</div>
<div class="row">
<div class="large-5 none show-for-medium columns info">
Some information to the left
</div>
<div class="large-7 columns">
<div class="image-container">
<div class="image">
image to the right
</div>
</div>
</div>
</div>
</div>
Set the second row to take up the rest of the remaining height with flex: 1 and make sure you nest that flex with display: flex:
.row.target-row {
flex: 1;
display: flex;
}
Set the .image-container to 100% height of its column parent.
.image-container {
height: 100%;
}
By default both columns will expand. Stop the left column from expanding with:
.large-5 {
align-self: flex-start;
}
(flex-start reference: https://stackoverflow.com/a/40156422/2930477)
Complete Example
.wrapper {
display: flex;
flex-direction: column;
min-height: 100vh;
width: 100%;
border: 1px solid black;
background-color: #ccc;
}
.row {
width: 100%;
}
.header {
background-color: green;
}
.info {
background-color: yellow;
border: 1px solid #ccc;
}
.image-container {
height: 100%;
background-color: red;
}
.large-5 {
align-self: flex-start;
}
.row.target-row {
flex: 1;
display: flex;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.1/css/foundation.min.css" rel="stylesheet" />
<div class="wrapper">
<div class="header row">
<div class="large-6 columns">
<h1>
HEADER
</h1>
</div>
<div class="large-6 columns">
<h1>
menu
</h1>
</div>
</div>
<div class="row target-row">
<div class="large-5 none show-for-medium columns info">
Some information to the left
</div>
<div class="large-7 columns">
<div class="image-container">
<div class="image">
image to the right
</div>
</div>
</div>
</div>
</div>
flex-grow only applies to flex children.
.image-container isn't a direct child of a display: flex element, so that property has no effect.
Plus, it affects the flex axis, which is not what you want.
Instead, you need to put those two elements in their own flex row, and use align-items (on the parent) and align-self (on either child) so that the first one aligns (on the cross axis) to flex-start (stick to top) and the second one to stretch.
You'll also want that flex row (parent) to have flex-grow: 1 so that it stretches along the vertical flex axis of its parent (.wrapper) to fill the rest of the page (otherwise, the grandchild will have nothing to stretch to).
For more information, read a good flex tutorial.
div.wrapper > div:not(.header).row {
flex: 1; /* 1 */
display: flex; /* 1 */
}
div.large-7.columns {
display: flex; /* 2 */
}
div.image-container { /* 3 */
flex: 1;
}
div.large-5.show-for-medium { /* 4 */
align-self: flex-start;
}
jsFiddle
Notes:
flex container and items consume all remaining height of respective parents
give children full height (via align-items: stretch initial setting)
flex item consumes all available width
yellow box does not need to expand to full height; now set to content height