SuperScrollorama: Reversing animation - javascript

This is my first post, but I'm a long-time viewer. Hope someone can help - this one's been driving me crazy and I've tried and tried to find an answer but to no avail.
Basically, I'm updating a friend's website with a few stylistic scrolling elements. I chose SuperScrollorama as it looks completely amazing, although I'm ready to accept that it's complete overkill for what I'm trying to achieve. I'm really interested in SuperScrollorama anyway, so I suppose I partly chose it just so I could try to use it!
Anyway, the idea I'm trying to implement involves:
Single page website, where section one is simply a centred, large (650px width) image and a navigation menu <ul> centred and fixed to the top of the page containing 6 <li> elements.
On scrolling down, I want the image to shrink to 250px width, and I want to make a space of 250px between the third and fourth <li> for the shrunken image to scroll into and then remain for the duration of the scroll. I'm trying to create the space by adding a margin-right to the third <li>. (I appreciate this may give me undesirable side-effects, one being that it won't be completely centred. Suggestions welcome here too! The problem that I'm about to describe, however, I also experienced when trying other methods based around floating and using two separate divs so the margin-right itself doesn't seem to be the root cause)
Now, I've managed to get the image to shrink and attach itself to the top of the page without too much trouble.
The problem that I'm having is with the margin-right. On page load, the <ul> appears centred and uniformly spread, as I want it to. The margin-right value on the third <li> is 0. However, the value jumps from 0 to 89px following the tiniest of scroll events. Continuing the scroll works as desired, but on scrolling back up, the margin returns to 89px and then stops.
Here's the code that I've got:
HTML:
<body>
<nav>
<ul>
<li>HOME</li>
<li>PROGRAMME</li>
<li id="grow_margin">TICKETS</li>
<li>MENU</li>
<li>VENUE</li>
<li>FAQ</li>
</ul>
</nav>
<header id="fix-it">
<h1><img id="scale-it" src="/images/logo.png" />TITLE</h1>
</header>
CSS:
html {
height: 100%;
width: 100%;
}
body {
height: 100%;
width: 100%;
}
nav {
position: fixed;
top: 0;
width: 100%;
height: 5%;
text-align: center;
}
nav ul {
list-style: none;
height: 100%;
}
nav ul li {
display: inline-block;
height: 100%;
}
nav ul li a {
color:#bbbbbb;
text-decoration: none;
margin: 8px;
}
header {
width: 100%;
position: fixed;
}
header h1 {
width: 100%;
text-align: center;
margin: 0;
padding: 0;
}
And the JS:
<script>
$(document).ready(function() {
var controller = $.superscrollorama({
reverse: true
});
var windowHeight=window.innerHeight;
var scrollDuration = windowHeight;
controller.addTween('#grow_margin',
TweenMax.to( $('#grow_margin'), .25, {css:{'margin-right':'250px'}, immediateRender:true}), scrollDuration);
controller.addTween('#scale-it',
TweenMax.fromTo( $('#scale-it'), .25, {css:{width:'650px'}, immediateRender:true, ease:Quad.easeInOut}, {css:{width:'250px'}, ease:Quad.easeInOut}),
scrollDuration);
controller.addTween('#fix-it',
TweenMax.fromTo( $('#fix-it'), .25, {css:{top:'40%'}, immediateRender:true, ease:Quad.easeInOut}, {css:{top:'4'}, ease:Quad.easeInOut}),
scrollDuration);
});
</script>
Any help would be so much appreciated! It's driving me absolutely crazy!
Thank you!
Rob

Related

How to preserve scroll-chain on overflow scrollable element on mobile?

I have this fixed height scrollable ul element which is for a video playlist. Scrolling works fine but when the user scrolls thru all the content they get stuck on the playlist container element. Basically, the scroll chain breaks and you can't scroll up unless you tap on one of the other elements on the page which is no easy job due to the playlist container taking all of the space on the screen and it doesn't have any padding around it.
What I need is, I need the browser to stop focusing on the ul element and shift the scroll event from element to window so they wouldn't get stuck scrolling on the ul element.
Playlist element's CSS:
.plyr-playlist-wrapper ul {
padding: 0;
margin: 0;
max-height: 28em;
min-height: 28em;
overflow-y: scroll;
-webkit-overflow-scrolling: touch; // this is the problem
}
You can solve this problem using JS (see below), but you should also consider restructuring your page so that you prevent this issue altogether. For example, you could choose not to limit the height of your ul element and still keep your video in focus when scrolling (e.g. by making it sticky).
Here is a possible solution based on JS (which needs some additional finetuning). It works by detecting when you have scrolled to the top of your ul element and bringing the video back into view.
document.getElementById("suggestions").onscroll = (e) => {
if (e.target.scrollTop == 0) {
document.getElementById("video").scrollIntoView({
behavior: "smooth"
});
}
}
#container {
margin-top: 5em;
}
#video {
height: 10em;
background: blue;
}
#suggestions {
overflow-y: scroll;
height: 28em;
margin: 0;
padding: 0;
background: red;
}
.suggestion {
height: 10em;
margin: 12px;
background: yellow;
}
<div id="container">
<div id="video">
</div>
<ul id="suggestions">
<li class="suggestion">
</li>
<li class="suggestion">
</li>
<li class="suggestion">
</li>
<li class="suggestion">
</li>
</ul>
</div>
Turns out momentum-based smooth scrolling was the problem. So I had to remove it and the problem was solved. You lose the smooth scrolling function but who cares.
// setting it to 'touch' will give you smooth scrolling but it will prob break the scroll chaining
-webkit-overflow-scrolling: auto;

Dynamically positioning element on scroll

Goal
To have the page navigation positioned lower on the page when initially loaded. So that it looks like pictured below.
Background
I created a navigational element that is using Headroom.js to control its position. The point of the library is that it moves the desired navigational item out of view when a user is scrolling down so that you can see more content. Then the item shows up when you scroll back up to make it convenient to click on a link if that is what you needed to do.
Current State
I have this current demo on codepen.
That navigational item is at the top of the page but on a lower z-index. So not initially visible.
when you scroll down the element is out of view.
But when you scroll up, it is where it needs to be
Code
HTML
<nav id="page-menu" class="link-header header--fixed slide slide--reset" role="banner">
<ul>
<li>Products</li>
<li>Features</li>
<li>Testimonials</li>
<li>Cases</li>
</ul>
</nav>
CSS
#page-menu {
background-color: #BA222B;
list-style-type: none;
width: 100%;
z-index:10;
}
#page-menu ul {
list-style-type: none;
margin: 0;
position: absolute;
bottom: 5px;
right: 10px;
}
#page-menu ul li {
display: inline-block;
margin-left: 10px;
}
#page-menu ul li a {
text-decoration: none;
color: #fff;
}
.link-header {
background-color:#292f36;
height: 100px;
}
.header--fixed {
position:fixed;
z-index:10;
right:0;
left:0;
top:0px;
}
jQuery
(function() {
new Headroom(document.querySelector("#page-menu"), {
tolerance: 5,
offset : 150,
classes: {
initial: "slide",
pinned: "slide--reset",
unpinned: "slide--up"
}
}).init();
}());
Full demo on codepen.
Goal :
From what you are describing, you want the read navigation to appear as such on page load:
And move with the gray bar, but and down, as the user scrolls, until it cutoff point reaches the bottom of the gray bar. Then you want things to kick in, and have the red bar slide up and out of view, and then up and down depending on scroll. You want the transition to be smooth.
Method:
The thing to keep in mind for a smooth transition is that you have two states: A top state and a bottom state. You have to design both, you have to figure out the exact height to change over, and you have to make sure that they will be identical at that spot, so appear seamless.
Top State:
We don't need any sort of extra positioning here. We want it to be static in fact, as odd as that might sound.
Bottom State:
We want fixed positioning here. Since we want the changeover to occur right when the red bar touches the top of the window, your CSS in fixed-header is perfect already.
Changeover Height:
The header and the gray nav bar combined are 180px, so that number will be our change over.
Code:
1. Statechange
Lets work backwards and take the state change first. You will need to change from 150px to 180px in a lot of places. For example, your JS code:
Existing JS:
if ($(window).scrollTop() >= 150) {
...
(function() {
new Headroom(document.querySelector("#page-menu"), {
tolerance: 5,
offset : 150,
New JS:
if ($(window).scrollTop() >= 180) {
...
(function() {
new Headroom(document.querySelector("#page-menu"), {
tolerance: 5,
offset : 180,
And your header will need an updated height, or a removal of height entirely.
Existing CSS:
header {
height:150px;
position: relative;
z-index:30;
}
New CSS:
header {
position: relative;
z-index:30;
}
2. Top State
The big thing here messing you up is that for some reason the library you are using is applying .header--fixed and link-header on page load. I don't know how to prevent this, but we can just neutralize is by removing them from your CSS.
Remove This CSS:
.link-header {
background-color:#292f36;
height: 100px;
}
.header--fixed {
position:fixed;
z-index:10;
right:0;
left:0;
top:0px;
}
Second, we need to tweak the ul inside your red nav.
Existing CSS:
#page-menu ul {
list-style-type: none;
margin: 0;
position: absolute;
bottom: 5px;
right: 10px;
}
New CSS:
#page-menu ul {
list-style-type: none;
margin: 0 auto;
padding:0;
width:960px;
max-width:100%;
text-align:right;
}
3. Bottom State
Everything works really well here aleady, except that the fixed-header class is getting added to the gray nav as well. We need to tweak our jQuery selector bit.
Existing JS:
if ($(window).scrollTop() >= 180) {
$('nav#page-menu').addClass('fixed-header');
}
else {
$('nav#page-menu').removeClass('fixed-header');
}
NewJS:
if ($(window).scrollTop() >= 180) {
$('header nav').addClass('fixed-header');
}
else {
$('header nav').removeClass('fixed-header');
}
4. Misc Cleanup
Everything looks really good here, except that the lis inside our two navs don't line up. We need to fix some margin-right to bring them into line.
Existing CSS:
#page-menu ul li {
display: inline-block;
margin-left: 10px;
}
New CSS:
#page-menu ul li {
display: inline-block;
margin-left: 10px;
margin-right: 10px;
}
Finally, I noticed that there's a missing closing bracket in your HTML, in the gray nav. It's not hurting much, but it could:
<nav>
<ul>
<li>Dentists</li>
<li>Labs</li>
<li>Patients</li>
<ul> <--- ( Should be </ul> )
</nav>
End Result:
http://codepen.io/anon/pen/qIrhx

Fully cover an overflow div with another div

This is a hard one to explain so bear with me (or just skip straight to the jsfiddle)
I have a Div with a max-height defined and overlow-x set to scroll. Within this Div there are a bunch of list items (in this instance, addresses). Naturally there can be many of these and they can overflow, which works fine. What I want is a 'cover' div that indicates that this panel is disabled. I have done this by putting an absolutely positioned div within the main div, like so.
<div style="max-height:150px;overflow:auto;position:relative">
<ul>
<li>Church Walk, Access To Foxholes Farm, DT2 9HG
</li>
<li>Garden Cottage, Access To Foxholes Farm, DT2 9HG
</li>
<li>Little Bride, Access To Foxholes Farm, DT2 9HG
</li>
...etc
</ul>
<div id="overlayDiv" style="display:none;background-color:white;position:absolute;top:0px;opacity:0.8;height:100%;width:100% ">
<p style="margin-top:50px;text-align:center;font-size:18px;">Searching...</p>
</div>
</div>
This then appears when the user does something, overlaying the content and making it appear disabled. Great! The problem occurs when my list items overflow. When the overlay div appears it only covers the current visible portion of the parent div, meaning that if I scroll down the div it appears 'uncovered' as the cover div only spans the height of the parent, not including its overflow.
This is really hard to explain so please go to my jsfiddle and click one of the addresses. You'll see that the div gets covered. If you then scroll down that div you will see that the items at the bottom of the list are uncovered.
This also works in reverse so if you click the 'Hide the overlay div' button to get rid of the cover and then click one of the addresses at the bottom of the list, you'll see that the 'cover' still only covers the top part of the div.
Any ideas on how you go about making that cover div extend the entire height of its parent, including the overflow? Other alternative solutions are welcomed and encouraged. Bear in mind that I don't necessarily need the 'Searching' text that gets overlaid on top, just the 'cover' would be enough.
3 divs instead of 2 works well:
http://jsfiddle.net/JhGCn/2/
html:
<div id="geogPickerAddressResultContainer" style="max-height:150px;overflow:auto;position:relative">
<div id="insideDiv">
<ul ...
</ul>
<div id="overlayDiv" style="display:none;">
<p style="margin-top:50px;text-align:center;font-size:18px;">Searching...</p>
</div>
</div>
</div>
css:
#insideDiv {
width: 100%;
height: 100%;
position: relative;
}
#overlayDiv {
background-color: white;
position: absolute;
top: 0px;
opacity: 0.8;
height: 100%;
width: 100%;
}
this works fine too:
http://jsfiddle.net/JhGCn/3/
var height = $('#addressPicker li').height();
$.each($('#addressPicker li'), function (i, addr) {
height += $(this).height();
$('#overlayDiv').css("height", height + "px");
etc..
I would take the overlay out of the parent, set a z-index and position it over the address picker with negative margin.
http://jsfiddle.net/JhGCn/1/
#overlayDiv{
background-color: white;
opacity: 0.8;
height: 100%;
width:100%;
position:absolute;
z-index:9999;
margin-top:-150px;
height:150px;
}
This a pattern I've seen before as well: http://jsfiddle.net/6oa6grn9/
#overlayDiv {
background-color: white;
opacity: 0.8;
position: absolute;
bottom: 0;
left: 0;
right: 0;
top: 0;
}

Place animated footer under other divs

so I wanted an animated footer for my webpage using jquery. There's supposed to be a button which should trigger the animation. I found a nice example for all this, and everything is fine and dandy. Except that the button (including the footer) has this code that makes it stick to the bottom of your web browser, rather than to the bottom of the page. I do [i]not[/i] want it to, like, "scroll" along with the page, I realy want it to be underneath all my other divs. I tried putting it in the div container (which has all my other divs in it as well), but that doesn't seem to work.
Now, (after 2.5 hours of googling) I found out that it might/may/could have something to do with "absolute" positioning in the CSS, so I tried switching some things around such as giving the footer's container a relative position or giving it an "overflow: hidden;" along with the rest a left float but nothing seemed to solve my problem. (I could've done something wrong, not that great with CSS after all :-/)
I hope someone is able/willing to help.
P.S. Here's the example I used:
http://return-true.com/2010/04/jquery-pop-up-footer-version-2/
and here's the code:
Javascript:
jQuery(function($) {
var open = false;
$('#footerSlideButton').click(function () {
if(open === false) {
$('#footerSlideContent').animate({ height: '300px' });
$(this).css('backgroundPosition', 'bottom left');
open = true;
} else {
$('#footerSlideContent').animate({ height: '0px' });
$(this).css('backgroundPosition', 'top left');
open = false;
}
});
});
HTML:
<div id="footerPlacement">
<div id="footerSlideContainer">
<div id="footerSlideButton"></div>
<div id="footerSlideContent">
<div id="footerSlideText">
<h3>Hey! I'm a Sliding Footer</h3>
<p>What's a Sliding Footer? Well I'm a cool little element which can be hidden from view, and revealed when the user wants to see me.</p>
<p>What can you use me for? Well look at all this stuff:</p>
<ul>
<li>Sales information</li>
<li>Important updates</li>
<li>Unobtrusive about panel</li>
<li>Or just a good ol' footer</li>
</ul>
<p>There are obviously many other uses, but these are the few useful ones I can think of.</p>
</div>
</div>
</div>
</div>
CSS:
#footerPlacement {
margin-bottom: 0px;
width: 1000px;
margin-left: auto;
margin-right: auto;
}
#footerSlideContainer {
position: fixed;
margin-left: 0px;
bottom:0px;
width: 1000px;
}
#footerSlideButton {
background: url('../images/footer/footerbtn.png') top left no-repeat transparent;
position: absolute;
top: -55px;
right: 20px;
width:50px;
height:50px;
border: none;
cursor: pointer;
}
#footerSlideContent {
width: 100%;
height: 10px;
background: #251b15;
color: #CCCCCC;
font-size: 0.8em;
border: none;
font-family: DejaVuSansBook, Sans-Serif;
}
#footerSlideText {
padding: 15px 10px 25px 25px;
}
Thanks in advance!
if you change your #footerPlacement to include position:relative, you can change #footerSlideContainer to be position:absolute and then your footer will sit below any content above it.
However you will need to make the content have a min-height of around 350px for the footer to work properly and if your content isn't long enough, the footer won't be at the bottom of the browser.
I also added overflow:hidden to #footerSlideContent. I have made a fiddle to demonstrate:
http://jsfiddle.net/tc6b8/

How to stack divs beside each other to create a carousel

I am trying to create a carousel, where clicking on any element will slide it leftwards, simultaneously sliding the right element into viewport. For that, I need to have the divs stacked side by side. I am trying it out as a float based layout (see Fiddle ).
Problem is that here clicking the red colored div slides it leftward alright, but not the green element leftwards. This is probably due to the fact that they are actually lying below another, as visible when the overflow: hidden is removed from #cont's style. How elese to stack them side by side so that sliding one leftward automatically slides the next one leftwards as well? (Creating the to-be-next element on the fly while clicking and animating it into viewport is a no-no, the element should be present in the DOM!)
I'd suggest you use a plugin, as there is more to this than you may realize. There are many plugins out there for this, here's a list to get you started: http://www.tripwiremagazine.com/2012/12/jquery-carousel.html
I modified your Javascript, HTML, and CSS to get you pointed in the right direction:
http://jsfiddle.net/nf5Dh/2/
You need a container contContent, positioned absolutely, and that container gets moved within the container div. You just float the elements in contContent to get them next to each other.
HTML:
<div id='cont'>
<div id="contContent">
<div id='i1'></div>
<div id='i2'></div>
<div id='i3'></div>
</div>
</div>
CSS:
#cont {
width: 50px;
padding-top: 10px;
background: blue;
height: 50px;
overflow: hidden;
position: relative;
}
#contContent {
height: 50px;
width: 150px;
position: absolute;
top: 0;
left: 0;
}
#contContent > div {
float: left;
display: inline-block;
height: 50px;
width: 50px;
}
#i1 { background: red; }
#i2 { background: green; }
#i3 { background: yellow; }
And the JS:
$("#contContent > div").click(function(){
$("#contContent").animate({left: "-=50px"},1000);
});
You'd probably be better off using an ul instead of all divs, this is at least more semantically correct, though not technically necessary.
<div id="carousel">
<ul id="carouselContent">
<li id="slide1"></li>
<li id="slide2"></li>
<li id="slide3"></li>
</ul>
</div>
This:
#cont {
white-space:nowrap;
overflow: hidden;
}
.pane { // or whatever the slide divs are called. get rid of the float.
float: none;
display: inline-block;
*zoom:1;
*display:inline;
}
You can use that carousel where you can generate javascript for the carousel http://caroufredsel.dev7studios.com/configuration-robot.php
I've used http://sorgalla.com/jcarousel/ for things like this in the past, that's based on postion: relative and left/right offsets. Probably easier than messing with floats.
You can try using a list item instead, and display them inline.

Categories