How to hold the footer at the bottom of the page, moving it up in a parallax-like effect?

I have a project in which I want to move the footer ( #footer ) up, scrolling the page in an effect similar to parallax. When you start scrolling the page, the footer should only start moving up until it becomes visible in the (bottom of the window).

The footer was supposed to cover most of the previous <div> halfway up and completely when it reached the top of the viewport.

The page may have a similar html structure, for example:

 <body> <div id="sectionA" class="div">First section</div> <div id="sectionB" class="div">Second section</div> <div id="sectionC" class="div">Third section <div class="box"></div> <div class="box"></div> <div class="box"></div> </div> <div id="footer" class="div cf">Footer</div> </body> 

The parallax effect is achieved using javascript / jQuery, which adds a dynamic negative value to the top CSS property of the (relatively positioned) footer. Here is the code for what it matters:

 var $window = jQuery(window), $footer = jQuery("#footer"), $viewport = window.innerHeight, $startEffect = $footer.offset().top - $viewport; function footerParallax() { var $scrollPos = $window.scrollTop() - $startEffect, $ratio = 0.6; $footer.css({ top: -($scrollPos * $ratio) }); } $window.scroll(function () { footerParallax(); }); 

The problem (obvious) is that as soon as the top property starts to get a negative value, the footer starts to move away from the bottom of the page.

I prepared JSFIDDLE and assigned colors for each section and body to make this clearer. body (dark red) appears below the footer after scrolling down.

What have i tried?

  • changing the margin-top instead of the margin-top property: this does the trick, however the previous <div> that should be covered with the footer ( #sectionC in the above example) overlaps the contents of the footer and breaks its layout, regardless of the fact that it is not visible due to its z-index property (added a few floating boxes in the fiddle to make this obvious .... clearfix hack didn't help either.)
  • setting the static position to the footer: neither top nor margin-top act on the static element.
  • Dynamically changing / decreasing the height #sectionC instead of the top of the footer to create the effect of moving the second up: the footer stops as soon as height is 0 (neither negative size nor negative linings).
  • Changed the height dynamic html and / or body tags to no avail.

I also tried some parallax plugins like skrollr and skrollr-stylesheets and some others.

The problem with this solution (the same with others) is that it is relayed at a certain (offset) position of the footer, measured in px, and set in the data attribute, but if the content changes dynamically, for example, using a layout plugin to place elements in another section of the document, measures become inaccurate, and the footer may start moving too soon or too late.

By the way, other sticky bottom-level CSS methods will not work, because they really click the footer on the bottom of the page, and here we do the opposite.

I think the question is:

  • How to keep the footer at the bottom of the page while it is moved up? - or -
  • How to reduce the gap to 0 between the end of the document and the bottom edge of the footer?

I'm starting to think that this question does not have a real solution as it is, or maybe I'm too tired to see the obvious. I am interested in exploring alternative solutions or hacks using CSS / javascript / jQuery or all of the above.

Remember that I am not asking how to create a parallax effect IF a completely different approach (or tuning to an existing js code) solves the position problem.

IMPORTANT Please note that this is a WP site with XHTML 1.0 Transitional DOCTYPE and installed many other jQuery plugins such as masonry, scrollTo, jQuery user interface, etc. Maybe I can’t change many things from the original structure (and I don’t want to), so the idea is to implement this without breaking too many things from a modular script.

EDIT No. 1 . Added graphics to clarify the issue.

  • Figure A Shows a regular web page that scrolls to the end. The red square represents the viewport, and the footer (gray) is reset to the right to illustrate. body has a reddish background color (not displayed under normal conditions) for illustration purposes only. NOTE : the height each section, as well as the height of the footer, is determined by their contents (forms, images, text, etc.), therefore it is NOT fixed.

  • Figure B shows the current question: if the footer slides upward in an effect similar to parallax (see JSFIDDLE for reference) when scrolling the page, it starts to cover any previous section above it (WITHOUT modifying either its own height or the height previous sections) And it also starts to separate from the bottom of the page, so the body color becomes visible. NOTE : the larger the viewing area (for example, in full screen mode), the higher the footer moves up (and the more content it covers)

  • Figure C - expected result: the footer should be stuck at the bottom of the page, in other words, it should be the last visible element after the page has completely scrolled (and not the body background, as in Figure B.) Note that the content and size of each section ( including footer) should (ideally) remain intact. Having said that, adding a lower footer to the footer or increasing its height is not the expected result, as it will disrupt its original visual layout.

enter image description here

+7
javascript jquery html css parallax
source share
3 answers

How was this decided?

As I mentioned in my question, I'm too tired to see the obvious, but @ dc5's answer put me on the right track:

 To help keep the footer layout from being affected, wrapping the content of the footer in an absolutely positioned div does the trick 

Based on this comment, the answer has become easier than all the code it offers:

  • (dynamically) wrapping the contents of the footer in an absolutely positioned div using the jQuery .wrapInner() method
  • animate the footer by setting the margin-top property instead of the top property

So this extra CSS:

 #footerInnerWrapper { position: absolute; top:0; left:0; width: 100%; background-color: #666 /* same as footer */ } 

and revised source code

 var $window = jQuery(window), $footer = jQuery("#footer"), $viewport = window.innerHeight, $startEffect = $footer.offset().top - $viewport; // add inner wrapper $footer.wrapInner('<div id="footerInnerWrapper" />'); function footerParallax() { var $scrollPos = $window.scrollTop() - $startEffect, $ratio = 0.6; $footer.css({ // top: -($scrollPos * $ratio) marginTop: -($scrollPos * $ratio) }); } $window.scroll(function () { footerParallax(); }); 

did the trick. See JSFIDDLE

+2
source share

Updated version

Below is an updated version that better suits your requirements.

This version returns to relative positioning for the footer element and uses margin-top to position it.

margin-top calculated from the scroll position of previous elements, height and current window. Then he uses either

  • viewport height if footer runs on screen
  • the initial header value of the footer ( $startEffect ) if the footer started on the screen

to determine the actual margin-top value.

In order not to affect the layout of the footer, wrapping the contents of the footer in an absolutely positioned div did the trick for the provided code example.

Script example

CSS

 #footer > div { position: absolute; top: 0; left: 0; ... } 

HTML:

 <div id="footer" class="div cf"><div>Footer</div></div> 

the code:

 var $window = jQuery(window), $footer = jQuery("#footer"), $viewport = window.innerHeight, $startEffect = $footer.offset().top; $prev = $footer.prev(), $useStartEffect = $startEffect < $viewport; function footerParallax() { var $scrollPos = $window.scrollTop() - $startEffect, $ratio = 0.6; var prevOffset = $prev.offset().top + $prev.height() - $window.scrollTop(); var marginTop = 0; if(prevOffset < $viewport && prevOffset < $startEffect) { if($useStartEffect) { marginTop = (prevOffset - $startEffect)*$ratio; } else { marginTop = (prevOffset - $viewport)*$ratio; } } $footer.css({ "margin-top": marginTop + 'px' }); } $window.scroll(function () { footerParallax(); }); footerParallax(); 
+4
source share

This does what you think you need a footer when it scrolls fully:

jsFiddle

Added code:

 function footerParallax() { var $scrollPos = $window.scrollTop() - $startEffect, $ratio = 0.6, $newTop = -($scrollPos * $ratio), $oldTop = parseInt($footer.css('top')), $nonRelTop = $footer.offset().top - $oldTop, $wanted = ($window.scrollTop()+$viewport-$footer.height()); if ($nonRelTop + $newTop < $wanted) { $('#sectionC').css('display', 'none'); $wanted = ($window.scrollTop()+$viewport-$footer.height()); $nonRelTop = $footer.offset().top - $oldTop; $newTop = $wanted - $nonRelTop; } else { $('#sectionC').css('display', 'block'); } $footer.css('top', $newTop); } $window.scroll(footerParallax); 

And in CSS, I added this so that $footer.css('top') does not produce NaN :

 #footer { top:0; /* ... */ } 

EDIT: A completely new approach after a more detailed description of the OP. Now I have a fixed position, which begins to increase in height to capture the entire screen when the user scrolled half of the document. HTML, CSS, and Javascript have been updated to achieve this goal:

jsFiddle

0
source share

All Articles