I'm using SuperScrollorama to trigger a lot of animations on a single page (scrolling) website. All of the images and text that slide in from the left or right work perfectly. The problem is when I try to make an image drop in from the top of the screen the image will bounce up and down the whole time the user scrolls until they finally get down to the point where the image is supposed to "sit" (It basically goes back to it's original position and then down to where it's supposed to stay and then back up again and so on)... Here's my relevant code:
HTML:
<div id="about-pin-div">
<div id="pin-frame-pin" class="pin-frame"><img src="img/about-products.png" style="width: 55%;"></div>
</div>
CSS:
#about-pin-div { position: relative; width: 100%; height: 100%; left: -5%; overflow: hidden; }
.pin-frame { position: absolute; width: 100%; height: 100%; overflow: hidden; }
.pin-frame img { margin-top: -200px; }
JAVASCRIPT:
$(document).ready(function() {
var controller = $.superscrollorama();
controller.addTween('#about-pin-div', TweenMax.from( $('#about-pin-div'), .5, {css:{bottom:'1000px'}, ease:Quad.easeInOut}), 0, 600);
// set duration, in pixels scrolled, for pinned element
var pinDur = 1000;
// create animation timeline for pinned element
var pinAnimations = new TimelineLite();
pinAnimations
.append(TweenMax.from($('#pin-frame-pin img'), .5, {css:{marginTop:80}}))
// pin element, use onPin and onUnpin to adjust the height of the element
controller.pin($('#about-pin-div'), pinDur, {
anim:pinAnimations,
onPin: function() {
$('#about-pin-div').css('height','100%');
},
onUnpin: function() {
$('#about-pin-div').css('height','100%');
}
});
});
Thanks in advance for any help!
I think you are having a number of issues here and I will try to point out some problems that I have had with this plugin.
(1) When in doubt turn off pushFollowers for your pins.
In an effort not to continue to repeat myself
Play through pinned elements in superscrollorama
janpaepke did an excellent job in writing this work around because he had the same issues himself.
(2) Never use margins for adjusting the position, IE handles margins badly sometimes depending on the context won't work the way you want it to.
When to use margin vs padding in CSS
Does a better job at explaining it then I can.
(3) I don't understand the need to trigger on pin functions to adjust the height of #about-pin-div. You are just resetting the starting value over and over that I don't see ever gets changed. Unless you were trying to compensate for the automatically adjusting of pinned elements but the work around in (1) should fix that.
Related
I am trying to make this parallax effect where when you scroll down, the image follows to the next location, then stops at said location(or destination). Once it reaches its destination, I want it to stay there and as you continue to scroll down, The image cannot continue past the destination set on it and I want it to scroll off the window, not stick at the top. Although I feel like this would be a fairly basic parallax task, unfortunately I am new to parallax.
<div class="myimg">
<img src="https://i.imgur.com/pzhXqfp.png" class="self" onclick="scrollWin()">
</div>
function scrollWin() {
window.scrollTo(0,1);
}
on scrollTo, on the Y axis, I have tried 0, 1, 50, 100, 500, and all kinds of numbers, but even at the lower numbers, it will scroll the entire page.
Edit: I found a perfect example: https://www.apple.com/ph/shop/buy-ipad/ipad-mini .
I would like to replicate this exact thing with the iPad. It scrolls down to a certain point on the Y axis and once it hits its destination, it no longer moves down the page. I have also tried the following, which is something I found from another Stack Overflow question, but this one is sticking to to top, which is not exactly what I'm looking for. Close though!
$(window).scroll(function() {
$(".myimg").css("top",Math.max(0,250-$(this).scrollTop()));
});
In the example website (https://www.apple.com/ph/shop/buy-ipad/ipad-mini) that you provided it is not a parallax effect but a sticky element in which it sticks to the screen at a given position until it reaches the end of its parent's height.
To create this effect just write the following .html and .css code:
body {
padding-top: 50vh;
padding-bottom: 200vh;
}
.parent {
height: 100vh;
}
.sticky-box {
background-color: blue;
width: 500px;
height: 500px;
position: sticky;
top: 0;
}
<div class="parent">
<div class="sticky-box"></div>
</div>
We define a div element with position: sticky with top: 0 for it to stick in top of the screen. Notice: The sticky-box travels the full height of the parent in the fixed position (so we define height: 100vh in the parent). More information in https://developer.mozilla.org/en-US/docs/Web/CSS/position.
What I am trying to figure out is how to animate a div that will start out in the middle of a div that is in the middle of a page. The div originally should not have a position: absolute. Unless it is not possible, I would like it not to start with that because it seems very tough to have any data below it. It's not going to be that big of a box. I am guessing anywhere between the height of 100px and 600px, with a width between 400px and 800px.
I originally found this JsFiddle Example that does a great job and almost exactly what I need. But the div starts with an absolute position and it is already located at the bottom right of the page to be animated.
Once the div is at the bottom right of the page, it needs to be fixed there so that I can scroll up and down the page without it moving. At this point I am not worried about being able to push it back up to the spot in which it came.
A couple things I tried: Lining it up in the position I desired, and then on the click of a button, add a class with the attribute position: absolute and calling the animate function like this:
chatWindow.stop().animate({
bottom: 0
, right: 0
}, 2000);
But my guess is that it originally needs to the the position set as in top: 0; left: 0 and that's why it won't work.
I already have it working without any animation and would love to be able to figure out how to animate this thing. Without animation, it's as simple as toggling a class with it's normal positions attributes with one that has a position: fixed; bottom: 0; right: 0.
Here is a Codepen Example that I created to show really what I need other than right animation part not being there. Any help would be awesome as I've been toying with this for quite some time now.
If you want an animation from left to right, you will have to play with left and top values. But the negative point is that will cause a weird animation because you want to keep a relative position of the box in the beginning.
So when you will do the animation, it will start from the very top left on the window, which is not good.
Like this
To avoid that, you will have to use absolute position in the beginning state. You said in your question you doesn't want it but I think it is required to get the wanted visual effect.
See here the live example with good effect
However, to keep a pretty nice animation, but I know it is not what you want, you can play with right and bottom values. It will make the box appears from the right and bottom corners of the window.
Like this
One possibility, still using absolute positioning, based on what's going on in your codepen example, would be to fake the current positioning by adding the following CSS:
.container {
padding-top: 250px;
}
.center-window {
position: absolute;
right: 50%;
margin-right: -200px; /* i.e. half of its width */
bottom: 100%;
margin-bottom: -250px; /* i.e. its height */
}
Then you could animate the right, bottom, and margin properties accordingly. See https://codepen.io/anon/pen/RaOJYY (though it doesn't currently do anything with the padding). Of course, if your not sure of the dimensions of .center-window, perhaps this solution won't quite work.
There's a lot of information on the web about this, but I really can't seem to find any exact answer that I need for my scenario - I've tried basically every combination of CSS I've found in tutorials and nothing's working.
Here's a couple of screenshots of what I'm facing (notice the markers):
Full resolution (1080p):
Shrunk browser window: (tablet)
You can see the markers are all over the place. I want these to stay relative, so the "marker" should stay above the word "great", even when the page resolution changes.
Here's my CSS, note that I've tried setting the overlay to position: absolute, with the pins as relative positioning. I've tried setting the top and left values as percentages for the markers, I can't seem to get anything to work.
.overlay {
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 100%;
z-index: 9997;
background-color: rgba(0,0,0,0.5);
display: none;
}
.overlay-inner {
width: 100%;
height: 100%;
position: absolute;
}
.pp_pin_dropped {
width: 48px; // tried as percentages, position: absolute is set on the elements in JQuery - will be moved to CSS
height: 48px;
z-index: 9998;
cursor: pointer;
background-image: url('/Images/pin_dropped.png');
}
And, finally, you can see this on the following URL: http://pintool.azurewebsites.net/ (click on the bottom right hand side icon to see the markers)
I know it's asking a lot, I just hope there's some CSS guru out there that I can point me in the right direction before I pull all my hair out.
Yikes, this is going to be very difficult to do using strictly CSS and HTML. I think you're going to need to use JS for this behavior. The jQuery UI position library will come in very handy for finding your marker locations: http://jqueryui.com/position/.
Here's one idea:
I'd wrap every "keyword" on the page in a span with a unique ID. For example:
<div>some text here <span id="pos">pos</span></div>
<img src="marker.png" id="pos_marker"/>
Then on window resize, reposition your images:
$( window ).resize(function() {
$("#pos_marker").position({my: "bottom center", at: "top center", of: "#pos"});
// and so on
});
you could wrap the targeted words or characters with a span tag and then use jQuery (or javascript) to locate them on the page.
perhaps this question would be helpful too: jQuery x y document coordinates of DOM object
When you locate the specific words, just use javascript to relocate the pins. And don't forget to reposition the pins on window resize.
I think you could treat them similar to how tooltips are done, embedding the pins directly as elements like
<span data-content="Great" class="pin"></span>
then use javascript to display the icon based on the element position and redraw it when the window is resized.
<script>
function drawpins() {
$(".pin").each(function(){
pos = this.position()
pin = this.data("content");
pin += '<img src="tooltip.jpg"'
pin += 'style="position:absolute;'
pin += 'top:' + pos.y + ';'
pin += 'left:'+ pos.x + ';'
this.html(pin)
})
}
$(window).resize(drawpins())
</script>
WARNING Not TESTED, just concept
this is your problem:
element.style {
left: 872px;
position: absolute;
top: 154px;
}
I am using max-width: 100%; height: auto; on all my <img> elements and on my image slider wrapper.
When resizing the browser window, the images scale correctly, but many surrounding elements don't follow along and misposition. They will self-correct once the page is refreshed or next image is loaded in the image slider. Any ideas?
Demo - scale the window, css at line 25
Pikachoose library sets the sizes of a few elements on each animation.
<div class="pika-stage" style="height: 355px;">
<div class="pika-aniwrap" style="position: absolute; top: 0px; left: 0px; width: 835px;">
This is why everything fixes itself when the next animation happens. You could look though the source and replicate the animations re-sizing code and put it in a $(window).resize event handler. Looking at the docs for Pikachoose it seems that they have a goto method.
You could do something like this:
$(window).resize(function(){$('#pikame').data('pikachoose').GoTo(3)})
Where the index of 3 is the current active slide. You probably want to use a form of timeout and only call it once to improve performance.
var resizeSlider = null
$(window).resize(function(){
if(resizeSlider) clearTimeout(resizeSlider)
resizeSlider = setTimeout(function() {
$('#pikame').data('pikachoose').GoTo(3)
}, 300)
})
This should make it so the goto is fired 300ms after the last window.resize event.
Hope this gives you some ideas.
Here's a link to what I'll be referring to.
I'm having some trouble getting the background image to work the way I'd like it to.
I want the background to auto resize based on the width of the window, which it is already doing correctly. If you make your window smaller you'll see the background shrink with it.
Here's the issue. If you make your window wide (short) then the background will resize and go too high so you can't see the top of the background anymore (since the background is bottom positioned).
I want the background to be top position when you are at the top of the page, and as you scroll down it will slowly move to be bottom positioned. Sort of like the effect of an Android phone's background when you move left and right. Of course, keep in mind that I still want the background to auto-resize when you make the window smaller.
html {
background-color: #70d4e3;
height: 100%;
}
body {
height: 100%;
}
.background {
margin-top: 45px;
width: 100%;
position: fixed;
bottom: 0;
left: 0;
z-index: -9999;
}
.banner {
margin: 0px auto;
width: 991px;
margin-bottom: -9px;
}
.content {
background: url("http://i.imgur.com/daRJl.png") no-repeat scroll center center transparent;
height: 889px;
margin: 0 auto;
width: 869px;
}
.innerContent {
padding: 30px;
}
<img src="http://i.imgur.com/6d5Cm.jpg" alt="" class="background" />
<div class="banner">
<img src="http://i.imgur.com/JptsZ.jpg" alt="" />
</div>
<div class="content">
<div class="innerContent">
testing
</div>
</div>
Maybe some javascript or jquery would be needed to achieve this.
Well, this was fun, thanks!
I hope you don't mind me taking the liberty to use percentages to make my life a little bit easier and possibly the script slightly more robust since I can reliably use floats with percentages.
What I did is make the layout, html and css comply with the rules you need for the bg to be animated properly, they stayed largely the same from what you had.
Then it was just a question of figuring out the calculations needed with the right properties to figure out the percentage you were from the top, the *20 is actually the amount of space 'left' to fill by the background image in percentages (as the background height is 80%).
They I moved the calculations to a function so I could call that on scroll and on window resize, making sure it's initiated on any event that modifies the window somehow...
Didn't do extensive testing but it worked in Chrome and I'm tired :p
I believe this is what you are looking for:
http://jsfiddle.net/sg3s/RSqrw/15/ See edit 2
If you wanted this the other way arround just make the page background start at the top and modify that:
http://jsfiddle.net/sg3s/RSqrw/14/ See edit 2
Edit:
As a bonus, and since I had never actually written jquery script as a 'plugin', I decided to convert this into one. What I came up with should be easy to implement and use!
http://jsfiddle.net/sg3s/RSqrw/52/ See Edit 3
Functionality successfully tested in Chrome, Firefox 3.6, IE9 + compatibility mode
Edit 2:
Reading the question again checking if I did it right I noticed I didn't quite do what you want, so I updated the link in the first edit which gives you a plugin in which you can have several options for the scrolling background. It retains my 'old' interpetation while also doing what you want... Read comments in code for some extra descriptions.
Edit 3:
As I went to work today I was bothered with the fact that my plugin 'try' was a little bloated. And as you mentioned in the comment it didn't quite fit the requirements.
So I rewrote it to only do what you want and not much more, tested in Chrome Firefox, IE9 +compat etc etc.. This script is a lot cleaner.
http://jsfiddle.net/sg3s/vZxHW/
You can chose to make the background stick to the top or bottom if the height fits in the window. Nothing else, but that is already more than enough to do some pretty cool stuff :p
An exact solution: Fiddle: http://jsfiddle.net/srGHE/2/show/
View source
Thanks for the challenge. See below for the solution, which is complying with all requirements, including recommended yet optional (with steps on how to remove these) features. I only show the changed parts of your page, with an explanation after each section (CSS, HTML and JavaScript):
CSS (changes):
html,body{
margin: 0;
height: 100%;
padding: 0;
}
body{
background-color: #70d4e3;
}
#background { /*Previously: .background*/
/*Removed: margin-top: 45px;
No other changes*/
}
#banner /*Previously: .banner; no other changes */
#content /*Previously: .content; no other changes */
#innerContent /*Previously: .innerContent; no other changes */
Explanation of CSS revisions:
margin-top:45px at the background is unnecessary, since you're absolutely positioning the element.
All of the elements which are unlikely to appear more than once should be selected via the id (#) selector. This selector is more specific than the class selector.
HTML (changes):
All of the class attributes have been replaced by id. No other changes have been made. Don't forget to include the JQuery framework, because I've implemented your wishes using JQuery.
JavaScript (new):
Note: I have added a feature which you didn't request, but seems logical. The code will automatically reserve sufficient margin at the left side of the window in order to always display the background. Remove anything between the marked comments if you don't want this feature.
$(document).ready(function(){
//"Static" variables
var background = $("#background");
var marginTop = parseFloat(background.css("margin-top")) || 0;
var bannerWidth = $("#banner").width(); /*Part of auto left-margin */
var extraContWidth = (bannerWidth - $("#content").width())/2; /*Same as above*/
function fixBG(){
var bodyWidth = $("body").width();
var body_bg_width_ratio = bodyWidth/1920;
var bgHeight = body_bg_width_ratio * 926; //Calcs the visible height of BG
var height = $(document).height();
var docHeight = $(window).height();
var difHeight = bgHeight - docHeight;
var scrollDif = $(document).scrollTop() / (height - docHeight) || 0;
/*Start of automatic left-margin*/
var arrowWidth = body_bg_width_ratio * 115; //Arrow width
if(bodyWidth - bannerWidth > arrowWidth*2){
$("body > div").css("margin-left", "auto");
} else {
$("body > #banner").css("margin-left", arrowWidth+"px");
$("body > #content").css("margin-left", (arrowWidth+extraContWidth)+"px");
}
/*End of automatic left-margin*/
if(difHeight > 0){
background.css({top:(-scrollDif*difHeight-marginTop)+"px", bottom:""});
} else {
background.css({top:"", bottom:"0"});
}
}
$(window).resize(fixBG);
$(window).scroll(fixBG);
fixBG();
});
Explanation of the JavaScript code
The size of the background is determined by calculating the ratio of the background and document width. The width property is used, because it's the most reliable method for the calculation.
Then, the height of the viewport, document body and background is calculated. If applicable, the scrolling offset is also calculated, to prepare the movement of the background, if necessary.
Optionally, the code determines whether it's necessary to adjust the left margin (to keep the background visible at a narrow window).
Finally, if the background arrow has a greater height than the document's body, the background is moved accordingly, taking the scrolling position into account. The arrow starts at the top of the document, and will move up as the user scrolls (so that the bottom side of the arrow will be the bottom of the page when the user has fully scrolled down). If it's unnecessary to move the background, because it already suits well, the background will be positioned at the bottom of the page.
When the page has finished loading, this functionality is added to the Resize and scroll events, so that the background is always at the right location.
If you've got any other questions, feel free to ask them.
well, I'm not sure if I understand you and why do you want to do that, but you can try adding 2 backgrounds (see http://www.css3.info/preview/multiple-backgrounds/ ), one with the top bg and another with the bottom bg but I think that if the page is not too long it will cause issues, so the other answer with pure CSS is as follows: first add 3 horizontal divs with 100% width. Top div will have your top bg and its height, middle div will be transparent and auto height and bottom div will have your bottom bg and its height. All divs will have a 0 z-index. Then create a higher z-index div to act as a container and you'll be set. If I understand your question right, that's the close I can think of to achieve that. This being said, I'm pretty sure you can do this with JQuery with way better results
Using jQuery I was able to give you what I think you're asking for:
$(window).scroll(function() {
var h = Math.max($(document).height(), $(window).height());
var bottom = h - $(".background").height() - $(window).height();
$(".background").css("top", (($(window).scrollTop() / h) * bottom) + "px");
});
EDIT: Forgot to account for the way scrollTop reports position.
Or maybe:
.background {
margin-top: 45px;
max-width: 100%;
position: fixed;
bottom: 0;
left: 0;
z-index: -9999;
max-height: 100%;
}
I reccomend using jQuery Background Parallax
http://www.stevefenton.co.uk/Content/Jquery-Background-Parallax/
The function is as simple as
$("body").backgroundparallax();
Ask if you don't get it to work.
#abney; as i understand your question may that's you want http://jsfiddle.net/sandeep/RSqrw/60/
you need only css for this:
#background {
position: fixed;
width: 100%;
height:100%;
top: 0;
left:0;
z-index: -1;
}
The solution to your issue is a nice little lightweight plugin by Scott Robin. You can get more info, download it, and make your life easier for all of your projects by visiting his project page here.