Max Height not working on flexing child with overflow - html

I have an element with 2 children.
I'm trying to have:
div grow as much as it needs based on 1 of its children
the other always fit the parents height
Thus, I want to avoid setting a height on the parent.
The problem arises when trying to handle overflow of the second child.
Here's the code:
.banner {
display: flex;
background-color: lightblue;
overflow: auto;
border: 4px solid black;
//max-height: 120px; // 1) IF I'M NOT SET THE SCROLL WON'T WORK
}
.constant {
color: white;
flex: 0 0 auto;
width: 200px;
// height: 150px; 2) DISABLED FOR NOW
border: 4px solid yellow;
background-color: olive;
border: 2px solid red;
}
.container {
display: flex;
text-align: center;
}
.main {
max-height: 100%; // 3) I SHOULD STOP MYSELF FROM GROWING MORE THAN MY PARENT
flex: 1;
overflow-y: scroll;
border: 2px solid white;
display: flex;
flex-direction: row-reverse;
align-items: flex-end;
flex-wrap: wrap;
}
.main div {
text-align: center;
width: 200px;
height: 80px;
}
.main-side {
flex: 0 0 auto;
color: white;
background-color: grey;
border: 2px solid yellow;
}
html {
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
background-repeat: no-repeat !important;
min-width: 0px;
min-height: 0px;
}
<div class="banner">
<div class="container">
<div class="main">
<div style="background-color:coral;">A</div>
<div style="background-color:lightgoldenrodyellow;">B</div>
<div style="background-color:khaki;">C</div>
<div style="background-color:pink;">D</div>
<div style="background-color:lightgrey;">E</div>
<div style="background-color:lightgreen;">F</div>
</div>
<div class="main-side">I've a fixed size</div>
</div>
<div class="constant">I can grow...and my parent should grow if I grow</div>
</div>
If I set a fixed height on .banner everything works out, but I would like to avoid doing so if possible.
jsfiddle
Thank you.

Related

Setting width of an element to that of one which overflows its container when both are in a flexbox?

Is there a CSS way of getting the blue line (class .cover) in this snippet to have a width equal that of the .scrl_can, which exceeds the width of its container .prnt?
The width of .scrl_can changes based on user input. A width of 100% sets the width of .cover to the width of .prnt. I tried align-items: stretch; in .prnt and it is the same as width of 100%.
I realize there are other ways of getting the blue line in that position and of the desired width, but the real UI piece has some relatively positioned elements that "drop" below the container when selected; and setting overflow-x: hidden, cuts them off; so I was trying this method which almost works.
Thank you.
.flex_can {
display: flex;
flex-flow: row nowrap;
width: 600px;
}
.space {
flex: none;
width: 150px;
height: 50px;
margin-left: 10px;
background-color: rgb(200,200,200);
}
.prnt {
flex: 1 1;
border: 1px solid black;
padding: 5px;
display: flex;
flex-flow: column nowrap;
overflow-x: scroll;
}
.scrl_can {
width: 500px;
height: 50px;
border: 0.1px solid green;
white-space: nowrap;
}
.cover {
flex: none;
width: 100%;
height: 2px;
background-color: blue;
margin-bottom: 20px;
}
<div class="flex_can">
<div class="prnt">
<div class="scrl_can">Some words here to span the width of prnt to make it a scroll can.</div>
<div class="cover"></div>
</div>
<div class="space"></div>
</div>
I would use the ::after pseudo element.
.flex_can {
display: flex;
flex-flow: row nowrap;
width: 600px;
}
.space {
flex: none;
width: 150px;
height: 50px;
margin-left: 10px;
background-color: rgb(200,200,200);
}
.prnt {
flex: 1 1;
border: 1px solid black;
padding: 5px;
display: flex;
flex-flow: column nowrap;
overflow-x: scroll;
}
.scrl_can {
position: relative;
width: 500px;
height: 50px;
border: 0.1px solid green;
white-space: nowrap;
}
.scrl_can::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 2px;
background-color: blue;
margin-bottom: 20px;
}
<div class="flex_can">
<div class="prnt">
<div class="scrl_can">Some words here to span the width of prnt to make it a scroll can.</div>
<!-- <div class="cover"></div> DON'T NEED THIS ANYMORE -->
</div>
<div class="space"></div>
</div>

Space between border parent div and child div's

I am getting white space between my parent div and child div when adding a border to the parent div. I have tried everything (overflow, (min) height/width, increasing border width) but nothing works. I have the same problem with images when.
Does someone know how I can fix this and why this is happening?
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body,
html {
margin: 0;
padding: 0;
}
.container {
margin: auto;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
height: 100vh;
width: 100vw;
}
.big-box {
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
background: white;
border: 5px solid darkgreen;
overflow: hidden;
height: 100px;
width: 100px;
}
.box {
flex: 1 1 33%;
min-height: 100%;
min-width: 100%;
background: black;
color: white;
border: none;
overflow: hidden;
}
<div class="container">
<div class="big-box">
<div class="box">
<h2>hello</h2>
</div>
</div>
</div>
Yes, I have come across this and I think it is related to fractions of a CSS pixel being interpreted in different ways when the system is mapping them to actual screen pixels, there being more than one screen pixel to a CSS pixel on many modern screens. The calculations of course vary on different zoom settings and so sometimes you can see the extra white and sometimes not depending on zoom level.
A practical, if hacky, way of getting round this is to give the parent the same background color as the child if that doesn't mess up other stuff in your styling.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body,
html {
margin: 0;
padding: 0;
}
.container {
margin: auto;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
height: 100vh;
width: 100vw;
}
.big-box {
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
background: white;
border: 5px solid darkgreen;
overflow: hidden;
height: 100px;
width: 100px;
background-color: black;
}
.box {
flex: 1 1 33%;
min-height: 100%;
min-width: 100%;
background: black;
color: white;
border: none;
overflow: hidden;
}
<div class="container">
<div class="big-box">
<div class="box">
<h2>hello</h2>
</div>
</div>
</div>
If that messes up your styling I suppose you could go one (hackier) step further and use linear-gradient backgrounds on the parent to give it a sort of black inner border of a (CSS) px or two and leave the rest as white.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body,
html {
margin: 0;
padding: 0;
}
.container {
margin: auto;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
height: 100vh;
width: 100vw;
}
.big-box {
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
background: white;
border: 5px solid darkgreen;
overflow: hidden;
height: 100px;
width: 100px;
background-image: linear-gradient(black 0 2px, transparent 2px calc(100% - 2px), black calc(100% - 2px) 100%), linear-gradient(to right, black 0 2px, white 2px calc(100% - 2px), black calc(100% - 2px) 100%);
}
.box {
flex: 1 1 33%;
min-height: 100%;
min-width: 100%;
background: black;
color: white;
border: none;
overflow: hidden;
}
<div class="container">
<div class="big-box">
<div class="box">
<h2>hello</h2>
</div>
</div>
</div>

Stretch columns in two columns layout with shared header using flexbox

I'm using flexbox to create a two-columns layout with a header row.
* {
box-sizing: border-box;
position: relative;
}
.container {
border: 2px solid gray;
display: flex;
flex-wrap: wrap;
height: 300px;
}
.header {
flex-basis: 100%;
border: 2px solid magenta;
height: 50px;
line-height: 50px;
text-align: center;
}
.column1 {
flex-basis: 150px;
/* height: calc(100% - 50px); */
border: 2px solid green;
}
.column2 {
/* height: calc(100% - 70px); */
flex: 1;
border: 2px solid orange;
}
<div class='container'>
<div class='header'>it's a header</div>
<div class='column1'>column 1</div>
<div class='column2'>column 2</div>
</div>
Feel free to see the full example here.
As you can see in the example there is a gap between columns and header. My aim is to stretch columns vertically to fill whole empty space in the container.
I can achieve it by setting height property like calc(100% - <header-height>). Is it the correct way?
I just tried to use "flex" style and set align-items: stretch to the container and align-self: stretch to columns but without success. Did I probably miss something trying to implement it this way?
I think specifying flex-direction as column is appropriate in this case.
The second row is itself a flex element with the flex-direction: row. You can fill the rest of the remaining space using flex: 1, which is equivalent to flex-grow: 1.
* {
box-sizing: border-box;
}
.container {
border: 2px solid gray;
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 300px;
}
.header {
border: 2px solid magenta;
height: 50px;
line-height: 50px;
text-align: center;
}
.subcontainer {
display: flex;
flex-direction: row;
flex: 1;
}
.column1 {
flex-basis: 150px;
border: 2px solid green;
}
.column2 {
flex: 1;
border: 2px solid orange;
}
<div class='container'>
<div class='header'>it's a header</div>
<div class="subcontainer">
<div class='column1'>column 1</div>
<div class='column2'>column 2</div>
</div>
</div>
Do it like shown below
* {
box-sizing: border-box;
}
body,
html {
height: 100%;
}
.container {
border: 2px solid gray;
display: flex;
flex-direction: column;
height: 100%;
}
.header {
width: 100%;
border: 2px solid magenta;
height: 50px;
line-height: 50px;
text-align: center;
}
.body-container {
display: flex;
width: 100%;
flex: 1;
}
.column1 {
width: 50%;
border: 2px solid green;
}
.column2 {
width: 50%;
border: 2px solid orange;
}
<div class='container'>
<div class='header'>it's a header</div>
<div class="body-container">
<div class='column1'>column 1</div>
<div class='column2'>column 2</div>
</div>
</div>

larger flex child causing previous sibling's padding to be ignored

So I have a flexbox but I'm having trouble understanding why the first child's padding gets ignored when the second child's content overflows.
here's an example when the second child's content aren't overflowing.
body {
padding: 0;
margin: 0;
}
.flex {
display: flex;
flex-direction: column;
width: 100vw;
height: 100vh;
}
.title {
background-color: green;
border-bottom: 10px solid black;
display: flex;
height: 50px;
padding-bottom: 40px;
}
.body {
background-color: blue;
flex: 1;
}
.content {
background-color: red;
height: 10vh;
}
<div class="flex">
<div class="title">
</div>
<div class="body">
<div class="content">
</div>
</div>
</div>
Here's an example when the child's content are overflowing
body {
padding: 0;
margin: 0;
}
.flex {
display: flex;
flex-direction: column;
width: 100vw;
height: 100vh;
}
.title {
background-color: green;
border-bottom: 10px solid black;
display: flex;
height: 50px;
padding-bottom: 40px;
}
.body {
background-color: blue;
flex: 1;
}
.content {
background-color: red;
height: 100vh;
}
<div class="flex">
<div class="title">
</div>
<div class="body">
<div class="content">
</div>
</div>
</div>
you can see in the second example that the title's height has greatly reduced.
It's because you're using flex css, which tries to accommodate all the children. If the title is supposed to not change in size no matter what, you need to set its flex-shrink to 0.
So try changing the css to:
.title {
background-color: green;
border-bottom: 10px solid black;
display: flex;
height: 50px;
padding-bottom: 40px;
flex-shrink: 0;
}

Flexbox: scrollable content with sticky footer

I want to make a box (flex-item in this case) which always stays in the middle of it's container. In that box, there is a header, footer and content section. If the size of the content grows too big in height, I want the content section to be scrollable. The header and footer should always be visible and the box should always stay in it's container.
Here is what I have been able to write:
HTML
<div class="flex-container">
<div class="flex-item">
<header>Header</header>
<div class="content">
A
<br>B
<br>C
<br>D
<br>E
<br>F
<br>G
<br>H
<br>I
<br>J
<br>K
</div>
<footer>Footer</footer>
</div>
</div>
CSS
body {
margin: 120px;
}
.flex-container {
display: flex;
width: 200px;
height: 200px; /* We can assume that the container's height is hardcoded in this example, but the end solution should work even if this value is changed*/
border: 1px solid black;
justify-content: center;
}
.flex-item {
box-sizing: border-box;
width: 150px;
border: 5px solid blue;
align-self: center;
background-color: red;
display: flex;
flex-flow: column;
max-height: 100%;
}
.content {
/* It should be possible to scroll this element when it get too big in height*/
background-color: grey;
flex: 1;
}
The code is hosted on JSFiddle: https://jsfiddle.net/9fduhpev/3/
To explain the same thing visually, here is the current situation:
Here is what I want:
Use overflow-y: auto;.
Read this: http://www.w3schools.com/cssref/css3_pr_overflow-y.asp
body {
margin: 120px;
}
.flex-container {
display: flex;
width: 200px;
height: 200px;
border: 1px solid black;
justify-content: center;
}
.flex-item {
box-sizing: border-box;
width: 150px;
border: 5px solid blue;
align-self: center;
background-color: red;
display: flex;
flex-flow: column;
max-height: 100%;
}
.content {
background-color: grey;
flex: 1;
overflow-y: auto;
}
<div class="flex-container">
<div class="flex-item">
<header>Header</header>
<div class="content">
A
<br>B
<br>C
<br>D
<br>E
<br>F
<br>G
<br>H
<br>I
<br>J
<br>K
<br>L
</div>
<footer>Footer</footer>
</div>
</div>
I suggest you give it overflow: auto. With that it will be scrollable when needed.
body {
margin: 20px;
}
.flex-container {
display: flex;
width: 200px;
height: 200px;
border: 1px solid black;
justify-content: center;
}
.flex-item {
box-sizing: border-box;
width: 150px;
border: 5px solid blue;
align-self: center;
background-color: red;
display: flex;
flex-flow: column;
max-height: 100%;
}
.content {
background-color: grey;
flex: 1;
overflow: auto;
}
<div class="flex-container">
<div class="flex-item">
<header>Header</header>
<div class="content">
A
<br>B
<br>C
<br>D
<br>E
<br>F
<br>G
<br>H
<br>I
<br>J
<br>K
<br>L
</div>
<footer>Footer</footer>
</div>
</div>
I would do something like this:
.content {
height: 100%;
overflow:auto;
background-color: grey;
flex: 1;
}
https://jsfiddle.net/9fduhpev/4/