Using Foundation XY-grid, and specifically a nested grid-y inside a cell, I want to use the class .auto on the parent cell to distribute the cell heights evenly, in the case of a grid-y with 2 cells that would be 50%/50%.
This works fine as long as the grid-y cell content is low enough to fit inside the cell without pushing the border. However, if the content is higher, the content is cropped.
A workaround for this is to set flex-basis for class .auto to "auto" instead of "0px" which is the predefined value in Foundation css.
This works fine as long as the content is high enough to push the cell border, but if it's smaller then the parent cell heights are not distributed evenly.
Side note: The use of ".grid-y" on each cell is to be able to position the content of the cell center vertically. Please see:
Vertically align content inside XY-Grid Cell
<div class="grid-container">
<div class="grid-x">
<div class="cell medium-6 grid-y align-middle align-center" style="background:green;">
<div style="background: blue; height: 300px">
Element A
</div>
<div style="background: violet; height: 300px">
Element B
</div>
</div>
<div class="cell medium-6 grid-y align-middle align-center" style="background:red;">
<!-- Nested Grid -->
<div class="grid-y" style="min-height: 100%; width: 100%;">
<div class="cell auto grid-y align-middle align-center" style="background:yellowgreen;">
<div style="background: yellow; height: 50px">
Element C
</div>
<div style="background: gray; height: 50px">
Element D
</div>
</div>
<div class="cell auto grid-y align-middle align-center" style="background:darkcyan;">
<div style="background: yellow; height: 70px">
Element E
</div>
<div style="background: gray; height: 70px">
Element F
</div>
</div>
</div>
</div>
</div>
</div>
Modified CSS:
.grid-y > .cell.auto {
-webkit-box-flex: 1;
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
}
instead of Foundation original code:
flex: 1 1 0px
Because the grid is already using Flexbox, you can set up a horizontal grid and equal height cells by making the cells also display flex.
Example: https://codepen.io/rafibomb/pen/wLWKXL
<div class="grid-x">
<div class="cell flex-container auto">
<img src="http://placehold.it/20" alt="">
</div>
<div class="cell flex-container auto">
<img src="http://placehold.it/50" alt="">
</div>
<div class="cell flex-container auto">
<img src="http://placehold.it/700" alt="">
</div>
</div>
Related
Forget how to code a div style table.
I haven't coded html in years and am pretty rusty. I'm trying to create a responsive div style table with the first div spans the entire column with 2 more divs next to it. A div with 2 cells on top and a div that spans the 2 cells on bottom.
I'm trying to create something that looks like this image.
<div class="table">
<div class="row">
<div class="cell">cell 1</div>
</div>
<div class="row">
<div class="cell">cell 1</div>
<div class="cell">cell 2</div>
</div>
<div class="row">
<div class="cell colspan">
<div><div>
cell 3
</div></div>
</div>
<div class="cell"></div>
</div>
Use flexbox. By assigning display: flex; to the .table, .row, and .column elements, child elements of each all become flexible and can easily be controlled to take up certain percentages of space within the table, and grow to fill all the available space like a table would.
The flex property takes a little getting used to. Here I used it to tell flex items to grow (the first value, flex-grow), and starting widths (the third value, flex-basis). This resource makes it pretty easy to understand: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
* { box-sizing: border-box; }
.table,
.row,
.column {
display: flex;
}
.column {
flex: 1 0 50%;
flex-direction: column;
}
.first-column {
flex-basis: 33%;
}
.cell {
flex: 1 0 100%;
padding: 20px;
border: 1px solid dodgerblue;
}
.first-row .cell {
border-left: none;
}
.second-row .cell {
border-top: none;
border-left: none;
}
<div class="table">
<div class="column first-column">
<!-- just the one cell in this column -->
<div class="cell">cell 1</div>
</div>
<div class="column">
<!-- need 2 rows here -->
<div class="row first-row">
<!-- first row will have 2 columns -->
<div class="column">
<div class="cell">cell 2</div>
</div>
<div class="column">
<div class="cell">cell 3</div>
</div>
</div>
<div class="row second-row">
<div class="cell">cell 4</div>
</div>
</div>
</div>
Well Consider I have a table with 3 columns. "Normally" each column should take 1/3rd of the page. However if one of the column's data gets too large, and the other columns have extra space it should "flex", and the column should occupy the remaining space.
However it should still be a "table": as in column & row borders need to align.
When using naive flex boxes I tried both a row and column first approach. However both have the problem that the "inner" flexbox might stretch, but that information is lost on the other flex boxes.
I've tried to solve it below using both methods: but as you can see it's not working:
.bordered{
border-width: 1px;
border-color: black;
border-style: solid;
}
.main {
display: block;
position: relative;
}
.row {
display: flex;
position: relative;
width: 100%;
}
.cell {
flex: 1 1 auto;
max-width: 75%;
}
<div class="main bordered">
<div class="row">
<div class="cell bordered">
first
</div>
<div class="cell bordered">
second
</div>
<div class="cell bordered">
third
</div>
</div>
<div class="row">
<div class="cell bordered">
first
</div>
<div class="cell bordered">
This is text that will increase the width of the cell.
</div>
<div class="cell bordered">
third
</div>
</div>
<div class="row">
<div class="cell bordered">
first
</div>
<div class="cell bordered">
This is text that will increase the width of the cell. Not only that, but due to the amount of text it also increases the height of a row. This isn't a problem with this setup. But had we chosen to use a column-first approach this cell would destroy any "row" layout.
</div>
<div class="cell bordered">
third
</div>
</div>
</div>
Can this be done? Or should I give up on this?
Flexbox is probably not the best-suited solution for this. I would recommend looking to use CSS Grid Layout. There are many ways to accomplish this, but here's a start.
Use a 3 column, 3 row grid, with auto width cells (using an optional min-width to preserve some space).
.main {
display: grid;
position: relative;
grid-template-columns: auto auto auto;
grid-template-rows: auto auto auto;
}
.bordered {
border-width: 1px;
border-color: black;
border-style: solid;
}
.cell {
grid-column-end: span 1;
}
.cell:nth-child(3n+1) {
grid-column-start: 1;
min-width: 50px;
}
.cell:nth-child(3n+2) {
grid-column-start: 2;
}
.cell:nth-child(3n+3) {
grid-column-start: 3;
min-width: 100px;
}
<div class="main bordered">
<div class="cell bordered">
first
</div>
<div class="cell bordered">
second
</div>
<div class="cell bordered">
third
</div>
<div class="cell bordered">
first
</div>
<div class="cell bordered">
This is text that will increase the width of the cell.
</div>
<div class="cell bordered">
third
</div>
<div class="cell bordered">
first
</div>
<div class="cell bordered">
This is text that will increase the width of the cell. Not only that, but due to the amount of text it also increases the height of a row. This isn't a problem with this setup. But had we chosen to use a column-first approach this cell would destroy any
"row" layout.
</div>
<div class="cell bordered">
third
</div>
</div>
</div>
I'm learning Bootstrap and I'm trying to figure out how to automatically adjust a rows height given this conditions:
There are 3 rows within a container-fluid
row1 must adjust to the height of its content
row3 must adjust to the height of its content and be at the bottom of the viewport
row2 should adjust its height to the space between row1 and row3 to fill the container-fluid
html, body, .container-fluid {
height: 100%;
background: lightyellow;
}
.col {
border: solid 1px #6c757d;
}
.content-1 {
height: 50px;
background-color: lightcoral;
}
.content-2 {
height: 200px;
background-color: lightgreen;
}
.content-3 {
height: 25px;
background-color: lightblue;
}
<div class="container-fluid">
<div class="row">
<div class="col">
<div class="content-1">
ROW 1 -> Height of its content
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="content-2">
ROW 2 -> Height between row1 and row3 automatically adjusted
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="content-3">
ROW 3 -> Height of its content
</div>
</div>
</div>
</div>
JSFiddle demo
What would be the best approach to do so?. Thank you in advance!
You're looking for the flexbox utility classes. d-flex is for display:flex, and flex-grow-1 will make the 2nd child div fill the remaining height. Use flex-column as you want a vertical layout.
<div class="container-fluid d-flex flex-column">
<div class="row">
<div class="col">
<div class="content-1">
ROW 1 -> Height of its content
</div>
</div>
</div>
<div class="row flex-fill">
<div class="col d-flex flex-column">
<div class="content-2 h-100">
ROW 2 -> Height between row1 and row3 automatically adjusted
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="content-3">
ROW 3 -> Height of its content
</div>
</div>
</div>
</div>
https://www.codeply.com/go/IIVJqGJ2qG
Note: The fixed heights set in the custom CSS have been removed to allow the header/footer to be the height of their content, and the content row to fill the remaining height.
Related:
Bootstrap 4: How to make the row stretch remaining height?
Bootstrap - Fill fluid container between header and footer
I see you use bootstrap 4. But anyone who use bootstrap 3 or not at all using any CSS libraries, then the solution would be the code below.
.parent-row{
display: flex;
}
.children-columns{
display: flex;
}
Plnkr of my situation: https://plnkr.co/edit/ppuUhrWB08ULGuFT4tXn
I recommend popping out the results window.
I have a vertical flex container that contains two items. The second item is also a vertical flex container. It contains several items that are horizontal flex containers. These horizontal containers contain two items. One of the items contains an image, set to height:100%. The other item is set to fill remaining space.
Visual Representation
grey = top-level vertical flex container
turquoise = fixed item
green = second vertical flex container
yellow = horizontal flex-container
red = flex item containing image
dark purple = image
magenta = flex item designated to fill empty space
Expectation: the item containing the image shrinks to contain the height:100% image, the second image expands to fill the space.
Actual Result: the item is the NATURAL WIDTH of the image and doesn't shrink, even though the image itself is smaller.
Visual Representation:
I've also tried not putting the img inside a container and letting it just be a flex item, but then height:100% makes the image as big as the vertical flex container because ¯\_(ツ)_/¯
I'm not sure how to go about resolving this issue.
HTML:
<div class="body-container">
<div class="body flex-column">
<div class="header flex-hold w-100">
I AM A HEADER
</div>
<div class="long-content flex-column w-100 flex-fill d-flex">
<div class="item d-flex">
<div class="thumb flex-hold"><img src="https://animatedanatomy.com/images/16-9-dummy-image6.jpg" /></div>
<div class="copy flex-fill">
<div>Text</div>
</div>
</div>
<div class="item d-flex">
<div class="thumb flex-hold"><img src="https://animatedanatomy.com/images/16-9-dummy-image6.jpg" /></div>
<div class="copy flex-fill">
<div>Text</div>
</div>
</div>
<div class="item d-flex">
<div class="thumb flex-hold"><img src="https://animatedanatomy.com/images/16-9-dummy-image6.jpg" /></div>
<div class="copy flex-fill">
<div>Text</div>
</div>
</div>
<div class="item d-flex">
<div class="thumb flex-hold"><img src="https://animatedanatomy.com/images/16-9-dummy-image6.jpg" /></div>
<div class="copy flex-fill">
<div>Text</div>
</div>
</div>
<div class="item d-flex">
<div class="thumb flex-hold"><img src="https://animatedanatomy.com/images/16-9-dummy-image6.jpg" /></div>
<div class="copy flex-fill">
<div>Text</div>
</div>
</div>
</div>
</div>
</div>
CSS:
body {
height:100vh;
margin:0px;
padding:0px;
}
div {
display:inline-block;
}
.d-flex {
display:flex;
}
.flex-column {
flex-direction:column;
}
.body-container {
height:100%;
}
.body {
display:flex;
height:100%;
flex: 1 1 auto;
}
.flex-hold {
flex: 0 0 auto;
}
.flex-fill {
flex: 1 1 auto;
}
.w-100 {
width: 100% !important;
}
.h-100 {
height: 100% !important;
}
.header {
}
.long-content {
background-color:#ffff00;
}
.item {
margin:4px;
background-color:#ccc;
flex: 1 1 auto;
}
.thumb {
display:block;
}
img {
height:100%;
}
I found a solution that works for my specific situation but not entirely sure how applicable it is in the wild. Mostly inspired by this question: https://stackoverflow.com/a/15389545/1857860
I reorganized the html of my horizontal container like so:
<div class="item d-flex flex-fill">
<div class="inner-wrapper">
<div class="d-flex h-100 w-100">
<!--<div class="thumb flex-hold">-->
<img class="h-100 flex-hold" src="https://animatedanatomy.com/images/16-9-dummy-image6.jpg" />
<!--</div>-->
<div class="copy flex-fill">
<div>Text</div>
</div>
</div>
</div>
</div>
So, I made my horizontal flex container relative, then inserted two wrapper elements. The first wrapper (inner-wrapper) is position:absolute, height:100%, width:100%. The second wrapper is just another horizontal flex container. Something about putting a flex container inside the absolute container "resets" what it considers to be height 100% for child elements. So, after that all I had to do was remove the container around my image and set it to height:100% and flex: 0 0 auto;
I am using the Flex Grid component of Zurb Foundation 6 to create a grid of responsive squares -- and that works beautifully. For the life of me, however, I cannot get the square content centered. I have tried all the usual css tricks: relative/absolute, a nested flex grid, etc. There must be something I am missing -- thanks for your help.
Here is the jsfiddle (which is the base code without any attempt at centering).
<div class="row">
<div class="square small-6 columns">
ABC
</div>
<div class="square small-6 columns">
DEF
</div>
</div>
<div class="row">
<div class="square small-6 columns">
123
</div>
<div class="square small-6 columns">
456
</div>
</div>
.square {
border: solid blue 1px;
padding-bottom: 30%;
}
For the life of me, however, I cannot get the square content centered. I have tried all the usual css tricks: relative/absolute, a nested flex grid, etc.
Well, the nested flex grid actually works:
.square {
border: solid blue 1px;
padding-bottom: 30%;
display: flex; /* new */
justify-content: center; /* new */
align-items: center; /* new */
}
It centers the content both vertically and horizontally.
The problem is that the boxes don't have any height. There's no space for the content to move vertically. What looks like height is actually padding, and that's outside the content box.
This is what the layout looks like without the padding-bottom: 30%: DEMO 1
Then add the nested flex container: DEMO 2
Then give the box some height: DEMO 3
Per the CSS Box Model, text goes in the content box. The padding is generally a content-free zone.
Here you go
li {
width:50%;
display: flex;
justify-content: center;
flex-direction: column;
text-align: center;
}
That is it, does the trick. Responsive etc.
Link
http://codepen.io/damianocel/pen/WrMmGe
You can do this with Foundation 6 (with Flex-Grid) only too.
The trick is to attach both align-spaced and align-middle to the outer row.
<div class="row align-spaced align-middle">
<div class="square small-6 row align-center">
<div class="row align-middle">
<span>ABC</span>
</div>
</div>
<div class="square small-6 row align-center">
<div class="row align-middle">
<span>DEF</span>
</div>
</div>
</div>
<div class="row align-spaced align-middle">
<div class="square small-6 row align-center">
<div class="row align-middle">
<span>123</span>
</div>
</div>
<div class="square small-6 row align-center">
<div class="row align-middle">
<span>456</span>
</div>
</div>
</div>
<style>
.square {
border: solid blue 1px;
height: 30vh;
}
</style>
as #michael-b points, the height is important.
Also, you can cut off one div layer if you do not need the blue line.
<div class="row align-spaced align-middle" style="height: 100px;">
<div class="small-6 row align-center">
<span>...</span>
</div>
</div>