How to make child div scrollable when it exceeds parent height? - html

I have 2 child divs nested in a parent div in row-column pattern: the parent is a column, and the children are rows.
The upper child div is of variable height, but is guaranteed to be less than the height of the parent div.
The lower child div is also of variable height. In some cases, the heights of the child divs will make the lower child div exceed the parent. In this case, I need to make the lower div scrollable. Note that I want only the lower div to be scrollable, not the whole parent div.
How do I handle this?
See attached jsfiddle for case example: http://jsfiddle.net/0yxnaywu/5/
HTML:
<div class="parent">
<div class="child1">
hello world filler
</div>
<div class="child2">
this div should overflow and scroll down
</div>
</div>
CSS:
.parent {
width: 50px;
height: 100px;
border: 1px solid black;
}
.child1 {
background-color: red;
}
.child2 {
background-color: blue;
}

Because this post is still ranking very high in Google, I'd like to post a better solution using flexbox. Actually this is very simple.
Use display: flex, flex-direction: column and overflow: hidden for parent and overflow-y: auto for child.
.wrapper {
display: flex;
flex-direction: column;
overflow: hidden;
}
.scrollable-child {
overflow-y: auto;
}
Here's the pen:
https://codepen.io/pawelsas/pen/vdwjpj

Overflow only works when you give it a value to overflow when greater than. Your value is relative to how big the top is, so using jQuery, grab that value then subtract from the parent.
$(document).ready(function() {
$(".child2").css("max-height", ($(".parent").height()-$(".child1").height()));
});
and add overflow's to the children
.child1 {
background-color: red;
overflow: hidden;
}
.child2 {
background-color: blue;
overflow: auto;
}
http://jsfiddle.net/m9goxrbk/

Use overflow property:
.parent {
width: 50px;
height: 100px;
border: 1px solid black;
overflow: auto;
}
jsFiddle
EDIT:
if you want only second div to be scrollable, you need to change it height to 30px so child1 and child2 will exactly fit the parent height and add overflow property there:
.parent {
width: 50px;
height: 100px;
border: 1px solid black;
}
.child1 {
height: 70px;
background-color: red;
}
.child2 {
height: 30px;
background-color: blue;
overflow: auto;
}
jsFiddle

Related

How to make child's height the same as parent

In my application I have a parent div and two other child divs inside this parent. One of these child div's has a set height while the other does not. I want to make the div who does not have a set height to be the same as the parent.
An illustration of what I am referring to can be seen in this jsfiddle: https://jsfiddle.net/ll3333/2Lxuj8wk/10/.
In this example, I want the div with class "child-2" to be the same height as the parent. For some reason, setting its height to "100%" does not seem to be working.
Thanks!
From the MDN on height:
The percentage is calculated with respect to the height of the generated box's containing block. If the height of the containing block is not specified explicitly (i.e., it depends on content height), and this element is not absolutely positioned, the value computes to auto. A percentage height on the root element is relative to the initial containing block.
The 100% of the height property that you are setting is telling the element to take up 100% of the parent's height (and this chains all the way to the first absolutely-specified height). However, you never actually specify the height of the parent element itself.
To resolve this, you'll need to set a height of 300px on the parent. Note that this means that the other element could also make use of height: 100%, which would allow you to save on code (though this is not shown below).
.parent {
display: flex;
flex-direction: row;
border: 1px solid purple;
height: 300px;
}
.child-1 {
height: 300px;
background-color: blue;
width: 40px;
}
.child-2 {
height: 100%;
background-color: red;
width: 40px;
}
<div class="parent">
<div class="child-1">
</div>
<div class="child-2">
</div>
</div>
you can add align-items: stretch; for .parent and remove height: 100%; in .child-2
.parent {
display: flex;
align-items: stretch;
flex-direction: row;
border: 1px solid purple;
}
.child-1 {
height: 300px;
background-color: blue;
width: 40px;
}
.child-2 {
background-color: red;
width: 40px;
}
<div class="parent">
<div class="child-1">
</div>
<div class="child-2">
</div>
</div>

Unexpected size for flex item child

I want to build a column layout with a menu, then a header, then a content container using flexboxes.
I know how to build it in other techs using fixed sizes, calc etc... But have troubles with flexboxes.
Here is a JsFiddle
I have this:
<div class="layout">
<div class="menu">
Menu
</div>
<div class="header">
Header
</div>
<div class="content">
<div class="scrollable-content">
...
</div>
</div>
</div>
.layout {
overflow: hidden;
border: solid;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.menu {
overflow: hidden;
border: solid red;
flex-grow: 0;
flex-shrink: 0;
}
.header {
overflow: hidden;
border: solid green;
flex-grow: 0;
flex-shrink: 0;
}
.content {
overflow: hidden;
border: solid blue;
flex-grow: 1;
flex-shrink: 1;
}
.scrollable-content {
overflow: auto;
height: 100%;
width: 100%;
}
As you can see on the JsFiddle, with this code, the .scrollable-content is actually never scrollable, because even while using height: 100% it becomes much larger than his parent div. How can I constrain that div's height to the parent's height?
Note: I know I could put the overflow: auto to the parent .content directly, but for reasons specific to my app I really don't want to: please only submit solutions that do not modify the html structure or change the scrollable container because I already know these solutions. I'm more interested to learn why my approach did not work and how it could be fixed (or not?)
Obviously the content that can be scrolled has a dynamic height and is not a fixed value of 450px like in my JsFiddle.
You could remove height: 100% from .scrollable-content, and then change the display of .content to flex:
Updated Example
.content {
overflow: hidden;
border: solid blue;
flex-grow: 1;
flex-shrink: 1;
display: flex;
}
.scrollable-content {
overflow: auto;
width: 100%;
}
You're missing a height: 100% on .content.
Since you're using percentage heights, you need to specify a height for all parent elements of the .scrollable-content.
For a more detailed explanation see: Working with the CSS height property and percentage values
You are almost there.
.content {
overflow: hidden;
border: solid blue;
flex-grow: 1;
flex-shrink: 1;
height:450px; //adjust accordingly.
}
The scroll activates once a height a limited height has been reached. In your case since you have the scrollable area limited to the parent's (content) height, you did right by giving it height: 100%....but....100% of what?
So, all you need is give the content class a stopping point. change the 450px to whatever is more suitable. If you are trying to cover for a gap below that content then the next item should be positioned absolute bottom. (just in case that is what you are tying to get to) I've seen this approach many times and that is usually what follows :)
Here is your updated jfiddle

In CSS, the "margin" of element has no effect for the "height" of its parent?

Following is the snippet (demo on JSFiddle)
#inner {
background-color: yellow;
margin-left: 50px;
margin-bottom: 50px;
}
#outer {
background-color: red;
}
<div id="outer">
<div id="inner">
test
</div>
</div>
As can be seen in the demo, the #inner element has a margin-bottom.
I expected the height of #outer will be large enough to include the outline of #inner margin. And the output will have a red bar below the yellow bar.
However, I found the #outer's height is not changed at all though I added the rule margin-bottom: 50px for #inner.
Does anyone have ideas about this? And is there a way to ensure the content area of parent is large enough to hold the outline of its child's margin?
Also, apart from giving a hack solution, it would be great if the answer can include some explanation or links to related document/article. And why is the margin rule designed like this.
Thanks!
What you are seeing is the collapsing margins problem.
Top and bottom margins of blocks are sometimes combined (collapsed)
into a single margin whose size is the largest of the margins combined
into it, a behavior known as margin collapsing.
Out of the three cases, yours is the case of collapsing margins between parent and child elements.
If there is no border, padding, inline content, height, min-height, or
max-height to separate the margin-bottom of a block with the
margin-bottom of its last child, then those margins collapse. The
collapsed margin ends up outside the parent.
If you add another element just after your parent div you will see that the margin ends up outside of it. The snippet below, shows you the collapsed margin:
#inner { background-color: yellow; margin-left: 50px; margin-bottom: 50px; }
#outer { background-color: red; }
<div id="outer">
<div id="inner">
test
</div>
</div>
<p>You can see the collapsed margin above this text outside of the parent div.</p>
Here is the reference from the specs: http://www.w3.org/TR/CSS21/box.html#collapsing-margins
How to fix this?
The solution is given in the quoted ref text itself above. Just apply any one of these to your parent div - border, padding, height, min-height, or max-height.
Easiest way to fix this would be to add a border to your outer div:
#outer { background-color: red; border: 1px solid gray; }
Better still, apply padding to the parent div instead of the margin on inner one.
#outer { background-color: red; padding-bottom: 50px; }
Examples:
Fiddle (with border): http://jsfiddle.net/abhitalks/rrtfhyky/1/
Fiddle (with padding): http://jsfiddle.net/abhitalks/rrtfhyky/2/
Snippet (with padding):
#inner { background-color: yellow; margin-left: 50px; }
#outer { background-color: red; padding-bottom: 50px; }
<div id="outer">
<div id="inner">
test
</div>
</div>
<p>Some text that follows.</p>
I had the same problem, just add overflow: auto to #outher div and it will fix the parents height
#inner {
background-color: yellow;
margin-left: 50px;
margin-bottom: 50px;
}
#outer {
overflow: auto; /* ADDED */
background-color: red;
}
<div id="outer">
<div id="inner">
test
</div>
</div>
Add This CSS
#inner {
background-color: yellow;
margin-left: 50px;
margin-bottom: 50px;
display: inline-block;
}
give a border to outer div :
#inner {
background-color: yellow;
margin-left: 80px;
margin-bottom: 50px;
}
#outer {
background-color: red;
border:1px solid white;
}
<div id="outer">
<div id="inner">
test
</div>
</div>
I know this common "bug", what I would do if I were you is changing the margin into padding and put it to the outer div:
My solution:
#inner {
background-color: yellow;
}
#outer {
background-color: red;
padding-left: 50px;
padding-bottom: 50px;
}
Also there are 3 other possible fixes:
By #Jenti Dabhi is the add the display:inline-block to the #inner div:
#inner {
background-color: yellow;
margin-left: 50px;
margin-bottom: 50px;
display: inline-block;
}
By #Chris is to add overflow: auto to the #outer div:
#outer {
overflow: auto;
background-color: red;
}
By #Abhitalks is to add a border to your #outer div:
#outer {
background-color: red; border: 1px solid gray;
}
This is a Typography concept,
generally, vertical margins of adjacent elements collapse!
Have a look at this article

Set parent width to width of child aligned to bottom

I am trying to set the width of a div element to the width of it's longest child element, which in this case happens to be a div that I want locked to the bottom of the parent div. I am also not using a fixed height for the parent, because I do not know how big the children will need to be
Here is my html/css:
HTML:
<div id ="header-right">
<div id="content1"></div>
<div id="footer"></div>
</div>
CSS:
#header-right{
background-color: red;
position: relative;
display: inline-block;
height: 300px; /*The actual width is unknown, this is just for example*/
}
#content1{
background-color: blue;
width: 200px;
height: 100px;
}
#footer{
background-color: cyan;
position: absolute;
bottom: 0;
width: 300px; /*Also an unknown value*/
height: 25px;
}
You can have a look at this jfiddle to see what happens:
https://jsfiddle.net/rkdqp9m5/2/
You can see the container div ignores the footer, since it is absolutely positioned.
However, if I do not use absolute positioning for the footer, then I cannot lock the footer to the bottom of the div, as you can see in this jfiddle
https://jsfiddle.net/rkdqp9m5/3/
I want to lock the footer to the bottom of the container, but I also want the parent's width to be based off the footer. I do not want to use tables for this, and I do not wan to used fixed widths or heights, as the container's and the footer's dimensions will be based off of images whose widths I do not know.
Edit: I would also like to keep this strictly in HTML/CSS, if possible
If you're OK with browser requirements of flexbox, you could do:
#header-right {
background-color: red;
padding: 20px 0px 0px 0px;
height: 300px;
display: inline-flex;
flex-direction: column;
justify-content: space-between;
}
#content1 {
background-color: blue;
width: 200px;
height: 100px;
align-self: flex-start;
}
#footer {
background-color: cyan;
width: 300px;
height: 25px;
align-self: flex-end;
}
<div id="header-right">
<div id="content1"></div>
<div id="footer"></div>
</div>
JSFIDDLE DEMO with all the necessary vendor prefixes.
Does this help: Relative parent DIV to inherit the width of absolute child DIV
What it suggests is that you can't use pure CSS, but you can use Javascript to achieve what you're trying to do.

Child is larger than parent with max-height. Overflow has no effect

I want to have a parent element which has a maximum height and a child element which fills this parent element. If the contents of the child are exceeding the parent a scrollbar should appear. I tried to solve it like this:
div.parent {
max-height: 50px;
width: 100px;
border: 1px solid black;
}
div.child {
height: 100%;
overflow-y: auto;
}
<div class="parent">
<div class="child">
<div class="some-content">
abcde<br>abcde<br>abcde<br>abcde<br>abcde<br> abcde
<br>abcde<br>abcde<br>abcde<br>abcde<br> abcde
<br>abcde<br>abcde<br>abcde<br>abcde<br> abcde
<br>abcde<br>abcde<br>abcde<br>abcde<br> abcde
<br>abcde<br>abcde<br>abcde<br>abcde<br>
</div>
</div>
</div>
Unfortunately this does not work as expected. The child grows over the parent.
Please respect, that setting overflow-y: auto to the PARENT is NOT an option, as it is suspected to hold other items that should not be scrolled. The child is suspected to fill the space that is left in the parent. See live DEMO for more information.
Live DEMO
As far as i'm aware there is no easy way to do this with CSS. Essentially you're asking the browser to fill the remaining space with the scrollable element. You can do this with JavaScript (this example uses jQuery because I'm lazy):
$('.parent').each(function(){
$(this).children('.child').height($(this).height() - $(this).children('.sibling').height()+"px");
});
http://jsfiddle.net/BUxUe/13/
You can try to use Flexbox.
div.parent {
max-height: 300px;
width: 200px;
border: 1px solid black;
display: flex;
flex-direction: column;
}
div.sibling {
border: 1px solid red;
flex: 0 0 auto;
}
div.child {
overflow-y: auto;
border: 1px solid blue;
flex: 0 1 auto;
}
I'm not sure, if this is a kind of hack. But it seems to solve this problem.
Check this out Fiddle
div.parent {
max-height: 50px;
width: 100px;
border: 1px solid black;
overflow:scroll;
}
div.child {
height: 100%;
}