Set same height in flex-box for dynamic content - html

In this case
need to keep same height for all three columns (this is working already according to current code, ".col" get same height using flex)
need to set max height of yellow div (dynamic content) for all yellow
div
need to be implement using CSS only (not JavaScript)
use flex (not tables)
here is test code jsfiddle
Current Design
Need Design
I have dynamic content inside the "bottom-content" area. what I need to do, set all "bottom-content" area same height (set max height for 3 yellow areas), and all "col" should be same height too.
HTML code
<div class="container">
<div class="col">
<div class="top-content">top content here</div>
<div class="bottom-content">bottom content here</div>
</div>
<div class="col">
<div class="top-content">top content here</div>
<div class="bottom-content">bottom content here</div>
</div>
<div class="col">
<div class="top-content">top content here</div>
<div class="bottom-content">bottom content here</div>
</div>
</div>
CSS code
.container {
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
flex-flow: row wrap;
overflow: hidden;
}
.container .col {
flex: 1;
padding: 20px;
}
.container .col:nth-child(1) {
background: #eee;
}
.container .col:nth-child(2) {
background: #ccc;
}
.container .col:nth-child(3) {
background: #eee;
}
.top-content {
background: #888;
border-bottom: 1px solid #333;
padding: 5px;
}
.bottom-content {
background: yellow;
padding: 5px;
}

Related

Scrollbar and its content is hidden outside of div

So I have a problem where I have 2 divs inside of another div with a fixed size. I the second of the two is too large to fit in the fixed height div so I want a scroll bara to appear. But the scrollbar goes outside of the content. How do I fix this?
html:
<div class="main">
<div class="first-child">
<div class="small-content">
Content
</div>
</div>
<div class="second-child">
<div class="large-content">
Content
</div>
</div>
</div>
css:
.main {
height: 250px;
overflow: hidden;
}
.first-child {
background-color: red;
}
.second-child {
max-height: 100%;
background-color: blue;
overflow-y: scroll;
}
.large-content {
padding-top: 300px;
}
.small-content {
padding: 10px;
}
https://codepen.io/RilleJ/pen/JeBVpz
I added an example as well to show what I mean. Basically I want to be able to scroll all the way down in the blue box and see the content without setting a fixed height. (Not that the content above, the red box, can be different sizes)
Use flexbox to divide the space of the container among the children.
Add flex-grow: 0, and flex-shrink: 0 for a child that just needs to take the space it needs for its content.
Add flex-grow: 1, and flex-shrink: 1 on the other children to divide the remaining space equally (each child will take at least the size of its content).
.main {
height: 250px;
overflow: hidden;
display: flex;
flex-direction: column;
}
.first-child {
flex-grow: 0;
flex-shrink: 0;
background-color: red;
}
.second-child {
flex-grow: 1;
flex-shrink: 1;
background-color: blue;
overflow-y: scroll;
}
.large-content {
padding-top: 300px;
}
.small-content {
padding: 10px;
}
<div class="main">
<div class="first-child">
<div class="small-content">
Content
</div>
</div>
<div class="second-child">
<div class="large-content">
Content
</div>
</div>
</div>

Moving one HTML element before another while maintaining document flow

I am trying to create tab module such as this:
https://codepen.io/oknoblich/pen/tfjFl
However I am having difficulty since I can not change the HTML layout:
<div class="container">
<div class="tab-header">Tab1</div>
<div class="tab-content teal">Content1</div>
</div>
<div class="container current">
<div class="tab-header">Tab2</div>
<div class="tab-content teal">Content2</div>
</div>
The problems are that absolute positioning removes the content from the document flow, while other methods prevents the content from being the full width of the page.
I created two codepen's that illustrates the difficulties:
https://codepen.io/dwigt/pen/pOQpLd (absolute positioning removes content from document flow)
https://codepen.io/dwigt/pen/YOREOJ (flexbox layout does not take up full page-width)
Is there anyway I can replicate the tab functionality using this HTML layout and no javascript?
You can use display: contents (which is unfortunately not too well supported) combined with flexbox layout with wrap, set on the .wrapper element. This way, tab-headers and tab-contents will be treated equally, as if they were at the same level with one another - the .container elements are "transparent" to the layout engine. As a result, they will all be laid out with flexbox logic applied. Finally, to have the three tab headers display first, we set the order of the tab contents to some high value (here 100), and since we have flex wrap enabled, the content is then pushed downwards to a new line, below the headers. See example below:
.wrapper {
max-width: 300px;
display: flex;
flex-wrap: wrap;
height: 100%;
}
.container {
height: 50px;
display: contents;
}
.container .tab-header {
width: 100px;
max-width: 100%;
max-height: 100%;
flex: 1 0 33.33%;
}
.container .tab-content {
display: none;
height: 200px;
order: 100;
}
.container.current .tab-content {
display: block;
width: 300px;
left: 0;
}
.footer {
height: 500px;
width: 300px;
display: block;
}
.red {
background: red;
}
.teal {
background: teal;
}
<div class="wrapper">
<div class="container">
<div class="tab-header">Tab1</div>
<div class="tab-content teal">Content1</div>
</div>
<div class="container current">
<div class="tab-header">Tab2</div>
<div class="tab-content teal">Content2</div>
</div>
<div class="container">
<div class="tab-header">Tab3</div>
<div class="tab-content teal">Content3</div>
</div>
</div>
<div class="footer red">Footer Text</div>
This isn't quite perfect because the first tab is a bit wider, but give this a shot and see if this doesn't get your closer to your goal. It allows your tabs to be 100% and also allows you to add more tabs that space evenly from edge to edge of your container.
Let me know how it works out :D
Add display: table-cell and width: 100% to your css selector label
label {
display: table-cell;
width: 100%;
margin: 0 0 -1px;
padding: 15px 25px;
font-weight: 600;
text-align: center;
color: #bbb;
border: 1px solid transparent;
}

Flex grandchildren doesn't expand to immediate parent's height

I have the following layout (simplified version). .account is the flex-container and .card-two holds the actual table. When there is a lot of content, everything works fine, but when .card-two doesn't have enough content (when showing error messages), it does not fill the height of its parent .content. the cards have a background color set, so the entire effect looks quite ugly.
How do I make the card behave and stretch to fill its container? I tried setting height on .account, setting flex-basis:1 0 0, but it doesn't work. setting height:100% to .card-two just makes it massively overflow its parent. Note: I do not have a lot of control on the HTML.
HTML code:
<div class="container">
<div class="account">
<div class="sidebar">This is a sidebar aka the first column</div>
<div class="content">
<div class="card-one">this is card number one. full width of the parent</div>
<div class="card-two">this card should have a lot of content. but sometimes it doesn't.</div>
</div>
</div>
</div>
CSS (without the changes I have tried):
.container{
// just a generic container.
width:1140px; margin:auto;
}
.account{
display: flex;
}
.sidebar{
width: 25%;
}
.content{
width: 75%;
}
here's a codepen (with some comments as to what I have tried): https://codepen.io/samia92/full/MVJqwQ
any help is much appreciated.
You need to add flex to .content then only card-two can have flexbox properties.
.container {
width: 600px;
margin: auto;
box-sizing: border-box;
}
.account {
display: flex;
height: 400px;
}
.card {
background: #ddd;
box-shadow: 1px 2px 2px rgba(0, 0, 0, 0.5);
padding: 15px;
}
.sidebar {
width: 25%;
margin-right: 10px;
}
.content {
width: 75%;
display: flex; /*Addded*/
flex-direction: column; /*Addded*/
}
.card-one {
margin-bottom: 20px;
}
.card-two {
flex: 1; /*Addded*/
}
<div class="container">
<div class="account">
<div class="sidebar card">
This is a sidebar aka the first column
</div>
<div class="content">
<div class="card-one card">
<p>this is card number one. full width of the parent</p></div>
<div class="card-two card"><p>this card should have a lot of content. but sometimes it doesn't.</p>
<p>I want it to expand to it's parent, which has appropriate height</p>
<p>There You go.</p>
</div>
</div>
</div>
</div>

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

Control width of flex items arranged vertically in a flex container

I'm trying to achieve the effect where the boxes labeled "HALF", take up only 50% of the width (aka they share the first row evenly).
The base requirement is that they remain in a single container. Is this possible to achieve using flexbox?
I've tried playing around with flex-grow, flex-shrink, and flex-basis but I'm afraid I'm not understanding how to make it work, or if it's even possible, given the single container requirement.
Consider this fiddle: http://jsfiddle.net/GyXxT/270/
div {
border: 1px solid;
}
.container {
width: 400px;
display: flex;
flex-direction: column;
}
.child {
height: 200px;
}
.child.half {
flex: 1 1 10em;
color: green;
}
.child:not(.half) {
flex-shrink: 2;
flex-basis: 50%;
color: purple;
}
<div class="container">
<div class="child half">
HALF
</div>
<div class="child half">
HALF
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
</div>
Instead of flex-direction: column, you can try a wrapping flexbox using flex-wrap: wrap; and you can set:
flex-basis: 50% for the half width divs
flex-basis: 100% for the full width divs
See that I have thrown in box-sizing: border-box to adjust for the widths when using flex-basis.
See demo below:
div {
border: 1px solid;
box-sizing: border-box;
}
.container {
width: 400px;
display: flex;
flex-wrap: wrap;
}
.child {
height: 200px;
}
.child.half {
flex-basis: 50%;
color: green;
}
.child:not(.half) {
flex-basis: 100%;
color: purple;
}
<div class="container">
<div class="child half">
HALF
</div>
<div class="child half">
HALF
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
</div>
The flex sizing properties -- flex-grow, flex-shrink, flex-basis and flex -- work only along the main axis of the flex container.
Since your container is flex-direction: column, the main axis is vertical, and these properties are controlling height, not width.
For sizing flex items horizontally in a column-direction container you'll need the width property.
(Here's a more detailed explanation: What are the differences between flex-basis and width?)
To achieve your layout with a single container, see another answer to this question.
If you want to stay in column-direction, you'll need to wrap the .half elements in their own container.
.container {
display: flex;
flex-direction: column;
width: 400px;
}
.container > div:first-child {
display: flex;
}
.child.half {
flex: 1 1 10em;
color: green;
width: 50%;
}
.child {
height: 200px;
width: 100%;
border: 1px solid;
}
* {
box-sizing: border-box;
}
<div class="container">
<div><!-- nested flex container for half elements -->
<div class="child half">HALF</div>
<div class="child half">HALF</div>
</div>
<div class="child">FULL</div>
<div class="child">FULL</div>
<div class="child">FULL</div>
<div class="child">FULL</div>
</div>
The base requirement is that they remain in a single container.
That can also be done without flexbox, by simply float the 2 half elements
div {
border: 1px solid;
box-sizing: border-box;
}
.container {
width: 400px;
}
.child {
height: 200px;
}
.child.half {
float: left;
width: 50%;
color: green;
}
.child:not(.half) {
width: 100%;
color: purple;
}
<div class="container">
<div class="child half">
HALF
</div>
<div class="child half">
HALF
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
<div class="child">
FULL
</div>
</div>
If the purpose is to hardcode the size in CSS units, or in percentages (which was mentioned the question), #kukkuz's solution is good as it is.
If you want to size element widths according to their own individual contents, then align-tems: flex-start or similar could do the job. It's possible to deal with the dimension perpendicular to that of the flex layout itself. See a tester on the bottom of the doc page
(Old question, but previous answers were incomplete, some are misleading)