Make div stay at bottom of page's content all the time even when there are scrollbars - css

I am looking to implement the opposite behaviour to the following question: CSS Push Div to bottom of page. I.e., when content overflows to the scrollbars, I would like the footer to be at the bottom of the page, like Stack Overflow.
I have a div with id="footer" and the following CSS:
#footer {
position: absolute;
bottom: 30px;
width: 100%;
}
This moves the div to the bottom of the viewport - but the element stays there even when you scroll the page down, so it is no longer at the bottom.
How can I make sure the div stays at the bottom of the page's contents even when the content overflows? I'm not looking for fixed positioning, only for the element to be at the bottom of all content.
Image:

This is precisely what position: fixed was designed for:
#footer {
position: fixed;
bottom: 0;
width: 100%;
}
Here's the fiddle: http://jsfiddle.net/uw8f9/

Unfortunately you can't do this with out adding a little extra HTML and having one piece of CSS rely on another.
HTML
First you need to wrap your header,footer and #body into a #holder div:
<div id="holder">
<header>.....</header>
<div id="body">....</div>
<footer>....</footer>
</div>
CSS
Then set height: 100% to html and body (actual body, not your #body div) to ensure you can set minimum height as a percentage on child elements.
Now set min-height: 100% on the #holder div so it fills the content of the screen and use position: absolute to sit the footer at the bottom of the #holder div.
Unfortunately, you have to apply padding-bottom to the #body div that is the same height as the footer to ensure that the footer does not sit above any content:
html,body{
height: 100%
}
#holder{
min-height: 100%;
position:relative;
}
#body{
padding-bottom: 100px; /* height of footer */
}
footer{
height: 100px;
width:100%;
position: absolute;
left: 0;
bottom: 0;
}
Working example, short body: http://jsfiddle.net/ELUGc/
Working example, long body: http://jsfiddle.net/ELUGc/1/

Just worked out for another solution as above example have bug( somewhere error ) for me. Variation from the selected answer.
html,body {
height: 100%
}
#nonFooter {
min-height: 100%;
position:relative;
/* Firefox */
min-height: -moz-calc(100% - 30px);
/* WebKit */
min-height: -webkit-calc(100% - 30px);
/* Opera */
min-height: -o-calc(100% - 30px);
/* Standard */
min-height: calc(100% - 30px);
}
#footer {
height:30px;
margin: 0;
clear: both;
width:100%;
position: relative;
}
for html layout
<body>
<div id="nonFooter">header,middle,left,right,etc</div>
<div id="footer"></div>
</body>
Well this way don't support old browser however its acceptable for old browser to scrolldown 30px to view the footer
plunker

I realise it says not to use this for 'responding to other answers' but unfortunately I don't have enough rep to add a comment onto the appropriate answer (!) but ...
If you are having problems in asp.net with the answer from 'My Head Hurts' - you need to add 'height : 100%' to the main generated FORM tag as well as HTML and BODY tags in order for this to work.

You didn't close your ; after position: absolute.
Otherwise your above code would have worked perfectly!
#footer {
position:absolute;
bottom:30px;
width:100%;
}

I would comment if i could , but i have no permissions yet, so i will post a hint as an answer, for unexpected behavior on some android devices:
Position: Fixed only works in Android 2.1 thru 2.3 by using the following meta tag:
<meta name="viewport" content="width=device-width, user-scalable=no">.
see http://caniuse.com/#search=position

This is an intuitive solution using the viewport command that just sets the minimum height to the viewport height minus the footer height.
html,body{
height: 100%
}
#nonFooter{
min-height: calc(100vh - 30px)
}
#footer {
height:30px;
margin: 0;
clear: both;
width:100%;
}

position: fixed;
bottom: 0;
(if needs element in whole display and left align)
left:0;
width: 100%;

I've solved a similar issue by putting all of my main content within an extra div tag (id="outer"). I've then moved the div tag with id="footer" outside of this last "outer" div tag.
I've used CSS to specify the height of "outer" and specified the width and height of "footer". I've also used CSS to specify the margin-left and margin-right of "footer" as auto. The result is that the footer sits firmly at the bottom of my page and scrolls with the page too (although, it's still appears inside the "outer" div, but happily outside of the main "content" div. which seems strange, but it's where I want it).

I just want to add - most of the other answers worked fine for me; however, it took a long time to get them working!
This is because setting height: 100% only picks up parent div's height!
So if your entire html (inside of the body) looks like the following:
<div id="holder">
<header>.....</header>
<div id="body">....</div>
<footer>....</footer>
</div>
Then the following will be fine:
html,body{
height: 100%
}
#holder{
min-height: 100%;
position:relative;
}
#body{
padding-bottom: 100px; /* height of footer */
}
footer{
height: 100px;
width:100%;
position: absolute;
left: 0;
bottom: 0;
}
...as "holder" will pick up it's height directly from "body".
Kudos to My Head Hurts, whose answer was the one I ended up getting to work!
However. If your html is more nested (because it's only an element of the full page, or it's within a certain column, etc) then you need to make sure every containing element also has height: 100% set on the div. Otherwise, the information on height will be lost between "body" and "holder".
E.g. the following, where I've added the "full height" class to every div to make sure the height gets all the way down to our header/body/footer elements:
<div class="full-height">
<div class="container full-height">
<div id="holder">
<header>.....</header>
<div id="body">....</div>
<footer>....</footer>
</div>
</div>
</div>
And remember to set height on full-height class in the css:
#full-height{
height: 100%;
}
That fixed my issues!

if you have a fixed height footer (for example 712px) you can do this with js like so:
var bgTop = 0;
window.addEventListener("resize",theResize);
function theResize(){
bgTop = winHeight - 712;
document.getElementById("bg").style.marginTop = bgTop+"px";
}

I hit my footer with a margin-top: auto and it did the trick! Im commenting this here just in case it could help any future visitors.

Related

Two divs inside another div and slide left right

I have a div that is masked off in terms of its width. Inside, I have 2 divs of the same width floated, so 100% + 100%. This means that either the left is visible or the right is visible at any one time.
In fact, what I'm trying to achieve is almost exactly the same as this:
jquery slide div within a div
Just one difference though. The height of my parent isn't fixed, it's dependent on the child size. So when I apply position: absolute; to the parent, it all goes pear-shaped.
Any solutions to this? I can use flexbox if necessary as I don't support IE8/9.
CSS would be something like this
.outer-wrap {
overflow:hidden;
position:relative;
width:300px;
}
.middle-wrap {
overflow:hidden;
position:absolute; // this doesn't work because it has no fixed height
left:0;
width:600px;
}
.middle-wrap.open {
right:0;
}
.inner-wrap {
float:left;
width:300px;
}
HTML
<div class="outer-wrap">
<div class="middle-wrap">
<div class="inner-wrap"></div>
<div class="inner-wrap"></div>
</div>
</div>
Another edit: I created a codepen, it's here: http://codepen.io/anon/pen/oxwmex CLick on the two buttons on the far right, they switch between the states
As you noted, your solution doesn't work because .middle-wrap has no fixed height. Try it with the following settings (note: no floats, no absolute positions):
.outer-wrap {
overflow-x: hidden;
position: relative;
border: 1px solid red;
width: 300px;
margin: 0 auto;
}
.middle-wrap {
position: relative;
width: 600px;
left: 0px;
}
.inner-wrap {
display: inline-block;
width: 300px;
vertical-align: top;
}
This will display the left of the two .inner-wraps within the visible part of .outer-wrap. To make the right .inner-wrap visible apply something like
jQuery(".middle-wrap").css("left", "-300px")
to the element or event you use for switching between the two inner-wraps. Or if you want it animated:
jQuery(".middle-wrap").aminmate({left: "-300px"})
(Plus another method to switch back to left: 0px)
The heigth of all elements is automatically adjusted to the heigth of the higher of the two .inner-wrap elements.
P.S. (edit): Erase the style="height:100px;" settings from the inner-wraps in the HTML, just fill them with some content to see it working.

css relative alignment upon image

I am trying to align a div on top of my image. Horizontal alignment works fine, vertical offset however doesn't. Also, the background-color of #studentenlijn is not applied.
HTML Snippet:
<div id="container">
<div id="studentenlijn">STUDENTENLIJN</div>
<img src="http://lsvb.nl/s/lsvbheader.jpg" class="banner" />
</div>
Relevant CSS
#studentenlijn {
width: 10%;
height: 10%;
position: absolute;
top: 30%;
left: 72%;
background-color: #660000;
}
JSFiddle: http://jsfiddle.net/YGeLA/
Any ideas?
Your body had a height of 0, thus affecting the height of the containers within it when you try to specify a percentage height. Another problem was that you had a floating image within your container div, and thus you need to hide the overflow in order for the container to properly calculate the heights of elements within.
I have made some minor changes to your fiddle here:
http://jsfiddle.net/YGeLA/1/
I added:
height: 100%; to the body element
overflow: hidden; to #container which forces the container to respect the height of all elements within it.
The size of your div is:
#studentenlijn {
width: 10%;
height: 10%;
}
So it'll be a % of the parent element. The parent element, your container, is:
#container {
width: 100%;
height: 100%;
}
At this point, your browser can't determine which size should have your block.
So you won't be able to center it (Since you can't center an element which have not a browser-determined size).
You can't see the background-color for the same reason. It is applied, but you won't see your colored block because his size is 0.
Try to solve it, and it would be easier to center your div. In case it doesn't help you, edit your post with your modification :)
the container height is 0px. so you can't give height 100%
you have to set height in px
look at this update
#container {
position:relative;
width:100%;
height:100%;
line-height: 0;
}
.banner {
width:100%;
}
#studentenlijn {
width:200px;
height:30px;
position:absolute;
top:35px;
left:72%;
background-color:#660000;
line-height:30px
}
http://jsfiddle.net/YGeLA/2/

Place div at bottom of viewport without overwriting previous content

I have an outer div, called #wrap, and two inner divs: #container and #footer. Content is inside #container, and is dynamic. There may be a little, there may be a lot.
When content is minimal, the footer div may appear half-way up the page. However, this changes depending on the monitor/resolution. What is 50% from bottom on a large monitor may only be 10% from bottom on a small/cluttered viewport.
If I use this css method:
body,html { height: 100%; }
#wrap { position:relative; min-height:100%; }
#container{ margin:0px 0px 50px 0px; }
#footer { position:absolute; bottom:0px; }
then the page will always extend to use 100% of the viewport and the footer will be at bottom of the viewport - exactly as required.
However, if the content increases (or if a small viewport), the footer may overwrite any content extending into its 130px height -- the footer will not bump down.
Is there a way to remedy this?
Note: I don't wish to use percentages for the footer height as it is fixed at 130px and cannot squish.
Here is a fiddle I've been using to experiment
This is the best example of sticky footer I've seen: http://ryanfait.com/resources/footer-stick-to-bottom-of-page/
UPDATE (April 2017): As the above link has become inoperable (and much time has passed since the original post) I'd like to offer the following solution to this problem:
Permanently fixed:
#container {
padding-bottom: 130px; // ...or more
}
#footer {
bottom: 0;
height: 130px;
position: fixed;
width: 100%;
}
For a dynamically fixed element, check out this jQuery plugin: https://libraries.io/bower/jquery-sticky-header-footer

Trying to set JScrollPane height to 100% without stretching container?

I have a middle container that takes up whatever vertical space is left on the screen. In it, I placed a Jquery scroller that is currently set to 200px:
.scroll-pane
{
width: 100%;
height: 200px;
overflow: auto;
}
.horizontal-only
{
height: auto;
max-height: 100%;
}
However, if I set .scroll-pane height to 100%, it just removes the scrollbar and stretches the whole page.
See JsFiddle here
How can I stop this? Thanks!
Here is my solution to this problem (jsfiddle). It uses markup like this:
<div id="top">...</div>
<div id="wrapper">
<div id="middle">...</div>
</div>
<div id="bottom">...</div>
The top and bottom divs are position absolutely at the top and bottom, with a width of 100%. The wrapper div has height: 100%, box-sizing: border-box, and top and bottom padding equal to the height of the top and bottom divs, respectively. This causes it to fill the viewport but have padding underneath the top and bottom divs. The middle div has a height of 100% so it fills the content box of the wrapper (i.e., 100% minus the top and bottom paddings). It has position: relative, which leaves you free to use height: 100% on both interior boxes.
Lastly, middleleft is positioned absolutely and middleright has a left margin equal to its width, which causes it to fill the remaining horizontal space.
height: 100% never works like you want it to. The CSS specifications dictate that it must equal the height of the browser window, or the closest parent block-level element with an absolute height specified. That means that this code will should not work as expected:
<!DOCTYPE html>
<html>
<head>
<title>Want the body to fill the page? Too bad!</title>
<style type="text/css">
html, body {
height: 100%;
}
.page {
padding-top: 50px;
box-sizing: border-box;
height: 100%;
}
.header {
margin-top: -50px;
height: 50px;
}
.body {
height: 100%;
background: gray;
}
</style>
</head>
<body>
<div class="page">
<div class="header">
<h1>Too bad!</h1>
</div>
<div class="body">
<p>Hello cruel world...</p>
</div>
</div>
</body>
</html>
However, that works fine in Chrome. Why? I can only assume that Google decided to specifically go against web standards because in this case, the standards make no sense. Why would I want something to be the exact height of the browser window? The only time is a <div> wrapping the whole page; in this case a simple "height is relative to the parent block" rule works just fine without breaking expectations elsewhere.
There is a way around this, though. At least, that's what I wanted to say before I tried this in Firefox too. Another way to get height: 100% (with some restrictions) is with position: absolute. However, it would seem that Firefox isn't respecting position: relative on a display: table-cell element - probably those pesky standards again. Here's the code for this technique anyway, if you are interested:
#wrapper > div > #middleleft {
position: relative;
}
.scroll-pane {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
So what can you do? Well, unfortunately, I don't yet know the answer to that. A kludgy solution would be to have Javascript set the height to an absolute pixel value, and attach an event to window resizing in order to update that height. I'll get back to you if I find a better way.
I'm not sure exactly what your trying to do, but another method would be to set body height to 100%, then set scrollpane to "height: auto". Then for the "top" and "bottom" div's used fixed positioning, plus margin equal to top/bottom height.
body {
height: 100%;
}
.top {
position: fixed;
top: 0;
height: 100px;
}
.middle {
height: auto;
margin: 100px auto;
}
.bottom {
position: fixed;
bottom: 0;
height: 100px;
}
<div class="top">content</div>
<div class="middle">content</div>
<div class="bottom">content</div>
Try that...

Setting width/height as percentage minus pixels

I'm trying to create some re-usable CSS classes for more consistency and less clutter on my site, and I'm stuck on trying to standardize one thing I use frequently.
I have a container <div> that I don't want to set the height for (because it will vary depending on where on the site it is), and inside it is a header <div>, and then an unordered list of items, all with CSS applied to them.
It looks a lot like this:
I want the unordered list to take up the remaining room in the container <div>, knowing that the header <div> is 18px tall. I just don't know how to specify the list's height as "the result of 100% minus 18px".
I've seen this question asked in a couple other contexts on SO, but I thought it would be worth asking again for my particular case. Does anyone have any advice in this situation?
You can use calc:
height: calc(100% - 18px);
Note that some old browsers don't support the CSS3 calc() function, so implementing the vendor-specific versions of the function may be required:
/* Firefox */
height: -moz-calc(100% - 18px);
/* WebKit */
height: -webkit-calc(100% - 18px);
/* Opera */
height: -o-calc(100% - 18px);
/* Standard */
height: calc(100% - 18px);
For a bit of a different approach you could use something like this on the list:
position: absolute;
top: 18px;
bottom: 0px;
width: 100%;
This works as long as the parent container has position: relative;
I use Jquery for this
function setSizes() {
var containerHeight = $("#listContainer").height();
$("#myList").height(containerHeight - 18);
}
then I bind the window resize to recalc it whenever the browser window is resized (if container's size changed with window resize)
$(window).resize(function() { setSizes(); });
Don't define the height as a percent, just set the top=0 and bottom=0, like this:
#div {
top: 0; bottom: 0;
position: absolute;
width: 100%;
}
Presuming 17px header height
List css:
height: 100%;
padding-top: 17px;
Header css:
height: 17px;
float: left;
width: 100%;
Use negative margins on the element you would like to minus pixels off. (desired element)
Make overflow:hidden; on the containing element
Switch to overflow:auto; on the desired element.
It worked for me!
Try box-sizing. For the list:
height: 100%;
/* Presuming 10px header height */
padding-top: 10px;
/* Firefox */
-moz-box-sizing: border-box;
/* WebKit */
-webkit-box-sizing: border-box;
/* Standard */
box-sizing: border-box;
For the header:
position: absolute;
left: 0;
top: 0;
height: 10px;
Of course, the parent container should has something like:
position: relative;
Another way to achieve the same goal: flex boxes.
Make the container a column flex box, and then you have all freedom to allow some elements to have fixed-size (default behavior) or to fill-up/shrink-down to the container space (with flex-grow:1 and flex-shrink:1).
#wrap {
display:flex;
flex-direction:column;
}
.extendOrShrink {
flex-shrink:1;
flex-grow:1;
overflow:auto;
}
See https://jsfiddle.net/2Lmodwxk/
(try to extend or reduce the window to notice the effect)
Note: you may also use the shorthand property:
flex:1 1 auto;
I tried some of the other answers, and none of them worked quite how I wanted them to. Our situation was very similar where we had a window header and the window was resizable with images in the window body. We wanted to lock the aspect ratio of the resizing without needing to add in calculations to account for the fixed size of the header and still have the image fill the window body.
Below I created a very simple snippet that shows what we ended up doing that seems to work well for our situation and should be compatible across most browsers.
On our window element we added a 20px margin which contributes to positioning relative to other elements on the screen, but does not contribute to the "size" of the window. The window-header is then positioned absolutely (which removes it from the flow of other elements, so it won't cause other elements like the unordered list to be shifted) and its top is positioned -20px which places the header inside of the margin of the window. Finally our ul element is added to the window, and the height can be set to 100% which will cause it to fill the window's body (excluding the margin).
*,*:before,*:after
{
box-sizing: border-box;
}
.window
{
position: relative;
top: 20px;
left: 50px;
margin-top: 20px;
width: 150px;
height: 150px;
}
.window-header
{
position: absolute;
top: -20px;
height: 20px;
border: 2px solid black;
width: 100%;
}
ul
{
border: 5px dashed gray;
height: 100%;
}
<div class="window">
<div class="window-header">Hey this is a header</div>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
</ul>
</div>
Thanks, i solved mine with your help, tweaking it a little since i want a div 100% width 100% heigth (less height of a bottom bar) and no scroll on body (without hack / hiding scroll bars).
For CSS:
html{
width:100%;height:100%;margin:0px;border:0px;padding:0px;
}
body{
position:relative;width:100%;height:100%;margin:0px;border:0px;padding:0px;
}
div.adjusted{
position:absolute;width:auto;height:auto;left:0px;right:0px;top:0px;bottom:36px;margin:0px;border:0px;padding:0px;
}
div.the_bottom_bar{
width:100%;height:31px;margin:0px;border:0px;padding:0px;
}
For HTML:
<body>
<div class="adjusted">
// My elements that go on dynamic size area
<div class="the_bottom_bar">
// My elements that goes on bottom bar (fixed heigh of 31 pixels)
</div>
</div>
That did the trick, oh yes i put a value little greatter on div.adjusted for bottom than for bottom bar height, else the vertical scrollbar appears, i adjusted to be the nearest value.
That difference is because one of the elements on dynamic area is adding an extra bottom hole that i do not know how to get rid of... it is a video tag (HTML5), please note i put that video tag with this css (so there is no reason for it to make a bottom hole, but it does):
video{
width:100%;height:100%;margin:0px;border:0px;padding:0px;
}
The objetive: Have a video that takes the 100% of the brower (and resizes dynamically when browser is resized, but without altering the aspect ratio) less a bottom space that i use for a div with some texts, buttons, etc (and validators w3c & css of course).
EDIT: I found the reason, video tag is like text, not a block element, so i fixed it with this css:
video{
display:block;width:100%;height:100%;margin:0px;border:0px;padding:0px;
}
Note the display:block; on video tag.
I'm not sure if this work in your particular situation, but I've found that padding on the inside div will push content around inside of a div if the containing div is a fixed size. You would have to either float or absolutely position your header element, but otherwise, I haven't tried this for variable size divs.

Resources