Positioning the top attribute of a element with jquery - javascript

I'm having an annoying issue trying to position the responsive navigation hamburger. I am using a plugin called responsive menu which creates the hamburger and uses absolute positioning.
I am trying to position the hamburger in the centre of the header at all times.
To achieve this I am using the following jQuery code.
However, the issue I have is when the hamburger is displayed and you scroll down the page and scroll back to the top of the page quickly. The hamburger does not position itself in the centre of the header. You need to scroll back down slightly for it to jump into place.
Any ideas how I can fix this please.. It's driving me crazy and I don't know jquery very well :(
Thank you for any advice in advance :)
Link to the site in question
$( window ).on("load resize scroll", function(e){
var headerHeight = $('nav').height()/2;
var iconHeight = $('#click-menu').height()/2;
var total = headerHeight - iconHeight;
if ($(window).scrollTop() >= 1) {
$('#click-menu').css('top', total);
}
else {
$('#click-menu').css('top', total);
}
});

It's hard for me to test and confirm this, but I believe the reason it's position is off when it hits the top is because the evaluation of $('nav').height()/2; happens immediately, but the header animates to size over 300 ms.
Although a bit hacky, I think you can solve the problem by adding a setTimeout
function setNavTop(){
var headerHeight = $('nav').height()/2;
var iconHeight = $('#click-menu').height()/2;
var total = headerHeight - iconHeight;
$('#click-menu').css('top', total);
}
$( window ).on("load resize scroll", function(e){
if ($(window).scrollTop() >= 1) {
setNavTop();
}
else {
setTimeout(setNavTop, 300); // wait for header to animate to size.
}
});
Since it has to delay for 300ms before adjusting the icon, its looks a bit glitchy. You can improve this by adding tweening the setTimeout. Not the most elegant, but it works
setNavTop();
setTimeout(setNavTop, 100);
setTimeout(setNavTop, 200);
setTimeout(setNavTop, 300);

Related

jQuery Change top value on scroll

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');
}

Browser Resize event for sticky navigation

I've been dealing with this problem since days now and I hope somebody here can help me.
I'm trying to make a sticky navigation and a 100% height header (body and html are set to 100% height too). Basically the problem I have is that the sticky navigation only works well after the page is (re)loaded. However scrolling after having resized the browser's window makes the navigation either jump to early or to late to the fixed position at the very top.
I'd need to implement a resize event I guess, so that the calculation of the variable "navOffset" fires everytime the window is resized, right?
I tried many ways of inserting this into my code which are also explained in the link below, but I falied everytime.
I hope somebody can disclose this secret to me as I'm getting insane about this.
Thanks a lot and have a great week!
Sascha
Example of the effect I want to achieve:
http://html5-webdesign.berlin/
Tutorials, which didn't help me:
https://stackoverflow.com/…/jquery-combine-document-ready-an…
jQuery(document).ready(function() {
var navOffset = jQuery("nav").offset().top;
jQuery("nav").wrap('<div class="nav-placeholder"></div>');
jQuery(".nav-placeholder").height(jQuery("nav").outerHeight());
jQuery(window).scroll(function() {
var scrollPos = jQuery(window).scrollTop();
if (scrollPos >= navOffset) {
jQuery("nav").addClass("fixed");
} else {
jQuery("nav").removeClass("fixed");
}
});
});
Just copy your second function (which you should probably name) and add it to the window resize event:
jQuery(document).ready(function() {
var navOffset = jQuery("nav").offset().top;
jQuery("nav").wrap('<div class="nav-placeholder"></div>');
jQuery(".nav-placeholder").height(jQuery("nav").outerHeight());
function setPosition() {
var scrollPos = jQuery(window).scrollTop();
if (scrollPos >= navOffset) {
jQuery("nav").addClass("fixed");
} else {
jQuery("nav").removeClass("fixed");
}
}
jQuery(window).scroll(setPosition);
jQuery(window).resize(setPosition);
});

Change scrollTop offset

I am using bootstrap 3 and have a fullscreen hero unit at the top of my page, below that is my navigation. I have some js which allows my navbar to stick to be fixed at the top after you scroll past the full screen hero. Also some js for my smooth scrolling links.
The problem is the offset is different before you scroll past the full screen hero and after. But it works fine when you are past the jumbotron. I have tried a bunch of different things but I can seem to get this to work exactly.
Check out the fiddle here.
Here is my js for the smooth scrolling links:
$(document).ready(function() {
// navigation click actions
$('.scroll-link').on('click', function(event){
event.preventDefault();
var sectionID = $(this).attr("data-id");
scrollToID('#' + sectionID, 750);
});
// scroll to top action
$('.scroll-top').on('click', function(event) {
event.preventDefault();
$('html, body').animate({scrollTop:0}, 1200);
});
// mobile nav toggle
$('#nav-toggle').on('click', function (event) {
event.preventDefault();
$('#main-nav').toggleClass("open");
});
});
// scroll function
function scrollToID(id, speed){
var offSet = 95;
var targetOffset = $(id).offset().top - offSet;
var mainNav = $('#main-nav');
$('html,body').animate({scrollTop:targetOffset}, speed);
if (mainNav.hasClass("open")) {
mainNav.css("height", "1px").removeClass("in").addClass("collapse");
mainNav.removeClass("open");
}
}
if (typeof console === "undefined") {
console = {
log: function() { }
};
}
By changing var offSet = 95; I am able to adjust the offset but what would be the best way to use 180 before the navbar sticks to the top but 95 when it does?
Also here is the js I am using for my navbar:
$(function () {
/* $(".navbar-fixed-top").css({"top":$(".jumbotron").height()});
$(window).resize(function (e) {
$(".navbar-fixed-top").css({"top":$(".jumbotron").height()});
});*/
$(document).on( 'scroll', function(){
console.log('scroll top : ' + $(window).scrollTop());
if($(window).scrollTop()>=$(".jumbotron").height())
{
$(".navbar").addClass("navbar-fixed-top");
}
if($(window).scrollTop()<$(".jumbotron").height())
{
$(".navbar").removeClass("navbar-fixed-top");
}
});
});
Are you open to angular.js? I have a directive i use for this. As seen here.
I'll grab the plunker link for you. you might find the code helpful.
Essentially you need to create a ghost dom element to take the place of the menu when you pull it to an new layout position.
EDIT: Here it is
I won't suggest grabbing angular just for this. But you can use the basis of the events and logic to build your own solution.
This here is creating an element and placing in its place
$scope.spacer = $element.after(
'<div class="spacer" style="height:' + $element[0].clientHeight + 'px"> </div>').next();
then this element is removed when the menu is back to its static position.
Inspect the dom and watch how it changes, this will probably help you see the events and changes that need to take place.
EDIT 2 SOLUTION:
HERE is the concepts applied to your JSFiddle
It's not the best solution but by adding margin: 0 0 -100px 0; to your .navbaryou lose the spacing issue.
Also you're getting 22 console errors because of missing images. I'm not saying that this is causing any major problems but you would be better off losing them.
The problem is that when you have not scrolled past the hero, navigation is still part of the layout and pushes content bellow it a little lower. When you scroll past (either manually or via a script) the hero, navigation is removed and fix positioned. That makes everything which was bellow to "jump up" exactly of the navigation height.
That means if portfolio was 1000px from the top, on click you say: go 1000px from top; but then porfolio moves 100px up (as explained above) meaning it is now 900px from the top while the window scrolled 1000px as you asked.
When you have scrolled past the hero, nothing changes its position.

Jquery Scroll One pixel from where ever the user is on screen

okay heres the scenario. I have a one page website with may sections using anchor links. Whe the user is on a secondary layout (page) and when they click on to go to a section on the main page again, for some reason the graphics dont load properly until a scroll happens. All I want to do is whenever the main layout is loaded, no matter which anchor it loads to, simply scroll the page up or down by 1 pixel.
$.scrollTo({ top: '+=100px', left: '+=0px' }, 800);
I tried the above, but this code simply takes the user 100 pixels from the top. I don't want that to happen, i.e. not from the top but from where ever the user is on screen.
use jquery scrollTop() to set the scroll position to the current scroll position + 1:
$(window).scrollTop($(window).scrollTop()+1);
I have a similar problem. I want to scroll down 1 pixel and then 1 pixel up, so the user hopefully won't notice anything at all. I did this:
window.scrollBy(0, 1); // 0 pixels horizontal and 1 pixel down
window.scrollBy(0, -1); // 0 pixels horizontal and 1 pixel up
UPDATE:
But I might end up using JQuery instead. All I want is the scroll event to fire and I can do that with:
$(window).scroll();
A pure JavaScript solution without the jQuery overhead:
window.scrollY += 100;
With jQuery (and a fancy animation):
var cur = $(window).scrollTop();
$(window).animate({scrollTop: cur + 100});
$("html, body").animate({scrollTop: ($(window).scrollTop() + 1)});

Keeping sidebar in viewport, problem with scrolling

I've got a solution for keeping a sidebar in the viewport as you scroll up and down the page. Problem comes in when the sidebar is longer than the content area, and you keep scrolling you get this jittering effect as the sidebar keeps pushing the footer down.
I've got an example of this setup in jsFiddle: http://jsfiddle.net/U9F7w/2/ (full screen: http://jsfiddle.net/U9F7w/2/embedded/result/ )
My question is, is there a way to make the sidebar stop once it touches the bottom/footer area?
I've read some solutions about setting the sidebar to absolute, unfortunately it's an existing site and changing the position didn't work and messed with a lot of the existing page elements.
Here's the jQuery/js I'm working with:
// set the offset
var sidebarOffset = $(".sidebar").offset();
var sidebarPadding = 15;
// when the window scrolls, keep sidebar in view
$(window).scroll(function() {
if ($(window).scrollTop() > sidebarOffset.top) {
$(".sidebar").stop().animate({marginTop: $(window).scrollTop() - sidebarOffset.top + sidebarPadding });
}
else {
$(".sidebar").stop().animate({marginTop: 0});
};
});
edit
One thing I thought about was (not sure if this is possible) to detect if the bottom of one div was lower than the bottom of another, stop the scrolling. Is there a way to detect if the bottom of one div is lower than the other?
Check if the sidebar's height is greater then that of the content:
var ct = $(".content");
var sb = $(".sidebar");
var sbOffsetTop = sb.offset().top;
var sbPadding = 15;
$(window).scroll(function() {
if (sb.height() < ct.height()) {
if ($(window).scrollTop() > sbOffsetTop) {
sb.stop().animate({top: $(window).scrollTop() - sbOffsetTop + sbPadding });
}
else {
sb.stop().animate({top: 0});
};
};
});
See demo fiddle with large content and demo fiddle with large sidebar.
And I don't know why exactly, I would use top in conjunction with position: relative, but marginTop works also fine.

Categories

Resources