I'm developing a mobile web app. This is the main structure from top to bottom: header div, menu div, content div, footer div. The header, menu and footer are constant and pages are loaded into the content div using ajax.
Some of the pages have lots of content and they fill out the page so scroll is needed. Some of the pages have only one or two lines of content so they leave a big empty part (Not necessarily different pages - one page for example shows a list of orders, you can have no orders and you can have hundreds...).
This is what i want to achieve: If the page is not full with content, the footer will be in the bottom of the page. If the page is full and scroll is needed, the footer will be immediately after the content (so you scroll down the page and in the end you reach the footer).
The sticky footer solutions are not good for me because i don't want the footer to stick to the bottom always, only when the page is not full of content.
Is there anyway to achieve that? Thanks.
Then you have to use javascript for that - calculate the height of the content - substract it from the window height and set the margin-top of the footer from that distance:
jsfiddle
jsfiddle show
HTML
<div id="header" class="header">Header</div>
<div id="content" class="content">Content</div>
<div id="footer" class="footer">Footer</div>
JS (This example uses jQuery, it should be included before this script.)
$('#footer').css('margin-top',
$(document).height()
- ( $('#header').height() + $('#content').height() )
- $('#footer').height()
);
You can put an onresize window that call this function on any resize of the window.
[edit blag :]
Here is the onResize method (but with a min-height and not a margin-top)
Check the JSFiddle
// function to set the height on fly
function autoHeight() {
$('#content').css('min-height', 0);
$('#content').css('min-height', (
$(document).height()
- $('#header').height()
- $('#footer').height()
));
}
// onDocumentReady function bind
$(document).ready(function() {
autoHeight();
});
// onResize bind of the function
$(window).resize(function() {
autoHeight();
});
Borders, padding and margin
If you want to have borders and padding included in the calculation you can use outerHeight() instead of height(). Alternatively outerHeight(true) also includes margins.
A CSS Sticky footer should solve your problem.
Here's an example
That is super easy to setup and use. It will force the footer down the page with the content, and if the content isn't big enough to fill the page it will stick to the bottom.
function autoHeight() {
var h = $(document).height() - $('body').height();
if (h > 0) {
$('#footer').css({
marginTop: h
});
}
}
$(window).on('load', autoHeight);
The following solution works for me, based on the answer from Александр Михайлов. It finds the bottom of the footer and determines if it is less than the document height and uses top margin on the footer to make up the shortfall. This solution might give issues if your content is being resized on the go.
$(function () {
updateFooterPosition();
});
$(window).resize(function () {
updateFooterPosition();
});
function updateFooterPosition() {
var bottomOfFooter = $('footer').offset().top + $('footer').outerHeight(true);
var heightShortage = $(document).height() - bottomOfFooter;
if (heightShortage < 0) heightShortage = 0;
$('footer').css('margin-top', heightShortage);
}
Here's the solution i came to on my project
function autoHeight() {
if ( document.body.clientHeight < window.innerHeight ) {
document.querySelector('#footer').style.position = 'absolute';
document.querySelector('#footer').style.bottom = '0';
}
}
document.addEventListener("DOMContentLoaded", function() {
autoHeight();
});
This solution worked for me. I think this is perfect if you have more than only a #header and #footer. It just push the content down with a padding-bottom if body is smaller than the viewport.
function autoHeight() {
var bodyHeight = $("body").height();
var vwptHeight = $(window).height();
var gap = vwptHeight - bodyHeight;
if (vwptHeight > bodyHeight) {
$("#content").css( "padding-bottom" , gap );
} else {
$("#content").css( "padding-bottom" , "0" );
}
}
$(document).ready(function() {
autoHeight();
});
$(window).resize(function() {
autoHeight();
});
Related
Hello all I am working on a project where in a page I have to stick the div to screen (disable scrolling) when its bottom is at the bottom of screen. I have two divs in the page and both the divs are of variable height. I want to stick the div2 and scroll the div1.
<script>
var divheight
var scrolltop
var screenheight
if(divheight-scrolltop <= screenheight){
/* now stick the div wherever it is i can not
use fixed position as both the divs are floating and
fixing the position will make it to change the position*/ }
else { /*un stick the div*/ }
</script>
i dont know what to put in if and else please help me
Make a function which fire on scroll. The main aim of the function would be to see the difference between screen height and bottom of the div. Once the difference is less than or equal to zero modify the css position to fixed. This will help you
(function ($) {
$('.DIV1').scroll(function () {
var $this = $(this),
win_ht = $(window).height(),
div_ht = $this.height(),
div_bot = $this.offset().top + div_ht;
if (win_ht - div_bot <= 0) {
$this.css({
'position': 'fixed',
'bottom': '0'
})
}
});
})(jQuery);
On my website, I have a sidebar DIV on the left and a text DIV on the right. I wanted to make the sidebar follow the reader as he or she scrolls down so I DuckDuckGo'ed a bit and found this then modified it slightly to my needs:
<script type='text/javascript'>//<![CDATA[
$(window).load(function(){
$(function(){
var $sidebar = $('#sidebar'),
sidebarOffset = $sidebar.offset(),
$window = $(window),
gap = $('#header').css('marginBottom').replace(/[^-\d\.]/g, ''),
distance = ($window.scrollTop()) - (sidebarOffset.top - gap),
footerHeight = $('#footer').outerHeight();
$window.scroll(function(){
distance = ($window.scrollTop()) - (sidebarOffset.top - gap);
if ( distance > 0 ) {
$sidebar.css({'top': gap + 'px', 'position' : 'fixed'});
} else {
$sidebar.css({'top': '0', 'position': 'relative'});
}
})
});
});//]]>
</script>
And it works just like I want it to. However, my website uses Skeleton framework to handle responsive design. I've designed it so that when it goes down to mobile devices (horizontal then vertical), sidebar moves from being to the left of the text to being above it so that text DIV can take 100% width. As you can probably imagine, this script causes the sidebar to cover parts of text as you scroll down.
I am completely new to jQuery and I am doing my best through trial-and-error but I've given up. What I need help with is to make this script not execute if a certain DIV has a certain CSS value (i.e. #header-logo is display: none).
Ideally, the script should check for this when user resizes the browser, not on website load, in case user resizes the browser window from normal size to mobile size.
I imagine it should be enough to wrap it in some IF-ELSE statement but I am starting to pull the hair out of my head by now. And since I don't have too much hair anyway, I need help!
Thanks a lot in advance!
This function will execute on window resize and will check if #header-logo is visible.
$(window).resize(function() {
if ($('#header-logo').is(':visible')) {
// Your code
}
});
I think you need to check this on load to, because you don't know if the user will start with mobile view or not. You could do something like this:
$(window).resize(function() {
if ($('#header-logo').is(':visible')) {
// Your code
}
}).resize();
This will get executed on load and on resize.
EDIT: You will probably need to turn off the scroll function if #header-logo is not visible. So, instead of create the function inside the scroll event, you need to create it outside:
$(window).resize(function() {
if ($('#header-logo').is(':visible')) {
var $sidebar = $('#sidebar'),
sidebarOffset = $sidebar.offset(),
$window = $(window),
gap = $('#header').css('marginBottom').replace(/[^-\d\.]/g, ''),
distance = ($window.scrollTop()) - (sidebarOffset.top - gap),
footerHeight = $('#footer').outerHeight();
function myScroll() {
distance = ($window.scrollTop()) - (sidebarOffset.top - gap);
if ( distance > 0 ) {
$sidebar.css({'top': gap + 'px', 'position' : 'fixed'});
} else {
$sidebar.css({'top': '0', 'position': 'relative'});
}
}
$window.on('scroll', myScroll);
} else {
$(window).off('scroll', myScroll);
}
});
Didn't test it, but you get the idea.
$("#headerLogo").css("display") will get you the value.
http://api.jquery.com/css/
I also see you only want this to happen on resize, so wrap it in jquery's resize() function:
https://api.jquery.com/resize/
I have an issue with a jquery function. You can see a working demo here - http://dev.sreejesh.in/menuissue/ . As you can see when the user scrolls down to the page, I have written a jQuery function(which will triger on scroll) to check scroll pixel. When the browser scrolls to a certain pixel(height of the sidemenu block), the Menu block will stay fixed & rest of the content scrolls as normal.
The functionality is working now, however the problem is menublocks makes a jumps when this function runs. I think this is because of the delay in running the function. Hope you guys have any nice trick to fix this.
I used an if/else function to check the scroll pixel, so when the scrolled pixel is greater than menublock height it will add a class "fixed" .
I use the following code.
HTML
<div id="globalwrapper">
<div id="menubar">
---- Menu List items-----
</div>
<div id="mainblock">
----Main content area----
</div>
</div>
jQuery
$(document).ready(function(){
$(window).scroll(function() {
adjustScroll();
});
});
function adjustScroll(){
var windowHeight = $(window).height();
var menublockHeight = $('#menubar').height();
var scrollValue = $(document).scrollTop();
var posValue = menublockHeight - windowHeight;
var menuStatus = $('#menubar').css('left');
$('#menubar').css('minHeight', windowHeight);
$('#menubar').css('height', menublockHeight);
console.log(menuStatus);
$(document).scroll(function() {
if(menuStatus == '0px') {
if(scrollValue > posValue){
$('#menubar').addClass('fixed');
$('#menubar').css('marginTop', -posValue);
}else {
$('#menubar').removeClass('fixed');
$('#menubar').css('marginTop', '0px');
}
}
});
}
I think only CSS can solve this issue, add this style:
#menubar{
position: fixed;
}
just test on Google Chrome,you can have a try.
I want to have a div positioned in the bottom of another div. This i can solve with just
bottom: 0px;
postion: fixed;
But, if the containing div is larger than the window, i want to freeze the inner div to the bottom of the window.
If it's easier the first condition can be scrapped and the inner div can just be positioned under the content, the important part is that the content must always be visible.
The best solution would be to detect with JavaScript if the footer is visible inside the viewport. If not, you should change it's styles to stick to the bottom of the window instead of that of the containing div.
You could use this function to see if it's in the viewport:
function elementInViewport(el) {
var top = el.offsetTop;
var left = el.offsetLeft;
var width = el.offsetWidth;
var height = el.offsetHeight;
while(el.offsetParent) {
el = el.offsetParent;
top += el.offsetTop;
left += el.offsetLeft;
}
return (
top >= window.pageYOffset &&
left >= window.pageXOffset &&
(top + height) <= (window.pageYOffset + window.innerHeight) &&
(left + width) <= (window.pageXOffset + window.innerWidth)
);
}
(taken from How to tell if a DOM element is visible in the current viewport?)
Now, every time you scroll or resize the page you can do a check that runs that function. Based on that, you can decide to set a class or change a CSS property that will do what you're looking for.
Since you didn't include any code (in the future, please do) I'm going to assume your code looks something like this:
<div class="wrapper">
(contents)
<div class="footer">footer</div>
</div>
To stick the .footer to the bottom of .wrapper, it has to have a 'positon: absolute' and the wrapper will need a position: relative. However, if you change it's position property to fixed and the wrapper to static (the default for all elements), the footer is going to stick to the bottom of the window instead.
View this example http://jsfiddle.net/GMYEh/
Now, using the script above you can tell which of the two it should be. You have to use a fake element at the same position of the footer, instead of the footer itself. That way, if you move the footer to the bottom of the window, you can still measure whether or not the bottom of the wrapper is in the viewport. (If you measure the footer itself and move it you'll get stuck).
The script that does this (in jQuery):
// add a fake footer after the wrapper
$('.wrapper').after($('<div class="fakefooter" />'));
$(document).on('resize scroll', function(e){
//measure if the fake footer is in viewport
if(elementInViewport($('.fakefooter')[0])) {
// If so, it should be in the bottom of the wrapper.
$('.wrapper').css('position', 'relative');
$('.footer').css('position', 'absolute');
} else {
// else it should be in the bottom of the window
$('.wrapper').css('position', 'static');
$('.footer').css('position', 'fixed');
}
});
Working example:
http://jsfiddle.net/GMYEh/4/
Try this:
HTML:
<div id="wrapper">
<div id="innerContent"></div>
</div>
CSS:
.fixedContent {
position: fixed;
bottom: 0;
}
and the javascript:
var wrapper = document.getElementById('wrapper');
var content = document.getElementById('innerContent');
function position() {
if (wrapper.offsetHeight + wrapper.offsetTop - content.offsetHeight - window.scrollY > window.innerHeight) {
content.className += ' fixedContent';
} else {
content.className = content.className.replace('fixedContent', '');
}
}
window.onload = position;
window.onresize = position;
If you're open to jQuery you can make the javascript more simple and compatible
var $wrapper = $('#wrapper');
var $content = $('#innerContent');
$(window).on('load resize', function() {
$content.toggleClass('fixedContent', $wrapper.outerHeight(true) $content.offset().top - $content.outerHeight(true) - $(document).scrollTop() > $(window).height());
});
EDIT:
I modified the conditions a bit adding the vertical scroll value and top offset.
I really like the floating panel on the left side of the following site:
http://envato.com/
I have no idea what its called, but I like how when you click on the search button, it expands to a search page, you click on another icon, and it expands with what appears like its own page.
How do I accomplish this? Is there some tutorial out there using html5, JavaScript or jQuery?
NOTE: All the answers so far only cover the floating bar, but not the clicking on a link on that floating bar to show a window expanded to the right.
<div id="float"></div>
#float{
position:fixed;
top:50px;
left:0;
}
Check working example at http://jsfiddle.net/TVwAv/
done using css,
HTML
<div id="floating_sidebar">
whatever you want to put here
</div>
CSS
#floating_sidebar {
position:fixed;
left: 0;
top: 100px; /* change to adjust height from the top of the page */
}
I am using this for a "floating (sticky) menu". What I have added is:
1. to avoid my 'footer' always being "scrolled" down in case the sidemenu is a little high, I only do the scrolling if necessary, i.e -
when the content is higher than the sidebar.
2. I found the animate effect a little "jumpy" to my taste, so I just changed the css through jquery. of-course you put a 0 in the animate time, but the animation still occurs, so it's cleaner and faster to use the css.
3. 100 is the height of my header. you can assume it to be the "threshold" of when to do the scrolling.
$(window).scroll(function(){
if ($('#sidebar').height() < $('#content').height())
{
if ($(this).scrollTop() > 90)
$('#sidebar').css({"margin-top": ($(this).scrollTop()) - 100 });
//$('#sidebar').animate({"marginTop": ($(this).scrollTop()) - 100 }, 0);
else
$('#sidebar').css({"margin-top": ($(this).scrollTop()) });
//$('#sidebar').animate({"marginTop": ($(this).scrollTop()) }, 0);
}
});`
you can use this ..
your html div is here
<div id="scrolling_div">Your text here</div>
And you javascript function is here
$(window).scroll(function(){
$('#scrolling_div').stop().animate({"marginTop": ($(this).scrollTop()) +10+ "px"}, "slow"});
});
You can also use the css for this
#scrolling_div {
position:absolute;
left: 0;
top: 100px;
}
I have not tested it but hopefully its worked.
I know this looks quite a big piece of code, however this function just works by specifying three simple options; your floater "top", your "target" (floater) and "reference" element to set the boundaries, it also takes care of the top and bottom position automatically, no css involved.
function scrollFloater(marginTop, reference, target, fixWhidth = false){
var processScroll = function(){
var from = reference.offset().top - marginTop;
var to = reference.offset().top + reference.outerHeight() + marginTop - target.outerHeight();
var scrollTop = $(this).scrollTop();
var bottom = to - reference.offset().top + marginTop;
if( fixWhidth )
target.css('width', target.width());
if( scrollTop > from && scrollTop < to )
target.css('position', 'fixed').css('top',marginTop);
else if( scrollTop >= to )
target.css('position', 'absolute').css('top', bottom);
else
target.css('position', '').css('top',marginTop);
}
$(window).scroll(function(){ processScroll(); });
processScroll();
}
And this is how you would use it:
$(function() {
scrollFloater(41, $('.box.auth.register'), $('.plans-floater'), true);
});
I hope this helps someone.