How to fix css height of dynamic body and dynamic footer - html

Simply put I have 3 elements,
<div>
<Header/>
</div>
<div>
<Body/>
</div>
<div>
<Footer/>
</div>
The header is a static but undefined height.
The body is an accordion that when expanded should overflow into a scroll bar
The footer is also an accordion that should always be showing but can minimize to only show its header rather than header + content.
What I need to have happen is to have the header always displayed in full, have the accordionFooter always display as much as it wants (whether header + content, or just header), and finally let the bodyAccordion display as much as it can and then overflow into a scroll bar.
Here's what I have so far.
Container: {
height: '100%',
minHeight: '100%',
display: 'flex',
flexDirection: 'column'
},
SectionContainer: {
flex: '1',
display: 'flex',
flexDirection: 'column',
position: 'relative'
},
bodyAccordion: {
overflowY: 'auto'
},
footerAccordion: {
position: 'absolute',
bottom: '0px',
right: '0px',
left: '0px'
}
The html is considerably more complex so here is a simplified version
<div className={Container}>
<MyHeader/>
<div className={SectionContainer}>
<div className={bodyAccordion}>
<MyAccordion/>
</div>
<div className={footerAccordion}>
<MyFooterAccordion/>
</div>
</div>
</div>
When the above code runs the bodyAccordion will overflow into the footeraccordion rather than increasing the size of the scrollable wheel.
Here's a jsFiddle that shows the issue
https://jsfiddle.net/jackyFrosty/mwz62bh9/2/

You need to to asign in your container class min-height:100vh. It happens because your 100% is equal to your child's labels

var headerheight= document.querySelector("header").offsetHeight;
var footerheight= document.querySelector("footer").offsetHeight;
var contentheight = window.innerHeight -(footerheight+headerheight);
document.querySelector(".content").style.height= `${contentheight}px`;
*{
margin:0;
padding:0;
}
header{
height:100px;
background-color:red;
}
footer{
height:50px;
background-color:yellow;
}
.content{
background-color:skyblue;
width:100%;
overflow-y:scroll;
}
.inner{
height:500px;
width:50%;
margin:0 auto;
background-color:white;}
<header>header</header>
<div class="content">
<div class="inner">body</div>
</div>
<footer>footer</footer>
i used javascript to get header and footer height so u can calculate the body height for remaining screen height !

When the above code runs the bodyAccordion will overflow into the footeraccordion rather than increasing the size of the scrollable wheel.
This is happening because you have given position: absolute to your footer. Get rid of it and the bodyAccordion will stack over your footer. If you want the scroll to work, you should restrict the height of your bodyAccordition. Currently there's no restriction on it. As Sergio has explained in his answer, it will be better if you go with 100vh instead of 100%
let the bodyAccordion display as much as it can and then overflow into a scroll bar
Finally for it, get rid of flex:1. This will make your bodyAccordition to take up maximum space above footer.
Hope it helps. Cheers!

Thanks for the answers everyone,
I was able to figure this out by using the following
<div className='header'>
<MyHeader/>
</div>
<div className='container'>
<div className='content'>
<MyContent/>
</div>
<footer className='footer'>
<MyFooter/>
</footer>
</div>
container: {
position: 'relative',
height: 'calc(100vh - 95px)',
display: 'flex',
flexDirection: 'column'
},
header: {
height: '35px',
width: '100%'
},
content: {
overflowY: 'auto',
flex: '1'
},
footer: {
marginBottom: '0px',
textAlign: 'left'
}

Related

How to show scrollbar without providing fixed height to inner container with outer container having position fixed

I want to show scrollbar without providing fixed height to inner container with outer container having position fixed.
I am facing an issue that if I provide to fixed height to the innerContainer. And when I check the responsiveness and change the height of the window the outerContainer with position fixed hides the content of innerContainer.
// OUTER CONTAINER
<div style={ { width: "250px", zIndex: 5, position: "fixed", right: "2rem" } }>
<div style={ { width:"100%, height: "100px" } }>
// having some other content
</div>
// INNER CONTAINER
<div style={ { width: "100%", height: "400px", overflowY: "auto" } }>
// overflowing content inside the container
</div>
</div>
Is there any solution please help me. I will be very thnkfull for time and help.
add to the outer container:
display: "flex", flexDirection: "column"
and then you can remove the height of the inner container.

How to have a div fixed only inside one div and change to position: absolute when it starts overlapping with following div

Say I have three divs like following:
<div class="wrapper">
<div class="container">
container1
<div class="element">
fixed
</div>
</div>
<div class="container2">
container2
</div>
</div>
I want div: element to be fixed when it is inside div: container, but its position should become absolute when div: container2 becomes visible, it should not overlap with div - container2, but scroll away at that time with div: container.
A pure CSS solution is preferable, but if not possible I may go for a JS or jquery solution. I have created a fiddle for this, and tried some solution suggested here, which are not working.
What I would suggest is to use javascript to recognize when the scrolling is at a certain point with window.pageYOffset
When it reaches your desired window Y Offset you can start an event that modifies the css value of the positioning from fixed to absolute (by setting the parent container to relative) and bottom at 0.
Check out this jsfiddle https://jsfiddle.net/zq0kkkcx/2/
Also, this is the code that I'm talking about:
document.addEventListener("scroll", function(event) {
if(window.pageYOffset >= 1200){
console.log("1200");
// this is where you want your element to become absolute
// positioned to his parent container
// write your css changes here and apply them to elements
// add relative to container and absolute with bottom 0 to element
} if (window.pageYOffset <= 1200){
console.log("<1200");
}
});
If you want a CSS solution, here is a trick that you can do using z-index. Other than this there is a JS solution.
.wrapper {
width:100%
}
.container {
width:300px;
margin:0 auto;
height:1200px;
background:#ccc;
position: relative;
z-index: -1;
}
.container2{
width:300px;
margin:0 auto;
height:1200px;
background:#fcf;
z-index: 1;
}
.element {
background:#f2f2f2;
position:fixed;
width:50px;
height:70px;
margin-left:250px;
border:0px solid #d6d6d6;
}
<div class="wrapper">
<div class="container">
container1
<div class="element">
fixed
</div>
</div>
<div class="container2">
container2
</div>
</div>
You're looking for a sticky header. There is currently no way to make a header sticky at an arbitrary scroll position using pure CSS - you'll have to look into a JavaScript solution to accomplish that.
Yes, it is 100% possible to do this without any JavaScript
I updated your fiddle
Markup should be like this
<div class="wrapper">
<div class="outer-scroller">
<div class="scroll-container">
container1
<div class="fixed-header">
fixed
</div>
</div>
</div>
<div class="last-container">
container2
</div>
</div>
and css
.wrapper {
width: 100%;
height: 300px;
}
.outer-scroller {
height: 140px;
overflow-y: scroll;
}
.scroll-container {
padding-top: 70px;
width: 300px;
height: 1200px;
background: #CCC;
}
.last-container {
width: 300px;
height: 600px;
background: #FCF;
}
.fixed-header {
background: #F2F2F2;
position: absolute;
width: 300px;
height: 70px;
top: 0;
pointer-events: none;
}
You'll see I've added an outer-scroller div.
The next bit is changing your CSS slightly
The new outer-scroller div is double the height of your fixed-header (for the purposes of this example) and it has an overflow-y: scroll on it.
The container inside there is still the same.
The next change is turning your position: fixed into a position: absolute and then adding padding to the top part of the div you want to scroll in order to push its content "below" the new "fixed" header.
Scrolling over the outer-scroller div then makes its content scroll, and because its height is set with an absolute element on top it then scrolls "under" the fixed header.
Once the bottom of its child content scroll-container is reached, the whole page then continues scrolling, and you get the illusion of the header disappearing.
The last bit is pointer-events: none on the header so that it doesn't scroll away when the cursor is over it (but the div below does)

how to fix footer at bottom gap without using height fixed?

I want to fix my footer at the bottom gap. I think content is less then this problem repeated and content full problem solved but I want to content less does not shows gap I'm using same footer remaining pages so help me any one.
If content is less, why not simply fix it at the bottom. I mean its the dirtiest hack possible.
If you want something clean, look into sticky footer.
$(function(){
function adjust(){
var winH = $(window).height(),
docH = $('document').height();
if(docH > winH){
//leave it
}else{
$('.footer').addClass('fix-footer');
}
}
$(window).on('resize',adjust);
})
.fix-footer{position:fixed; bottom:0; left:0; width:100%;}
The simplest way to do this is by using Flexbox. The flex property specifies how much the item will grow to fill up the remaining space.
The container needs to be set to display: flex, and we set min-height: 100vh for the body so that it fills up at least 100% of the viewport height.
CSS
body {
display: flex;
min-height: 100vh;
flex-direction: column;
}
main {
flex: 1;
}
HTML
<body>
<main>Main content goes here</main>
<footer>Footer goes here</footer>
</body>
Use .main class as a container put all your body data in main container
<html>
<head>
<style>
body {
margin:0;
display: flex;
height: 100vh;
flex-direction: column;
display:-ms-flexbox;
}
.main {
flex: 1;
}
</style>
</head>
<body>
<div class="main">Put you form here</div>
<div class="footer">Footer goes here</div>
</body>
</html>
<div class="footer"></div>
css
.footer {
position: absolute;
right: 0;
bottom: 0;
left: 0;
padding: 1rem;
}
Position-absolute:
This is a very powerful type of positioning that allows you to literally place any page element exactly where you want it. You use the positioning attributes top, left bottom and right to set the location.
Position-fixed:
A fixed position element is positioned relative to the viewport, or the browser window itself. The viewport doesn't change when the window is scrolled, so a fixed positioned element will stay right where it is when the page is scrolled,

Scroller with dynamically sized headers/footers

What I'm looking for is to have a container div with any number of headers and footers which would then have another scrolling div in between the various headers/footers. The catch is here that the headers and footers can't scroll and the container/headers/footers can take any height depending on their content.
I've only been able to get this working with a statically sized header/footer. In the code I've added the problem I've come across: the text in the header/footer may wrap, which will bring it to two lines. So the header should grow to allow this extra line and the content should shrink to give space to the header. Is there any way to do this without using javascript? I will know the number of headers/footers ahead of time if that helps.
This is going to be a component in a page possibly with one or more per page, for example in a 2x2 setup where each takes up a 4th of the browser window. The functionality is mainly needed as the width of the browser might change causing the header content to break a new line. This could be done pretty easily with javascript but I've always heard that resize event handlers are evil.
For example if my wrapper is 600px high, I may have 2 headers and 1 footer. Lets say the first header's content causes it to break to a new line, but the second header's doesn't. So the first headers height is 20px where the second's is 10px. And lets say the footer's content also causes a line break and thus has 20px height. This gives us 50px worth of headers and footers so now the height of the scroller should be 550px.
Ascii Art:
____________________________________________
| HEADER 1 |
|________breaks to new line__________________|
|____________________________HEADER2_________|
| | ||
| | ||
| This is my scroller | ||
| | ||
| | ||
| | ||
|_________________________________________|_||
| Some |
|_____Footer_________________________________|
HTML:
<div class="wrapper">
<div class="header">
Some<br/>
Header
</div>
<div class="scroller">
Content<br />
Content<br />
Content<br />
Content<br />
...
</div>
<div class="footer">
Some<br/>
Footer
</div>
</div>
CSS:
body{
height:100%;
}
.wrapper{
height:400px;
border-left:1px solid red;
}
.header, .footer{
background-color: #EEE;
height:27px;
}
.scroller{
height:calc(100% - 54px);
background-color: #CCC;
overflow:auto;
}
the red border is to show how far the wrapper goes down, so the footer doesn't show up below. I did this instead of overflow: hidden simply for debugging.
http://jsfiddle.net/yKTdz/4/
Achieved with pure CSS
(not even CSS3), by mixing table display with relative and absolute positioning.
Running Demo: http://jsfiddle.net/x4vhW/
HTML
<div class="wrapper">
<div class="tr stretch">
<div class="td">a header</div>
</div>
<div class="tr">
<div class="td">
<div class="contentWrapper">
<div class="content">
content 0
...............
...............
...............
content 29
</div>
</div>
</div>
</div>
<div class="tr stretch">
<div class="td stretch">a footer</div>
</div>
</div>
CSS Dark Magic(tm)
.wrapper {
height : 200px;
width : 200px;
display : table;
}
.tr { display : table-row; }
.td { display : table-cell; }
.stretch { height : 1%; }
.contentWrapper {
position : relative;
overflow-y : scroll;
height : 100%;
}
.content {
position : absolute;
right : 0;
left : 0;
}
Note: the stretch class is used in order to prevent headers and footers to grow if content has a small content; with stretch, they will auto-fit.
And finally, according to CanIUse, it is supported by almost all browsers, including IE8.
Building on DMoses answer, this solution involves just a bit more jquery, but it removes the issue of the scrollbar being slightly hidden by the footer/header
the jQuery:
$(document).ready(function(){
$('.scroller').css("margin-top", $('.header').height());
var height = $('.wrapper').height() - ($('.footer').height() + $('.header').height());
$('.scroller').css("height", height);
});
jsfiddle.net/XSADu/5/
I took Matt Cooper's solution and updated it a bit. This resolves the inability to add more than one widget to a page, and also the footer sizing issue.
http://jsfiddle.net/XSADu/10/
Steps:
Make the wrapper relative so that absolute children can be position
Make header,footer,scroller absolute. Position the footer at the bottom
Add javascript to size the scroller top/bottom.
CSS
.wrapper{
height:400px;
border-left:1px solid red;
position: relative;
}
.header, .footer, .scroller {
background-color: #EEE;
position:absolute;
width: 100%;
}
.footer {
bottom: 0;
}
.scroller{
background-color: #CCC;
overflow:auto;
}
JS
$(document).ready(function(){
$('.scroller').css("top", $('.header').height());
$('.scroller').css("bottom", $('.footer').height());
});
NOTE: If the header/footer sizing are dynamic, you may want to give them some max heights as a percentage of the wrapper, so that the content isn't hidden.
This can now be done using CSS grids pretty easily. without the need of an filler elements even.
If you want multiple headers, simply put a few divs in there, or make the "header" div a flexbox if that's what you want.
HTML stays the same:
<div class="wrapper">
<div class="header">
Some<br/>
Header
</div>
<div class="scroller">
Content<br />
Content<br />
Content<br />
Content<br />
...
</div>
<div class="footer">
Some<br/>
Footer
</div>
</div>
CSS:
.wrapper{
height:400px;
border-left:1px solid red;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: [header] auto [content]1fr [footer]auto;
}
.header{
background-color: #EEE;
grid-row: header;
}
.footer{
background-color: #EEE;
grid-row: footer;
}
.scroller{
background-color: #CCC;
overflow:auto;
grid-row: content
}
http://jsfiddle.net/yKTdz/15/
There's no way to do this with just Css, You'd need to use Javascript to check the height of the header and footer when the page loads and adjust things accordingly. Otherwise when you use position:fixed you'll get some overlap. See the Attached fiddle! http://jsfiddle.net/XSADu/
I use jQuery to adapt the padding-top on the scroller on document ready. like so
$(document).ready(function(){
$('.scroller').css("padding-top", $('.header').height());
});
As stated by Matt Cooper, I don't think there's a css pure solution. Here's my attempt: jsfiddle
var CalcHeight = function() {
this.init = function() {
var totHeight = $('body').height();
var componentsHeight = $('.headers').height() + $('.footers').height();
var diff = totHeight - componentsHeight;
$('.hider').css({
height: diff
});
}
this.init();
}
var calcHeight = new CalcHeight;

Height of Browser Window and Divs

I am currently trying to build a website with a banner of a fixed height (100px) at the top, and I want the rest of the content to fill the rest of the page. I have it so that I have the banner is in a div, and the rest of the page in another div, and I want the rest of the page to be the height less 100px (100% - 100px). Obviously you cannot mix % and px when it comes to height. However, is it possible to define a variable to be the widow height (100%) minus the banner height (100px) and then use this to define the height of my remaining div.
I am new to css, html and hardly know any other languages, so please try to keep answers simple, as I am a simple person!
Height is dynamic so that as you add content to your "content section", so will the size of the contianer thats holding it.
The short answer is, dont set a height for your "content section".
<div style="height: 100px">
Your banner
</div>
<div>
Body
</div>
You can just use 100% as the height of your content div - it will stretch to take up the space from your banner to the bottom of the screen.
An important part is to set the height of html and body to 100%:
HTML
<html>
<head>
<title>Foo</title>
</head>
<body>
<div id="banner"></div>
<div id="content"></div>
</body>
</html>
CSS
#banner {
height: 100px;
background-color: #ccc;
}
#content {
height: 100%;
background-color: #000;
}
body {
height: 100%;
}
html {
height: 100%;
}
See demo here: http://jsfiddle.net/yHFjh/
Use window.innerHeight / document.documentElement.clientHeight property
<div id="banner">banner</div>
<div id="content">content</div>
<script>
if(navigator.userAgent.toLowerCase().indexOf("msie") > -1){
document.getElementById("content").style.height = document.documentElement.clientHeight - document.getElementById("banner").offsetHeight + "px";
} else {
document.getElementById("content").style.height = window.innerHeight - document.getElementById("banner").offsetHeight + "px";
}
</script>
Create a html and body of height 100%. Position the banner absolute. Add a content div below your banner and set it's min-height to 100%. This content will be behind the banner, but will be at least 100%. Add a div in the content with a padding-top of the height of the banner to prevent content to end up underneath the banner.
HTML:
<div id="banner"></div>
<div id="content">
<div id="main">
Lorem Ipsum is simply dummy text..
</div>
</div>​
CSS:
html, body { height: 100%; }
#banner { position: absolute; height: 100px; width: 100%; background: green; }
#content { min-height: 100%; background: yellow; }
#main { padding-top: 100px; }​
http://fiddle.jshell.net/pY6dc/