Use JS to Calculate Div Height - javascript

I am using some javascript to calculate the height of the page and then set a min-height on on a div. The reason for this is to push the footer to the bottom of the page for pages that are short on content. My issue is the min-height is about 30-40 px to big thus causing scroll bars. (Note: I am not using a solution like sticky footer for various reasons and prefer this solution.)
Here is my code:
JS
$(function() {
var height = $(window).height() - ($("header").outerHeight() + $("footer").outerHeight() );
$("#page-content").css("min-height",height+"px");
});
HTML
<header class="container">
<div id="menu" class="row">
<!-- Content -->
</div>
</header>
<div id="page-content">
<!-- Content -->
</div>
<footer>
<!-- Content -->
</footer>
I believe the issue lies in my CSS. For example I have a margin in the header as so:
#menu{
margin: 5px auto 10px;
}
If I remove that code it will reduce the scrollbar just a little bit. (I have other margins set in place on the page so changing just this one will not work as a solution).
How would I re-write the JS code to factor in the margin for the header and other sections?

The <header> box's height doesn't reflect the child #menu's margins because they are both normal box elements, and if the #page-content had margins, they would overlap the #menu's margins, in which case the header's height would include some part of the content's height, which wouldn't make sense.
The issue is collapsing margins: http://www.w3.org/TR/css3-box/#collapsing-margins
As that page explains, you can get tell the browser not to collapse margins a few ways:
add display: inline-block; to your #menu { } rules (my first suggestion)
add overflow: hidden; to your header { } (a potentially better suggestion if you're having alignment issues)
make your <header> absolutely positioned, or float it. Or do that to the #menu inside.
Or if you want to go for a hack, you could calculate the header height manually:
var header_height = $("header").outerHeight() +
parseInt($("header").children().css('margin-top'), 10) +
parseInt($("header").children().css('margin-bottom'), 10);
Now that I think about it, this makes sense, and I think the css spec is doing the right thing.
Updated: http://jsfiddle.net/HzBSz/2/
Also see: Outer element margin not equal to inner element margin

For some reason the JS is not calculating the margins. I added the margins I had in the header and footer and they totaled 45px. Thus the script now looks like so:
$(function() {
var height = $(window).height() - ($("header").outerHeight() +
$("footer").outerHeight() + 45 );
$("#page-content").css("min-height",height+"px");
});
I add 45px and the script now functions correctly.

Why not just place the footer on the bottom manually? I mean, I know you said you prefer not to, but why? If you want it to always be there, do
position:relative;
bottom:0;
If you want it to scroll with the rest of the page (as it sounds like you may), use
position:absolute;
instead.
This is a much better method than dynamically inserting dummy content to push a footer down.

Perhaps you look at this
http://matthewjamestaylor.com/blog/keeping-footers-at-the-bottom-of-the-page
may solve your problem.

Try .outerHeight(true) for all your elements instead of .height() or .outerHeight():
$(function() {
var height = $(window).outerHeight(true) - ($("header").outerHeight(true) + $("footer").outerHeight(true) );
$("#page-content").css("min-height",height+"px");
});
.height() - returns the height of element excludes padding, border and margin.
.innerHeight() - returns the height of element includes padding but excludes border and margin.
.outerHeight() - returns the height of the div including border but excludes margin.
.outerHeight(true) - returns the height of the div including margin.

Related

Element in container with overflow:hidden; has width same as parent, despite the overflowed width being wider

Given:
<div class=gallery>
<div class=slider>...</slider>
</div>
with gallery having main css as overflow:hidden; positon:relative; and as an example width:1000px;
The slider then has "wider" content, stretching far beyond the width of the gallery which has a set width to 1000px here.
The problem is, calculating the slider width (using jQuery('.slider').outerWidth()) gives the same width as .gallery element, when overflow:hidden is used.
The only way to get slider to show it's actual width, is to use position: absolute on .slider
Problem with that is that now, .gallery will no longer expand it's height.
I have to somehow manually calculate (and keep track of) height to set on gallery. I do not know the height in advance of the contents of .slider.
Frankly, I don't get why .slider width can not be calculated unless position:absolute is used.
There might be a way to iterate child elements of .slider and possibly calculate the width of each child, but risks are the overflown children have width set to zero as well.
Anyone know a good workaround for this?
You could set slider width to
width:100%
with that, it will never go out of its parent width
slider.scrollWidth seems to do the trick and returns the same value as:
var total = 0;
$slider$.children().each(function(i, e){
e = jqr(e);
total += e.outerWidth(true)
})
return total;

How to set body height with JavaScript?

document.body.height = document.getElementById("page-main").clientHeight + 400;
#page-main {
position:absolute;
width:100%;
height:2000px;
z-index:2;
background:#eeeeee;
}
#footer {
position:fixed;
width:100%:
bottom:0px;
height:400px;
z-index:1;
background:#aaaaaa;
}
<body>
<div id='page-main'>main</div>
<div id='footer'>footer</div>
</body>
I have a footer div with position: fixed; bottom: 0px; and a main content div with position: absolute;.
Basically the idea is to have the main content div act like a sheet of paper on top of the static background of the document, so you would scroll through the content of the page and when you get to the bottom you would need to be able to scroll a couple hundred more pixels to reveal the footer div below the main content div.
I allowed this in my landing page by finding out the height of the body necessary to facilitate this extra space at the bottom and setting the height using height: 1720px; on the body itself. However, I'd like to implement this in a way that it does not need to be constant, as I fear browsers and devices may have different rendered heights for the main content div and I'd like to use this on multiple pages without having to individually hard code the body height.
I tried using JavaScript to find the height of the main content div (using clientHeight, which seems to work perfectly) and add a couple hundred pixels to that number for the height of the body as follows:
document.body.height = document.getElementById("page-main").clientHeight + 400;
and also tried changing the following:
document.body.style.height
document.body.style.paddingBottom
This does not change the height of the body at all. I tried using a similar approach to change the body's background to red, which works, but for some reason it just refuses to change the height specifically. I've tried placing this script in the head, above the body, and at the end of the body. Doesn't help. Finding the clientHeight of the main content div works fine, adding 400 to that number seems easy enough, and I know the document definitely has a body, so I'm very confused as to why it could possibly be that JavaScript refuses to change the height of the body.
I've checked the console in Edge and Chrome and it seems there's no issue, so I'm completely lost here. Normally I can find answers online and I've never had to ask for help but at this point I feel like it's such a simple question and I have no idea why it won't work.
Sorry if this question is't written well, but does anybody have an idea of why JavaScript might not be allowing the changing of the height of the body?
TL;DR:
content div is positioned absolute and can change depending on scenario
footer div is positioned static on the bottom and is supposed to be revealed below the content div by allowing user to scroll a couple hundred pixels below the end of the content div
I want to achieve this by altering the height of the body, which works perfectly through hardcoding in html but for some reason JavaScript refuses to change the height of the body
Try it like this:
document.body.style.height = document.getElementById("page-main").clientHeight + 400 + 'px';
You have to specify the units to get a proper result. Like you would do in CSS.
Setting the height of the body element, the way you want in your question, is complicated by it's relationship with html element and their default CSS (like position: static on body), and by the overflow property. Read more here.
From my experiments on the chrome console, you can't set body height via document.body.clientHeight, it seems to be read-only. You'll need to set height (and possibly overflow) properties in CSS (via document.body.style for javascript).
However, I think the best solution for the effect you want doesn't involve setting body (or html) properties at all. Try this:
Let the footer element by default have CSS: display: none
Detect when user has scrolled to the bottom of the page (using jQuery or scrollTop) or bottom minus some offset
Change the footer's CSS to display: block (by toggling classes preferably, or editing the style property). This will automatically increase the body's scrollbar to accommodate the footer.
When user scrolls back up beyond the footer (or point 2 is false), you set it's CSS to display: none again.
With the above approach, there is no need to hard code or know before hand the height of your footer and non-footer content. You don't need to mess with html or body element CSS. You can also apply CSS animations if you want!

Set the scrollable height of an entire page regardless of content?

Is there a way using css and html to control the maximum scrollable height of a page, regardless of the content which is present on the page?
For a concrete, hypothetical example: say the <body> is incredibly simple - a <div> which is 5000px tall. How would you set the scrollable height to be only 2000px?
Thus it would appear that the 2000th pixel is the last pixel on the page. The browser's scroll bar would appear to be at the bottom, not just "stuck" halfway down the page. Am I missing something simple to achieve this behavior? I would prefer pure css/html because it seems like it should be doable, but I would accept js.
You can do something like this
HTML
<div class="outer">
<div class="inner">
<!--your content here-->
</div>
</div>
CSS
.outer {
height:2000px;
overflow:auto;
}
.inner {
height:5000px;
overflow:hidden;
}
You should set the body height to a specific number and set overflow to hidden.
body{
height:2000px;
overflow:hidden;
}
Made an example here
Use max-height or height css properties and overflow:hidden on your container element. It will hide everything that is greater than the height you specify, therefore limiting the scrollbar height.
I should also mention that you can use overflow-y:hidden will achieve the same thing, but will only affect top and bottom edges of an element. See more details here.

How to adjust height of a HTML element to cover all free spaces of it's parent?

Suppose we have a DIV element like this:
<div id='parent'>
<!-- The childs will come here -->
<div id='footer'>This is footer</div>
</div>
and this function that create HTML elements dynamically and inserts them into the div#parent
function addChild(name)
{
$("<div></div>").text(name).prependTo( $("div#parent") );
}
CSS:
div#parent
{
height:400px;
background-color:yellow;
}
div#footer
{
/* height: ??? */
background-color:red;
}
Now I want, the element div#footer covers whole available/remaining height of the element div#parent, How I can do this by CSS or Javascript?
Thanks
Another solution using CSS. The solution here is using display:table and display:table-row
div#parent
{
display:table;
height:400px;
width:100%;
background-color:yellow;
}
div{
display:table-row;
height:20px;
}
div#footer
{
/* height: ??? */
background-color:red;
height:auto;
}
http://jsfiddle.net/aawbE/
If you simply want the footer to always be at the bottom of the page, then I would suggest checking out http://www.cssstickyfooter.com/. They have a great concept for making sure that the footer will either be at the end of the content, or touch the bottom of the page.
Example
If you want the footer to cover the entire bottom portion of the screen (beginning where the content ends and ending at the bottom of the screen) then you do need to know the total height being used by all of the elements inside of the "container" element as well as the height of the "container" element.
An easy way to do this is to put all child elements into a different div (the height of which you can easily track.
//find the difference in height between the
//"parent" div (minimum of 100% of page height) and
//the "main" div (the total height of its child elements)
height = document.getElementById('parent').offsetHeight -
document.getElementById('main').offsetHeight;
//Set the top margin of footer to minus the height
//(make footer go up 'height' number of pixels
document.getElementById('footer').style.marginTop = -height+'px';
//Set the height of the footer to 'height'
document.getElementById('footer').style.height = height+'px';
It's important to note that these calculations are based off of the cssStickyFooter code. This makes sure that the bottom of the footer remains at the bottom of the screen (unless it passes the bottom of the screen).
Example
For this example I added a green border around the 'main' div so that you can see where it ends. I also make sure to change the footer whenever the page is re-sized in case the child elements move around (re-size the page to see this happen). I also added a min-height to the footer so there will still be a footer even if #main.height >= #parent.height.
I hope this helps.

My webpages div doesnt set dynamic width correctly

I have 2 toolbars, 1 of each side of the screen, and a main content area. I dont want it to have to sidescroll cause that is pathetic, so i was trying to figure out if someone could help me set it up.
My current attemp was:
$("#main").css("width", window.outerWidth - $("#t1").width() - $("#t2").width());
The issue is that it is too big still because of margins. Instead of me doing width, should i do outerWidth, similar to how i did window, or is there a jquery command which will do just that?
Thanks
here is a basic fiddle: it is set up differently, but the idea is there. I just am unsure as to how to do it. http://jsfiddle.net/fallenreaper/DfZx7/
Upon tinkering deeper and deeper with my fiddle, i am fairly certain i figured it out in the example i had given. derp Standby while i look and see if i can apply the same thing to my code.
The sample did not work with my code, but border was set to 2px around, for both main and attributes. Deducting 8 pixels resolves.
You don't need JavaScript to avoid scrollbars. It's a layout width two fixed-width columns and a liquid one.
Here is the "skeleton" of your layout in a responsive way:
<div id="window">
<div id="column-sx"></div>
<div id="main"></div>
<div id="column-dx"></div>
</div>​
CSS:
#window {
width:100%;
overflow:hidden;
}
#column-sx {
width:54px;
float:left;
}
#column-dx {
width: 140px;
float:right;
}
#main {
width:100%;
float:left;
margin-right:-194px; /* left + right col width */
}
#main > * {
margin-right:194px; /* left + right col width */
}
This way it will never "break" nor cause an horizontal scrollbar.
Anyway, probably you want to set a min-width for #main contents, and add another container for contents instead of targeting them with > *
Check this fiddle with your code revised
Off the top of my head, i would think outerWidth would work. If it doesnt, you can find the margin value via the .style attribute - but thats not ideal.
One thing you should be aware of is window resize if your setting your widths dynamically and you truely hate horizontal scrolling. You could put the above function also in the $().resize() function to ensure the widths are always within the window and complement this with css min-width so it doesnt go too small.

Categories