Animating a navigation menu coming in - javascript

I have some kind of sticky menu optimised with jQuery. I wrote some code to detect the height we're in and after a certain value bring the navigation down and make it sticky by setting its position value fixed!
Here is the code :
$(window).scroll(function () {
var $locationY = $(window).scrollTop(),
$defaultY = 385;
if ( $locationY < $defaultY ){
$('#nav').removeClass("sticky")
}
else {
$('#nav').addClass("sticky")
}
});
And the question is how can I animate this? To show up nicely for example slides from top to bottom. I wanna know what's the right approach for using slideDown, animate, ... methods for this case.
Thanks.

Something like this? DEMO http://jsfiddle.net/yeyene/UZgXB/1/
Not sure your sticky menu is shown on load or not.
JQUERY
$(document).ready(function () {
$(window).scroll(function () {
if ($(this).scrollTop() > 200) {
$('#nav').stop()
.addClass('sticky')
.animate({
'padding': '1% 2% 1% 2%'
}, 400, "swing");
} else {
$('#nav').stop()
.removeClass('sticky').addClass('normal')
.animate({
'padding': '6% 2% 6% 2%'
}, 400, "swing");
}
});
});
CSS
#nav, .normal {
float:left;
margin:0;
padding:6% 2%;
width:96%;
background:red;
}
.sticky {
position:fixed;
left:0;
top:0;
}

I think transition can help you.
#nav{
transition:top 2s ease;
}
And position the #nav using postion:fixed; and top:xxxpx; like
.sticky{
position:fixed;
top:300px;
}
demo Try it.

What I would do is have it position fixed, its top value equal to 0 minus its height. Then animate it to top value 0.
This way it will slide from the top exactly like the facebook timeline menu... The sticky class should have the negative top value, the JS will correct it in animation.
$(window).scroll(function () {
var $locationY = $(window).scrollTop(),
$defaultY = 385;
if ( $locationY < $defaultY ){
$('#nav').removeClass("sticky")
}
else {
$('#nav').addClass("sticky").animate({top:0},400);
}
});

Related

Smooth Transition Between Background Images

So, I made this script where the background changes the farther you scroll down the page, but I want it so there is a transition between each of the images. So when you scroll from one image to the next, it slowly fades into the next. Sort of like a parallax.
JS:
$(document).ready(function() {
$("body ").css("background-image", "url('http://i.imgur.com/rs2Ittp.jpg')");
$(window).scroll(function() {
if($(this).scrollTop() > 0) {
$("body ").css("background-image", "url('http://i.imgur.com/rs2Ittp.jpg')");
}
if($(this).scrollTop() > 1000) {
$("body ").css("background-image", "url('http://i.imgur.com/H5QLuD6.jpg')");
}
if($(this).scrollTop() > 2000) {
$("body ").css("background-image", "url('http://i.imgur.com/KzZpgdS.jpg')");
}
if($(this).scrollTop() > 3000) {
$("body ").css("background-image", "url('http://i.imgur.com/UsLLJSx.jpg')");
}
});
});
Any solutions are appreciated (:
The easiest solution is through CSS:
body {
transition: background-image 0.5s ease-in-out;
}
Edit: My answer may have been a bit premature, since this is not a cross-browser solution. A better way to do this would be by using two divs with different background images using transition: opacity 0.5s; A lot more javascript is involved in this solution though.
Here's one way of doing it.
Create two elements with position: fixed, then change the opacity as you scroll. Once you get over a certain scroll position, swap the next images in and use the same opacity logic minus the intended scroll length.
edit: my opacity math could be more refined + need to add swapping the images back when scrolling the reverse direction
<!-- html -->
<div class="bottom"></div>
<div class="top"></div>
/* css */
.bottom,
.top {
position: fixed;
background-size: cover;
height: 100%;
width: 100%;
}
// js
var img1 = 'url(http://i.imgur.com/rs2Ittp.jpg)'
, img2 = 'url(http://i.imgur.com/H5QLuD6.jpg)'
, img3 = 'url(http://i.imgur.com/KzZpgdS.jpg)'
$(document).ready(function() {
$('.top').css("background-image", img1)
$('.bottom').css("background-image", img2)
$(window).scroll(function() {
var scrollTop = $(this).scrollTop()
if (scrollTop < 1000) {
$('.top').css('opacity', 100 / scrollTop)
}
else if ($(this).scrollTop() > 1000) {
$('.top').css("background-image", img2)
$('.bottom').css("background-image", img3)
$('.top').css('opacity', 100 / (scrollTop - 1000))
}
})
})
codepen

How do I make a hidden div ease out from the top instead of from the left using .show()?

I am trying to animate my navigation menu to bounce in from the top when it reaches a certain anchor point. I am currently using the .show()/.hide() to accomplish this, but it only eases in from the left. I tried to incorporate .animate() into it with no luck.
This is what I have so far:
var t = $("#about").offset().top;
$(window).scroll(function(){
if( $(document).scrollTop() >= t ) {
$('#global-nav').show(500, 'easeOutBounce');
} else {
$('#global-nav').hide(500, 'easeInExpo');
}
});
html {
height: 2000px;
}
#global-nav {
height:50px;
background:#000;
z-index: 9999;
position: fixed;
left: 0;
top: 0;
width: 100%;
display: none;
}
#about{
margin-top:400px;
}
<div id="global-nav"></div>
<div id="about"></div>
I am using the jQuery Easing plugin and have the current code functional here, just scroll down to see it in action: http://jsfiddle.net/Hysteresis/0oazqj4y/30/
Is there an option for .show() to specify the ease in direction or do I need to incorporate the .animate() some how? I am fairly new to jQuery and have been working on this all day to no avail. Any help would be appreciated.
Try using .SlideDown() function in jQuery http://api.jquery.com/slidedown/
Try using slide() or its variants. Here's an example with slide down to show and slide up to hide:
$(window).scroll(function(){
if( $(document).scrollTop() >= t ) {
$('#global-nav').slideDown(500, 'easeOutBounce');
} else {
$('#global-nav').slideUp(500, 'easeInExpo');
}
});

jQuery sticky header jumps at specific height

I'm trying to create a basic sticky header.
The header contains 2 parts: top and main. When page is scrolled down, i want to keep only the .main sticky (so that the .top becomes invisible).
I'm trying following code, but it is jerky and if the content has a specific height, it does not let scroll, starts jumping. I have captured video to illustrate the problem. Please see:
http://www.screenr.com/Z89H
Here's the demo:
http://jsfiddle.net/M33g4/
(you might not see the issue because of different screen height, in that case drag the results window to set its height about 535px).
HTML:
<header>
<div class="top"></div>
<div class="main"></div>
</header>
<section>
</section>
jQuery:
$(window).scroll(function () {
var height = $('header').outerHeight();
if($(this).scrollTop() > height){
$('header').addClass('sticky');
}else{
$('header').removeClass('sticky');
}
});
I'm sure you will have fixed this by now but after encountering the same issue I came up with a solution:
The issue was caused by the document size not having enough leeway beneath the fold to fit the height of the overall header. This meant that if a visitor tried to scroll down, the sticky part of the header will become fixed, but immediately unfix itself.I believe it may be the bounce-back effect that causes the problem but I haven't tested to verify this.
In short, I fixed it by adding simple check to ensure that there is more than enough space beneath the fold by comparing the height of the body and the height of the window. i.e body height minus window height must be greater than the total header height. Here's the code that worked in my instance:
// Sticky sub navbar
var sub_nav_height = $('#sub-nav').outerHeight();
var total_height = $('#main-head').outerHeight();
var header_height = total_height - sub_nav_height;
var content_height;
var y;
$(window).scroll(function() {
// Only make sticky if window is large enough not to cause jumping issue
content_height = $('body').height() - $(window).height();
if(content_height > total_height) {
y = $(this).scrollTop();
if($(this).scrollTop() > header_height) {
$('#sub-nav').addClass('fixed');
} else {
$('#sub-nav').removeClass('fixed');
}
}
});
There are two caveats which I decided were absolutely fine for my scenario. The first is that an extra calculation has been added every time the scroll event is triggered, but this hasn't caused me any performance issues. The second is that the sticky header functionality is simply disabled when a vistor's window is a problematic size, but again I had no qualms with this as the navbar could still just about be seen.
Check this
http://jsfiddle.net/M33g4/3/
JS
$(window).scroll(function () {
var height = $('.top').height();
if($(this).scrollTop() > height){
$('.top').hide();
$('header').addClass('sticky');
}else{
$('.top').show();
$('header').removeClass('sticky');
}
});
CSS
*{
margin: 0;
padding: 0;
}
header{
width: 100%;
}
.top{
height: 50px;
background: blue;
}
.main{
height: 70px;
background: green;
}
section{
height: 560px;
background: yellow;
}
.sticky{
position: fixed;
width: 100%;
}
You should target to the top but not to whole header demo
$(window).scroll(function () {
var height = $('header .top').outerHeight();
if($(this).scrollTop() > height){
$('header').addClass('sticky');
}else{
$('header').removeClass('sticky');
}
});
http://jsfiddle.net/M33g4/1/
$(window).scroll(function () {
var height = $('.top').outerHeight();
if($(this).scrollTop() > height){
$('header').addClass('sticky');
}else{
$('header').removeClass('sticky');
}
});
guess you got the wrong height.
Updated:
The blinking issue is caused by height changing (due to position: fixed)
check this one: http://jsfiddle.net/M33g4/6/
$(window).scroll(function () {
var height = $('.top').outerHeight();
if($(this).scrollTop() > height){
if($('.main.sticky').length == 0) {
$('header').append(
$('.main').clone().addClass('sticky'));
}
}else{
$('.main.sticky').remove();
}
});
and stick .main only:
.sticky{
position: fixed;
width: 100%;
top: 0;
}
This works for me:
Set the height variable to 30:
$(window).scroll(function () {
var height = 30;
if($(this).scrollTop() >= height){
$('header').addClass('sticky');
}else{
$('header').removeClass('sticky');
}
});
and change the css for the sticky class to the following:
.sticky{
position: fixed;
width: 100%;
top: -30px;
left: 0;
}
Top is -30 instead of -40. Works for me!
Check how the content in this demo snaps to the top, under the header, but not visible. You might want to resize the Results window to about 500px. Is there a solution to this please?
$(window).scroll(function () {
var height = $('.top').outerHeight();
if($(this).scrollTop() > height){
$('header').addClass('sticky');
}else{
$('header').removeClass('sticky');
}
});

Animating DIV to Bottom of page and then on another click animate again to Top

i was working on this div animation where the original position of div from top is 70% and the div is absolute.
Now, when I click on button it slides to bottom of page with top:95%.
Now I want to check if the position is top:95% and if so, then i want to slide it back to top:70%;
Somehow the Div slides to 95% but dosent come back. what i am doing wrong here??
code
css:-
#mainMenu {
width: 100%;
height: 30px;
background-color: black;
top: 70%;
position: absolute;
}
body {
margin: 0px;
}
#clickToCheck {
font-size: 22px;
}
JQuery
<script>
$(document).ready(function () {
$('#mainMenu').click(function () {
$("#mainMenu").animate({ top: "95%" }, 1100);
});
});
$(document).ready(function () {
$('#clickToCheck').click(function () {
if ($('#mainMenu').position().top === '95%') {
$("#mainMenu").delay(1000).animate({ top: "70%" }, 1200);
} else {
alert('its not at bottom');
}
});
});
and Html
<body>
<span id="clickToCheck">Click to CHeck</span>
<div id="mainMenu"></div>
The problem is that the function
$('#mainMenu').position().top
Will return the value in pixels instead of percentage. So if you want to check if the top is 95% you will have to do the math based on the top and window height (or div height). here is the code:
$('#mainMenu').position().top/$(window).height()*100
Here you will have the the percentage of the #mainMenu in relation to the full window. If the #mainMenu is inside a div, just do based on the div's height. Also beware that you will probably get a number like 94.2343123. So when checking, I would not do and "if = 95". I would do something like "if >= 93" or something like it.
The basic problem is that .position(), .offset(), and .css() all work in pixels by default.
A reasonable workaround would be to store the the menu's original .offset() using .data() and just check to see if its offset has changed, like so:
Working Example
$(document).ready(function () {
$('#mainMenu').data('startPos', $('#mainMenu').offset().top); // when the doc is ready store the original offset top.
$('#mainMenu').click(function () {
$("#mainMenu").animate({
top: "95%"
}, 1100);
});
$('#clickToCheck').click(function () {
if ($('#mainMenu').offset().top > $('#mainMenu').data('startPos')) { // if new offset is greater than original offset
$("#mainMenu").delay(1000).animate({
top: '70%'
}, 1200);
} else {
alert('its not at bottom');
}
});
});

Footer slides up with .slideUp but then slides down

I've got the jQuery .slideUp and .slideDown function below, and when reaching the #showfootershop div at the bottom of the browser window, the #footershop div slides up and then immediately slidesdown.
How can I get the #footershop to remain "up" and visible when #showfootershop is at the bottom of the browser window and not slide down until the user scrolls the browser window up?
Fiddle: http://jsfiddle.net/8PUa9/1/
jQuery:
$(window).scroll(function(){
/* when reaching the element with id "showfootershop" we want to
show the slidebox. */
var distanceTop = $('#showfootershop').offset().top - $(window).height();
if ($(window).scrollTop() > distanceTop)
$("#footershop").slideUp();
else
$("#footershop").slideDown();
});
html in footer:
<div id="showfootershop"></div>
<div id="footershop">
<h1>Shop Links</h1>
</div>
</body>
</html>
CSS:
#footershop {
height:35px;
width:100%;
display: none;
z-index: 2;
}
Use two functions for slidingUp and slidingDown, and toggle them once you have shown the slider and hidden it alternatively.
$(function() {
var slideUp = function() {
if ($(window).scrollTop() + $(window).height() >= $(document).height()) {
console.log('At bottom!!');
//toggle the handlers
$("#footershop").slideDown(function() {
$(window).off('scroll', slideUp).on('scroll', slideDown);
});
}
};
var slideDown = function() {
if ($(window).scrollTop() + $(window).height() < $(document).height()) {
//toggle the handlers
$("#footershop").slideUp(function() {
$(window).off('scroll', slideDown).on('scroll', slideUp);
});
}
};
$(window).on('scroll', slideUp);
});​
EDIT: I think the main problem you have is #footershop increases document.height when it shows and reduces when hidden, which is correct. This causes additional scroll events which creates the undesired behaviour.
Check this fiddle: I fixed this partially.
http://jsfiddle.net/BuddhiP/8PUa9/8/
Check this JSBin version for fixed version: http://jsbin.com/axobow/2
Main thing I did was #footershop is now absolutely positioned, so it doesn't cause the document size to change when shown or hidden, which is important in this case as if document.height() changed it affects you calculation.
Although fiddle works as expected, div is not positioned right on bottom. I hope you can fix that.
Hope this helps.
NOTE: You need to test the fiddle with full-height window, otherwise you will not see the footer sliding up since it shows somewhere in the middle of text.
I'm not sure what's wrong with the other answers that you haven't accepted, but here's mine:
JSFiddle
JS:
$(window).scroll(function() {
var distanceTop = $('#showfootershop').offset().top - $(window).height();
if ($(window).scrollTop() >= distanceTop - 20) {
$("#footershop").animate({
'height': '35px'
}, 'fast');
}
else {
$("#footershop").animate({
'height': '0px'
}, 'fast');
}
});​
CSS:
#footershop {
height:0px;
width:100%;
z-index: 2;
background:#00ffff;
position: absolute;
bottom:0;
left:0;
overflow:hidden;
}
body {
position:relative;
}
​
An alternative to all of this jQuery slideUp/slideDown is to use CSS to handle it.
We detect when the user has reached your #showfootershop element and then add or remove a class from the footer:
$(window).scroll(function()
{
var distanceTop = $('#showfootershop').offset().top - $(window).height();
if($(document).scrollTop() >= distanceTop)
$('#footershop').addClass("show");
else
$('#footershop').removeClass("show");
}
Then we use CSS to display the footer or hide it depending on the presence of that class:
#footershop
{
position: fixed;
height: 0px;
z-index:999;
bottom: 0;
overflow:none;
-moz-transition:all 0.5s ease-in-out;
-o-transition:all 0.5s ease-in-out;
transition:all 0.5s ease-in-out;
-webkit-transition:all 0.5s ease-in-out;
}
#footershop.show
{
height:35px;
-moz-transition:all 0.5s ease-in-out;
-o-transition:all 0.5s ease-in-out;
transition:all 0.5s ease-in-out;
-webkit-transition:all 0.5s ease-in-out;
}
As you can see above when the .show class is on the footer we change the height of the footer element to display it. CSS transitions are then used to animate this change.
The nice thing about this method is it's very lightweight and efficient (especially if you've got a lot of jQuery animations working at the same time), and you can easily animate various different changes like the opacity, text and background colours, etc. without needing to touch your JS at all.
jsFiddle
Here's your jsFiddle modified
http://jsfiddle.net/DigitalBiscuits/8PUa9/29/
slideUp() will also hide the element and offset of a hidden element is [0,0] so the instant footer is hidden distanceTop is negative. You could animate height to zero and get same visual result and since you aren't hiding the footer it will still have same top offset
I would recommend just putting a little buffer inbetween your scroll up and scroll down code.
I have made a slight tweak to your code to put in a buffer of 100px:
Javascript
$(window).scroll(function() {
var distanceTop = $('#showfootershop').offset().top - $(window).height();
if ($(window).scrollTop() >= distanceTop) {
$("#footershop").slideDown();
}
else if ($(window).scrollTop() < (distanceTop - 100)) {
$("#footershop").slideUp();
}
});
Demo
Trying to scroll to an element is way too messy, just use the bottom of the page.
$(window).scroll(function() {
if ($(window).scrollTop() + $(window).height() == $(document).height()) {
$("#footershop").slideDown();
}
else {
$("#footershop").slideUp();
}
});​
jsfiddle

Categories