I have did one example: on scroll down, RHS panel on floating when scroll bar reach the RHS panel header.
http://www.elankeeran.com/test/RHSpanel.htm
But while scroll down RHS panel jump to off screen; I don't why position fixed not referring parent relative position left. it referring body left position.
after changing below css its working fine
#floating-box{position: absolute;width:100%;width:960px; margin:0 auto;}
if anyone known better solution please let me know.
Since you asked why this is happening, see the definition of position : fixed in the CSS spec, notably that
for a fixed positioned box, the containing block is established by the
viewport.
Or, as another site puts it,
the parent element is always the browser window
var wHeight = $(window).height();
$('.right-panel').css("height",wHeight-80);
if ( scrollY > bodyY && isfixed ) {
$floatingbox.stop().css({
position: 'fixed',
// left: wLeft,
top: 10
remove the !isfixed and make it isfixed
Related
I want to fixed the left and right div while only scrolling. It only fixed while scrolling and depends upon the parent div. I want to do some like this.
On that website, category div on left side, is fixed while scrolling and it fixed only within the parent div. Not exceed on the div.
Here my sample plunkr. I want to do same thing in my website too fixed the both left and right div.
Is it possible to done by angularjs instead of jquery?
can anyone help for me?
Im not sure if it can be done using angularjs as i've not really looked into it but it can easily be done using
var fixmeTop = $('.fixme').offset().top; // get initial position of the element
$(window).scroll(function() { // assign scroll event listener
var currentScroll = $(window).scrollTop(); // get current position
if (currentScroll >= fixmeTop) { // apply position: fixed if you
$('.fixme').css({ // scroll to that element or below it
position: 'fixed',
top: '0',
left: '0'
});
} else { // apply position: static
$('.fixme').css({ // if you scroll above it
position: 'static'
});
}
});
I love that this code works, but I cannot, for anything, wrap my head around WHY it's working?
Here is the jfidddle
Here is the code:
jQuery(document).ready(function($) {
clone = $('div').clone();
$('div').after(clone);
$('div:last').hide();
offset = $('div:first').offset();
var fromtop = offset.top;
$(document).scroll(function() {
doc = $(this);
dist = $(this).scrollTop();
if (dist >= fromtop) {
$('div:last').show();
$('div:first').css({
'position': 'fixed'
});
} else {
$('div:first').css({
'position': 'static'
});
$('div:last').hide();
}
});
});
I guess I am not understanding how scrolltop and offset are interacting or what they REALLY are, as in their true positions on the page. The code says if ScrollTop (the scrollbar position?) is higher than the value of the div's offsettop , then make the div sticky. But if ScrollTop is the position of the scrollbar, isn't it true that sometimes the scroll bar position could be lower than the div's position BEFORE the div is at the top of the page? What is it about being at the top of the page (offsettop of 0?)--and only at the top of the page, never before-- that makes offsettop a smaller value than scrolltop?
Really confused, and I don't want to just copy the code without understanding what it's really doing.
scroll Top is actually how many pixels 'up' the page has moved (or how many pixels you have moved down the page)
Basically all that happens is the .offset sees how far down the page (from the top of the page) the 'sticky' menu is
When you scroll to that point the bar becomes fixed (which is basically relative to the window instead of the document)
When you scroll back up it just switches back to being positioned in the document.
For clarity
.offset = 200px say - this is how far down the document the sticky menu is
.scrollTop - is 0 when the page loads
When you scroll down the page 201px
.scrollTop > .offSet -> so make the bar fixed (remember fixed is relative to the window - not the document)
If you scroll back up the process is reversed.
It's actually very simple. Let me try if I can make it a bit clear to you:
Whenever you want something (let's say some div) to get fixed on top as you scroll down, you need two things:
You need the current vertical position of your div. And you calculate that by using offset().top
You need to track how much user has scrolled. And you calculate that by using scrollTop()
So in your case, if the current position of your div is top: 100, then as soon as your scrollbar reaches the number 101, your div will get the class of .fixed
By default, the scrollbar vertical position is 0 when the page loads.
I have a project where the requirement is to move the footer ( #footer ) upward while scrolling down the page in a parallax-like effect. When you start scrolling down the page, the footer should start moving upward only until it's visible in the (bottom part of the) viewport.
The footer should have covered most of the preceding <div> half way up and in full when it has reached the top of the viewport.
The page may have a similar html structure like this :
<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-like effect is achieved via javascript/jQuery adding a dynamic negative value to the top CSS property of the (relative 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 (obvious) issue is that as soon as the top property starts getting a negative value, the footer starts moving away from the bottom of the page.
I have prepared a JSFIDDLE and assigned colors to each section and body to make it clearer. The body (dark-red) is visible under the footer after scrolling to the bottom.
What have I tried?
modifying the margin-top instead of the top property: this does the trick, however the preceding <div> that has to be covered by the footer (#sectionC in the example above) overlaps the contents of the footer and breaks its layout regardless that it is not visible due to its z-index property (added some floating boxes in the fiddle to make it evident.... a clearfix hack didn't help either.)
setting a static position to the footer: neither top or margin-top have effect over a static element.
Changing/reducing dynamically the height of #sectionC instead of top of footer to produce the effect of moving the second upwards : the footer stops moving as soon as height is equal to 0 (neither negative size or negative paddings are allowed)
Changed the height dynamically of the html and/or body tags to no avail.
I have also tried some parallax plugins like skrollr and skrollr-stylesheets and some others.
The problem with this solution (same with others) is that it relays in an specific (offset) position of the footer measured in px and set in a data attribute, but if the content changes dynamically, for example using the masonry plugin to arrange elements in another section of the document, the measures become inaccurate and the footer may start moving too early or too late.
By the way, other CSS sticky-footer techniques won't work because, well, they actually push the footer to the bottom of the page, and here we are doing the opposite.
I guess the question is either :
how to keep the footer stick to the bottom of the page while it is moved upwards? - or -
how to reduce the gap to 0 between the end of the document and the bottom edge of the footer?
I am starting to think that this issue has not a real solution the way it is, or maybe I am already too tired to see the obvious. I am interested in learning alternative solutions or hacks via CSS / javascript / jQuery or all of the above.
Bear in mind that I am not asking how to create the parallax effect UNLESS a totally different approach (or tweaks to the existing js code) solves the position issue.
IMPORTANT : Please consider that this is a WP site with an XHTML 1.0 Transitional DOCTYPE, and has installed many other jQuery plugins like masonry, scrollTo, jQuery UI, etc. I may have not control to 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 and from a modular script.
EDIT #1 : Added a graphic to clarify the question.
Figure A. shows a regular web page scrolled down to the end. The red square represents the viewport and the footer (grey) is slighted moved to the right for illustration purposes. The body has a reddish background color (not visible in normal conditions) just for illustration purposes too. NOTE: the height of each section as well as the height of the footer is determined by their content (forms, images, text, etc.) so is NOT fixed.
Figure B. shows the current issue: If footer slides up in a parallax-like effect (see JSFIDDLE for reference) while scrolling down the page, it starts covering any preceding section above it (WITHOUT modifying neither its own height or the height of the preceding sections) AND it also starts separating itself from the bottom of the page, therefore the body's color background becomes visible. NOTE: the bigger the viewport is (fullscreen mode for instance) the higher the footer is moved upward (and more content is covered by it)
Figure C. is the expected result: the footer should be stuck to the bottom of the page, in other words, it should be the last visible element after the page has been totally scrolled down (and not the body background as in Figure B.) Notice that the contents and the size of each section (including the footer) should (ideally) remain untouched. Having said that, adding padding bottom to the footer or increasing its height is not the expected result since it would break its original visual layout.
Updated Version
Below is an updated version that should better matches your requirements.
This version goes back to relative positioning for the footer element and uses margin-top to position it.
margin-top is calculated off of the previous elements offset, height and current window scroll position. It then uses either
the viewport height if the footer starts offscreen
the initial top value of the footer element ($startEffect) if the footer started onscreen
to determine the actual value for margin-top.
To help keep the footer's layout from being affected by this, wrapping the content of the footer in an absolutely positioned div did the trick for the sample code provided.
Example Fiddle
CSS:
#footer > div {
position: absolute;
top: 0;
left: 0;
...
}
HTML:
<div id="footer" class="div cf"><div>Footer</div></div>
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();
How was it solved?
As I mentioned in my question, I was too tired to see the obvious but #dc5's answer put me on the right track :
To help keep the footer's layout from being affected,
wrapping the content of the footer in an absolutely
positioned div does the trick
Based on that comment, the answer became simpler than the whole code he proposed needing only :
(dynamically) wrapping the content of the footer in an absolutely positioned div using jQuery's .wrapInner() method
animating 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 the tweaked original 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
This does what I think you need, the footer sticks when it has scrolled in view entirely:
jsFiddle
Code added:
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 the CSS I added this so that $footer.css('top') wouldn't produce NaN:
#footer {
top:0;
/* ... */
}
EDIT: A completely new approach after more clarification of OP. I now have a fixed position footer that starts increasing in height to take over the entire screen when the user has scrolled passed half of the document. The HTML, CSS and Javascript have all been updated to achieve this:
jsFiddle
I'm trying to fix a elements position based on the scroll position within the window.
I thought it would be as easy as getting the offset of the element where the fixed element should become fixed and then when the window.scrollTop is equal to it add CSS but it is weird.
It seems as though the offset of the element is larger than the scrollTop largest numeral.
Is there any other way of getting this to work?
I want it to have the same functionality as this with regards to the footer on scroll;
http://be.blackberry.com/
But I don't want to clone the element, I want to detect when it gets to near the bottom of the page and then change the position on the bottom of the element.
Thanks in advance.
B
This should help get you in the right direction:
var footer = $("#footer");
// min amount to show when not scrolled to the bottom of the page.
var minVisable = 25;
$(parent.document).scroll(function() {
// check position
if (window.scrollY + window.innerHeight + minVisable > $("html").height()) {
// if at the bottom of the page, stick the footer to it
footer.css("position","absolute").css("top", $("html").height() - footer.height());
} else {
// else keep top part of footer on the screen
footer.css("position","fixed").css("top", window.innerHeight - minVisable );
}
});
I was able to implement the solution posted here ("position: fixed and absolute at the same time. HOW?") to get a div element to move with the rest of the page horizontally, but stay fixed vertically. However, this solution causes the selected element to move ALL the way to the left of the page (with what appears to be a 20px margin). I'm still new to javascript and jQuery, but as I understand it, the following:
$(window).scroll(function(){
var $this = $(this);
$('#homeheader').css('left', 20 - $this.scrollLeft());});
takes the selected element and, upon scrolling by the user, affects the CSS of the element so that its position from the left becomes some function of the current scrollbar position adjusted by the 20px margin. If this is correct? And if so, can anyone think of a way that I could change it so that instead of moving the selected element all the way to the left side of the window, we only move it as far left as my default CSS position for the body elements of the HTML document (shown below)?
body {font-size:100%;
width: 800px;
margin-top: 0px;
margin-bottom: 20px;
margin-left: auto;
margin-right: auto;
padding-left: 20px;
padding-right: 20px;}
EDIT: Here is a jsfiddle (code here) that I made to illustrate the issue. My page is designed so that when it is displayed in full-screen or near full-screen mode, the #homeheader element appears centered horizontally due to its width and the left and right margins being set to auto. As the page gets smaller and smaller the margins do as well, until they disappear altogether and are replaced by the padding-left and padding-right settings of 20px. So at this point (when the window is small enough that the margins disappear altogether), which is what the jsfiddle shows, the code appears to work as intended, but when the window is full-sized the JS overrides the CSS and pushes the div element all the way to the left (getting rid of the margin) upon any scrolling action.
There are two events you need to handle to get this to work correctly. First is the scroll event which you are pretty close on. The only thing you might want to do is to use offset to get the current left position value based on the document.
The other event which is not yet handled is the resize event. If you don't handle this then once a left position is defined your element (header) will be there always regardless of whether or not the user resizes the window.
Basically something like this should work:
var headeroffset;
var header = $('#homeheader');
// handle scroll
$(window).scroll(function() {
// auto when not defined
if (headeroffset === undefined) {
// capture offset for current screen size
headeroffset = header.offset();
}
// calculate offset
var leftOffset = headeroffset.left - $(this).scrollLeft();
// set left offset
header.css('left', leftOffset);
});
// handle resize
$(window).resize(function() {
// remove left setting
// (this stops the element from being stuck after a resize event
if (header.css('left') !== 'auto') {
header.css('left', '');
headeroffset = undefined;
}
});
JSFiddle example: http://jsfiddle.net/infiniteloops/ELCq7/6/
http://jsfiddle.net/infiniteloops/ELCq7/6/show
This type of effect can be done purely in css however, i would suggest taking a look at the full page app series Steve Sanderson did recently.
http://blog.stevensanderson.com/2011/10/05/full-height-app-layouts-a-css-trick-to-make-it-easier/
As an example you could do something like this:
http://jsfiddle.net/infiniteloops/ELCq7/18/
Try this
$('#homeheader').css('left', parseInt($('body').css('margin-left')) - $this.scrollLeft());});
What I did here is just replace 20 with body's left-margin value.