Display:flex and scrolling inner divs - html

https://jsfiddle.net/wqmm0kxb/5/
html:
<div class="full">
<header><h1>header stuff</h1></header>
<section>
<div>
{lots and lots of content}
</div>
<div>b</div>
<div>c</div>
</section>
</div>
css:
.full {
position: fixed;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
header {
flex: 78px 0 0;
background: #ececec;
color: black;
padding-left: 33px;
}
section {
flex: auto 1 1;
display: flex;
align-items: stretch;
> div {
flex: auto 1 1;
overflow-y: auto;
}
}
}
My outer container, '.full', takes up the full width and height of the screen, and uses display:flex to make sure that the header + section children stretch to take up all the space beneath them.
Now, what I want is naturally for the header to take up 78px and the section to take up {full height - 78px} -- but without doing anything like calc preferrably. And I want to be able to scroll in the div children of section, without scrolling affecting the other divs or the page as a whole.
This works perfectly in Chrome, but open up my fiddle in firefox, edge, ie and it doesn't work as expected. Section gets the height of {lots and lots of content} rather than only taking the remaining space of '.full'
What should I do to achieve the Chrome-like layout that I'm expecting?

Apply the overflow-y:auto for your section also, that will fix the issue in IE and Firefox.
section {
flex: auto 1 1;
display: flex;
align-items: stretch;
overflow-y: auto;
> div {
flex: auto 1 1;
overflow-y: auto;
}
}
Fiddle DEMO

Related

Flex 1 : height is not fixed to remaining space

I have a "boxHeader" which height is fixed to 64px and a "boxcontent" which I want height to be fixed to the remaining space.
My problem: if the height of the children in the "boxContent" exceed the height of the remaining space, it will also increase the height of "boxContent". And I don't want that, I want the children of "boxContent" to respect the max size (and add scroll)
Edit: The children inside "boxContent" are React Components, I have a "Sider" of Ant Design containing multiple Panel's Collapse AND I have a Content side by side. I want to add a scroll bar on the Sider AND on the Content so both Sider and Content have overflow-y: auto
Can you help me ?
Here the code
<div id="container">
<div id="boxHeader">
<HeaderArea />
</div>
<div id="boxContent">
{...}
</div>
</div>
#container {
display: flex;
flex-flow: column;
height: 100% !important;
min-height: 100% !important;
#boxContent {
/* height: calc(100vh - 64px); this works, but i don't want to calcule the size*/
flex-grow: 0;
flex-shrink: 0;
flex-basis: auto;
background: white;
}
#boxHeader {
flex: 0 0 64px;
}
body{
height: 100vh; /*100% is also tested*/
}
You can give #boxContent max-height and overflow-y: scroll with these two I think it is going to work. But If it is not can you add your HTML so that I can look and fix it. I hope this line of code fixes your problem.
#boxContent {
max-height:300px; //(for example)
overflow-y: auto;
flex-grow: 0;
flex-shrink: 0;
flex-basis: auto;
background: white;
}

Children of overflowing flex container exceed container [duplicate]

This question already has answers here:
Can't scroll to top of flex item that is overflowing container
(12 answers)
Closed 4 years ago.
I've been on this for a while now and tried a lot of the solutions I've seen across different Stackoverflow questions / blogposts / ... But I honestly can't figure out what's going wrong.
I've got a flexed div with two divs in there. The top div A has a fixed height, the other div B fills the rest using flex: 1;. If the screen is resized and it's smaller than the height of A + B together, then B will start overflowing. I want it to scroll, but I also want the content to be fully visible when scrolling. For some reason which I can't figure out, the content renders out of the top of div B as you can see in this screenshot of my fiddle:
Some of the previously asked questions got me somewhere. For example setting the body to height: auto;, but then when my screen is bigger than A + B it can't be center aligned anymore. min-height: 0; also doesn't seem to help in this case.
How can I make sure my container overflows but will fully show the content of it?
You can solve the issue by giving .second:
flex-basis: auto;
flex-shrink: 0;
Or, with shorthand: flex: 1 0 auto;
Working example:
html, body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
body {
display: flex;
flex-direction: column;
}
.second {
flex: 1 0 auto;
background: blue;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
min-height: 0;
overflow: auto;
}
.container {
display: flex;
flex-direction: column;
width: 100%;
max-width: 500px;
min-height: 0;
/* added this to make it obvious. Obviously, not needed */
padding: 2rem 0;
}
.container-child {
height: 110px;
background: green;
width: 100%;
}
.container-child:not(:last-child) {
margin-bottom: 30px;
}
<div class="second">
<div class="container">
<div class="container-child"></div>
<div class="container-child"></div>
<div class="container-child"></div>
</div>
</div>
I added some top and bottom padding to .container to make it obvious that it's working - but it's not needed.
Now let's look at why this is happening. When you apply .second { flex:1; } it means:
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0%;
... which allows it to have a smaller size than its contents.
Whenever you have a bigger child centered in a smaller parent, the browser won't provide a scrollbar to top (or to left, when horizontal), because then , if the top of the parent and the top of the child coincide and the child is bigger than the parent, the child is no longer centered, is it?
The same happens when using other centering techniques and you center a bigger child in a smaller parent.
To fix the problem, you need to prevent the child from outgrowing the parent.
In this case, it meant sizing .second based from its content (flex-basis: auto) and not allowing it to shrink: (flex-shrink: 0;).
To better visualize the issue, consider this example:
.left, .right {
position: relative;
border: 1px solid red;
padding: 1rem 5rem;
}
.left {
left: -5rem;
}
.right {
right: -5rem;
}
<div class="left">
I'm taken left
</div>
<div class="right">
I'm taken right
</div>
If the browser provided scrollbars to allow you to scroll to beginning of .left, it would mean that left: -5rem did not apply. I hope that makes sense, I can't explain it better.

column flex with height 0 padding trick

I have 2 divs that are placed on top of each other. For purposes of alignment, I am using display: flex and flex: column on the div containing these two divs. However, the first div uses the "height 0 padding" trick for videos. The problem I'm having, is that when using flex: column and change the width of the screen, the height doesn't change (and I want the height to change so that it matches the ratio for the video). What ends up happening is that the div stays the same, and the video shrinks within it and it looks ugly because there is extra background.
Plunker: https://plnkr.co/edit/TaeF5f8VufJWPU3GRZPr?p=preview
(in short, I want it such that when I change the width of the browser, the red div's height gets smaller)
CSS
/* Styles go here */
body {
height: 100%;
}
.container {
height: 80vh;
display: flex;
flex-flow: column;
}
.video {
flex: none;
height: 0;
padding-bottom: 30%;
background-color: red;
width: 80%;
}
.next-content {
flex: 1 0 auto;
width: 80%;
background-color: blue;
}
HTML:
<body>
<h1>Hello Plunker!</h1>
<div class="container">
<div class="video"></div>
<div class="next-content"></div>
</div>

get the height of the previous element

Can i get the height of the previous element using only CSS?
I am using calc() function to set dynamically height of the div B.
#b{
height:calc(100vh - heightOfPreviousElement);
}
I need to know the height of the previous element.
what i know is that, 100vh is equal to 100% of the screen height.
I used the code in the answer below.Using flex,
I have one problem. The height of the color orange become smaller.
You can easily achieve the effect you're looking for using flexbox. The trick is to allow the blue container (the one with the flexible height) to grow in size whenever the need arises, using flex: 1 1 auto, which is simply a shorthand for:
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
See proof-of-concept code snippet below:
body {
padding: 0;
margin: 0;
}
.wrapper {
display: flex;
flex-direction: column;
flex-wrap: no-wrap;
align-items: center;
justify-content: center;
height: 100vh;
}
.wrapper > div {
width: 100%;
}
#c1 {
background-color: #880015;
color: #fff;
height: 60px;
margin-bottom: 10px;
}
#c2 {
background-color: #ff7f27;
}
#c3 {
background-color: #00a2e8;
flex: 1 1 auto;
margin-bottom: 10px;
}
<div class="wrapper">
<div id="c1">height: 60px</div>
<div id="c2">height: auto (determined by content?)</div>
<div id="c3">flexible height</div>
</div>
No you can't select a previous element in CSS.
You might be interested in JQuery Prev OR Parents method for selecting previous element and apply height using .css() method?

Make two flex items each 50% height of parent

I am using css flex layout to build a dashboard and would like to put two widgets (one on top of the other) inside of a flex item and make them 50% height of their parent at all times (regardless of content). So if my html is:
<div class="flex-container">
<div class="flex-item">
<div class="widget" id="w1">
widget 1 content
</div>
<div class="widget" id="w2">
widget 2 content
</div>
</div>
</div>
and my css looks like:
.flex-container {
display: flex;
flex-direction: column;
}
.flex-item {
flex: 1;
}
How can I get the two .widgets to always occupy 50% height of .flex-item?
I've tried:
.flex-item {
flex: 1;
display: flex;
}
.widget {
flex: 1;
}
But this only works when the content in both widgets are the same.
I've worked up a more elaborate jsfiddle to better illustrate my issue.
Thanks in advance!
When you say that flex: 1 only works when the content in both widgets are the same, that is not correct. That would defeat the purpose of flex: 1.
flex: 1 tells flex items to distribute container space evenly among themselves. If there are four flex items with flex: 1, each will take 25%. Three would take 33.33%. And two flex items will take 50%. This is regardless of content quantity.
See this illustration: DEMO
The problem you're having is not clear in the code you posted in the question. However, it's apparent in your fiddle demo.
You have a main container with a height: 400px. You also have a rule adding 10px padding all-around to your divs. This adds 20px height to each div. You also have a header with height: 2em.
When you account for the extra heights the layout works.
Try these adjustments:
HTML (no changes)
CSS
div {
box-shadow: inset 0 0 0 1px rgba(30, 100, 200, 0.5);
padding: 10px; /* sneaky villain */
font-family: arial;
}
h1, p { margin: 0; }
#main-wrapper {
height: 400px; /* primary height */
display: flex;
flex-direction: column;
}
#header {
flex-shrink: 0;
height: 2em; /* header height */
}
#main-column-wrapper {
flex: 1;
display: flex;
flex-direction: row;
height: calc(100% - 2em - 20px); /* primary height - header height - padding */
}
#side-column {
width: 20%;
flex-shrink: 0;
}
#main-column {
flex: 1;
display: flex;
flex-direction: column;
height: calc(100% - 40px); /* main-column-wrapper height - padding (2 divs) */
}
#widget1,
#widget2 {
flex: 1;
flex-shrink: 0;
overflow: auto;
}
Revised Fiddle
Another option would be to use box-sizing: border-box to adjust for the padding. Learn more here: https://css-tricks.com/box-sizing/