I have a website that uses a parallax background, the background is 1200px long.
The issue is:
I have a page with indefinite height, the page get expanded dynamically to its content. So if a user press read more it expands without refresh, which ruin the parallax effect because the background reaches its end before the page finish.
The background is complex design image, it cannot be repeated and adding background-color to cover up the white space cant be done, but I wish I can keep the cool parallax effect!
My question:
Is it possible to make the parallax stop when it reaches a specific y-position, and freezes the background when scrolling beyond the specific y position? But also to be able to trigger on the parallax effect when scrolling back to the specific y-position and above?
If we assume background is moving at 0.1 speed, then the max height will be 1200/0.1 = 12000px.
If page reaches y-position = 12000px -> stop parallax effect and freeze image as is -> and if page return back to 1199px start parallax again
How to do this in Javascript? If possible in CSS would be great too.
Edit:
here is what I did before posting on Stackoverflow:
I used Stellar.js for the parallax effect, simply i added the following javascript:
$(window).stellar({responsive:false});
and added the following code to the tag (which hold the background-image):
<body data-stellar-background-ratio="0.1">
I also tried another approach, by using a custom JavaScript I found in the web:
$( window ).scroll( function(){
var ypos = $( window ).scrollTop(); //pixels the site is scrolled down
var visible = $( window ).height(); //visible pixels
const img_height = 1261; //image height
var max_scroll = img_height - visible; //number of pixels of the image not visible at bottom
//change position of background-image as long as there is something not visible at the bottom
if ( max_scroll > ypos) {
$('body').css('background-position', "center -" + ypos + "px");
} else {
$('body').css('background-position', "center -" + max_scroll + "px");
}
});
in this case, it do scroll until the end of the background, But I can't figure out how to slow down the scroll speed of the background.
Related
I am hoping to create an effect similar to this one further down the page, in the 'Designing For 20-Somethings' section.
The effect is essentially to get a long image to change the css top value within a device such as a MacBook or iPhone, so it appears as though the image within the device is also scrolling whilst the user is scrolling the website.
I've created a fiddle to show how far I've got, but this doesn't work well on resize or when initially loaded.
This is some of the code I am using below
var yOffset = $element.offset().top - ($(document).scrollTop() + $(window).height()/diviser)
Any help is appreciated.
OK I see it now. But the movement is so subtle i didn't even notice it. It looks to be a lot of work for something that is pretty much unnoticeable. It appears he's changing the top position of the image based on some percentage change of the full window scroll but only when the image is inside the viewport.
Just off the top of my head (completely untested) something like this would scroll the image up and 1/4 the speed the window would scroll;
var mobiletop = $('.mobile').position().top;
var scrollfactor = 4;
$(window).scroll(function(){
if($(window).scrollTop() > mobiletop){
var imgtop = $('.mobile img').position().top - (($(window).scrollTop() - mobiletop)/scrollfactor);
$('.mobile img').css('top', imgtop + 'px');
}
I have a parallax web page with a series of modules that contain a large photo and a smaller text box that overlays the photo and sits absolutely positioned at the bottom of it. While the size of the photos change, the text box is consistently 340px. Initially, when the site scrolls, the text box is hidden (I am doing a translateY(340px) and hiding the overflow on the container).
I know how to determine when to start revealing the box:
window.addEventListener('scroll', self.monitorScroll, false);
var moduleOffset = Math.floor($el.offset().top);
var moduleTriggerPos = moduleOffset - self.windowHalfHeight; //trigger animation when module is halfway up the screen
self.monitorScroll = function(){
self.yPos = window.pageYOffset;
if (self.yPos > thisObject.triggerPos){
//BEGIN ANIMATION
}
}
but I don't know how to tell the object how much to move each time the listener is triggered. The number of times it is called seems to be based on how fast you scroll, and the amount I would need to move the object differs, as the container resizes with the browser (the narrower the browser, the smaller the photo becomes).
I am currently using a static amount to move the object:
if (newPos >= 0){ //if our object hasn't reached a translateY(0px) value
thisObject.curPos = 320 //starts at 320, the amount it has been translated by in order to hide it
var newPos = thisObject.curPos - 25; //the amount we move it each time
thisObject.textEl.css({ translate: [0,newPos] }); //move it by 25px
thisObject.curPos = newPos; //update the current position
}
How do I get more accurate determination of how much to move the item by, rather than using a static movement amount. I want it to be based on the percentage of the way I've scrolled toward the module's final reveal position, which would ideally be when the module was fully at the top of the screen at full browser width (max width of 1200px), or some percentage thereof if they had resized the browser smaller.
I don't need exact code, but more just a conceptual understanding of what I should be monitoring / calculating to determine the correct positioning. Thanks!
I figured this out. For various reasons I made the trigger point for the CSS animation start when it first appears on screen rather than halfway up, then used this code:
var scrollProgress = (((self.windowHeight+self.yPos)-thisObject.offset)/thisObject.height);
var scrollAmt = scrollProgress*self.moduleTextHeight;
var translateAmt = -scrollAmt;
if (scrollAmt <= self.moduleTextHeight){
thisObject.textEl.css({ translate: [0,translateAmt] });
} else {
thisObject.textEl.css({ translate: [0,-self.moduleTextHeight] });
}
I am building a template where there are large navigation buttons at the very top that, when clicked, make a corresponding page (an absolutely positioned DIV) slide out from underneath the button and fill the whole page via CSS transitions.
I have a series of commands in a window resize function that keep everything in place/the right size if the window changes size. It is all working fine, except for a small issue where when the page is "out", if the browser window gets resized vertically, the CSS height transition triggers as opposed to the DIV snapping to the new height instantly (the DIV is 100% width and a dynamically calculated height the makes it fill the screen below the navigation buttons exactly). My solution to that was to add a line of code that would change the transition property to not include height BEFORE updating the height, then change it back immediately after. It seems to do nothing at all though. My code:
window.addEventListener('resize', function(event){
bottomLoc = findBottom.getBoundingClientRect();
if (pageOut1 == false) {
pageLoc1 = pageButton1.getBoundingClientRect(); //redefine location variable
document.getElementById("page1").style.top = pageLoc1.top + 70 + "px"; //update closed page position
document.getElementById("page1").style.left = pageLoc1.left + "px"; //update closed page position
} else if (pageOut1 == true) {
document.getElementById("page1").style.transition = "width 0.5s, left 0.5s"; //turn off height transition
document.getElementById("page1").style.height = bottomLoc.bottom - 70 + "px"; //update height
document.getElementById("page1").style.transition = "height 0.5s, width 0.5s, left 0.5s"; //turn height transition back on
}
});
The part that doesn't seem to be working is in the "else if" statement. Even though I take out the "height 0.5s" before the height update happens, it still does the transition. This is not exactly a huge, website breaking problem, but it does cause a scroll bar to randomly appear and disappear when resized smaller, which looks bad.
Hopefully someone can help me understand why this is not working, as this would help with a lot of other templates I have that require dynamic repositioning of absolutely positioned elements. Thanks!
fiddle: http://jsfiddle.net/DerNalia/88N4d/9/
The behavior I'm trying to accomplish:
The Sidebar(s) should be fixed on the page if there is enough room
for them
The Sidebar(s) should scroll if there is ever not enough room for them
When scrolling down, and the bottom of the sidebar(s) is reached, it should stop scrolling
When scrolling down, the sidebar(s) should also scroll down, until
the bottom of the sidebar(s) is/are reached
When scrolling up, and the top of the sidebar(s) is reached, it should stop scrolling
If at any point during the scrolling of the content, the user switches directions of scrolling, the sidebar(s) shall also move in the same direction as the rest of the page / content
When scrolling up, the sidebar(s) should also scroll up, until the
top of the sidebar(s) is/are reached
If the content is shorter than the sidebar(s), the sidebar(s) should
still be able to scroll This is the one that I'm having trouble
with
How do I make it so that I can detect the intended scroll distance desired by the user, rather than use the actual scrolled distance of the content body? There may be another solution, but this is all I can think of for right now.
I'm currently using Chrome on Mac.
UPDATE:
something I've noticed: using the track pad on macs does the stretching / bouncy scrolling shenanigans on the edges.. which messes up this javascript hard core. It's possible to scroll the sidebar completely off the screen if you bounce up enough times. Mouse Wheel scrolling does not have this issue.
I think you’d be much better off positioning the columns absolute and then check positions onscroll and toggle the positions.
It gets quite complicated, since the scroll will jump if both columns are fixed and the content has regular flow.
I created a solution for you using a simpler logic that goes:
var $win = $(window);
var $containers = $(".container").css('position','absolute');
// we need to force a height to the body for fixed positioning
$('body').css('minHeight', Math.max.apply( Math, $containers.map(function() {
return $(this).height();
})));
$win.bind("resize scroll", function() {
var scrolled = $win.scrollTop(),
winheight = $win.height(),
elheight = 0;
$containers.each(function() {
elheight = $(this).height();
$(this).css('position', function() {
if ( elheight > (winheight+scrolled) ) {
$(this).css('top',0);
return 'absolute';
}
$(this).css('top', Math.min(0, winheight-elheight));
return 'fixed';
});
});
});
It should fill your requirements. The fixed positioning kicks in if the columns are shorter than the window height, or if the scrollTop is enough.
A demo in all it’s glory: http://jsfiddle.net/mb9qC/
I wanted to do something similar to this.
In this case when the user click in the image, this images is showed with 100% of the browser height, and the user can go to the next/previous image. When the user clicks again the image is showed in a bigger size(may be in the real size) and the user can go up and down in the image, but with out scroll, just moving the mouse.
What I want to do is when the user click the first time in the image go right to the last step: The biggest image with up and down synchronized with the mouse movement, and the possibility to go to the next image. In other words a mix with the features of the first and the second step of the original case.
Where I can see a tutorial, or a demo?? or how can I do the this??
Thanks
Basically, there are three parts to what you want to do.
Clicking on the image will show the image with respect to browser height
You can go to the next image while you are in this mode
Click on that image again will go into a supersize mode where your mouse position dictates what part of the image you are looking at
I'm not going to write a whole fiddle to demonstrate this because it's a decent amount of work but I can tell you the basic ideas.
With #1, when you click on the image, you will create a new div with a z-index of some high number (like 9999). The position would be fixed, and you will create
$(window).resize(function() {
var windowheight = $(window).height();
$("#imgdiv").css("height", windowheight);
});
Which will resize the image if the user decides to resize your window, this way it's always taking up the full height of your browser.
With #2, the arrows just create a new img tag. And the idea is something like
function loadnew() {
// create the new image
var newimg = "<img id='newimg'></img>"
$("#imgcontainer").append(newimg);
// make sure it has the same classes as the current img
// so that it's in the same position with an higher z-index
// then load the image
$("#newimg").addClass( "class1 class2" );
$("#newimg").css( "z-index", "+=1" );
$("#newimg").css( "opacity", 0 );
$("#newimg").attr("src", "url/to/img");
// animate the thing and then replace the src of the old one with this new one
$("#newimg").animate( {
opacity: 1;
}, 1000, function() {
$(oldimg).attr("src", $("#newimg").attr("src"));
});
}
Now with #3, you will size the image with respect to the width. The div fixed positioned. So again, you need a
$(window).resize(function() {
var windowwidth= $(window).width();
$("#imgdiv").css("width", windowwidth);
});
to make sure it's always taking up the whole screen. And for the mouse movement, you need to have a mousemove event handler
$("#superimgdiv").mousemove( function(e) {
// need to tell where the mouse is with respect to the window
var height = $(window).height();
var mouseY = e.pageY;
var relativepct = mouseY/height;
// change the position relative to the mouse and the full image height
var imgheight = $("superimg").height();
$("superimgdiv").css("top", -1*relativepct*imgheight);
});
And that's it. Of course I'm leaving out a bunch of details, but this is the general idea. Hopefully this can get you started. Good luck.