I have created small menu order application, I have added 5 menu categories is Desserts, salad, thai noodles and more using horizontal scroll bar. if I click salad or any categories move left and right position working fine in chrome. I checking safari browser not working horizontal scroll. what I am missing. could you please check and let me know.
html:
<div class="menu" id="menu">
<div class="topnav sticky" id="stickyMenu"><span data-id="appetizers" id="nav1" class="cat-nav">Appetizers</span><span data-id="desserts" id="nav2" class="cat-nav">Desserts</span><span data-id="pizza--classic-11-inches-" id="nav3" class="cat-nav active">Pizza (Classic 11 inches)</span><span data-id="salad" id="nav4" class="cat-nav">Salad</span><span data-id="thai-noodles" id="nav5" class="cat-nav">Thai Noodles</span></div>
<!-- <div class="row filter">
<input type="text" id="gsearch" class="form-control gsearch" placeholder="Search within this Menu...">
</div> -->
</div>
js code:
$(document).on('click', ".topnav .cat-nav", function(e) {
$(".topnav .cat-nav").removeClass("active");
$(this).addClass("active");
var target = $(this).data("id");
$('html, body').animate({
scrollTop: ($("#"+target).offset().top - 50)
}, 500);
});
$(window).scroll(function() {
//get current sroll position
var scrollPosition = $(window).scrollTop();
//get the position of the containers
var s=["appetizers","desserts","pizza--classic-11-inches-","salad","thai-noodles"];
for (i=0; i<s.length; i++) {
if (scrollPosition >= ($("#"+s[i]).offset().top) - 190) {
$("#nav"+(i+1)).addClass("active");
$("#nav"+(i+1)).siblings().removeClass("active");
// $('.cat-nav').scrollLeft(myScrollPos);
var element = document.querySelector(".active");
element.scrollIntoView({behavior: "smooth" ,inline: "center"});
// $("#nav"+(i+1)).css({behavior: "smooth" ,inline: "center"});
}
}
});
Add overflow: auto to your sticky or topnav class:
.sticky {
overflow: none;
overflow-x: auto;
display: block;
}
This might work.
Related
Smooth scrolling effect in JQuery not working in IE & Mozila Browsers, its fine in Chrome browser can any one help on this. iam using this code. some times working in mozila but in IE. please ignore stickit() function.
Thanks in Advance.
< script src = "https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js" > < /script> <
script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" > < /script> <
script src = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" > < /script> <
script src = "scroll_110.js" > < /script>
$(document).ready(function() {
// Add scrollspy to <body>
$('a').scrollspy({
target: "a",
offset: 50
});
// Add smooth scrolling on all links inside the navbar
$("a").on('click', function(event) {
// Make sure this.hash has a value before overriding default behavior
if (this.hash !== "") {
// Prevent default anchor click behavior
event.preventDefault();
// Store hash
var hash = this.hash;
// Using jQuery's animate() method to add smooth page scroll
// The optional number (800) specifies the number of milliseconds it takes to scroll to the specified area
$('body').animate({
scrollTop: $(hash).offset().top
}, 1200, function() {
// Add hash (#) to URL when done scrolling (default click behavior)
window.location.hash = hash;
});
} // End if
});
});
// Create a clone of the menu, right next to original.
jquery('.menu').addClass('original').clone().insertAfter('.menu').addClass('cloned').css('position', 'fixed').css('top', '0').css('margin-top', '0').css('z-index', '500').removeClass('original').hide();
scrollIntervalID = setInterval(stickIt, 10);
function stickIt() {
var orgElementPos = jquery('.original').offset();
orgElementTop = orgElementPos.top;
if (jquery(window).scrollTop() >= (orgElementTop)) {
// scrolled past the original position; now only show the cloned, sticky element.
// Cloned element should always have same left position and width as original element.
orgElement = jquery('.original');
coordsOrgElement = orgElement.offset();
leftOrgElement = coordsOrgElement.left;
widthOrgElement = orgElement.css('width');
jquery('.cloned').css('left', leftOrgElement + 'px').css('top', 0).css('width', widthOrgElement).show();
jquery('.original').css('visibility', 'hidden');
} else {
// not scrolled past the menu; only show the original menu.
jquery('.cloned').hide();
jquery('.original').css('visibility', 'visible');
}
}
#top,
#middle,
#bottom {
height: 1600px;
width: 900px;
background: green;
}
.menu {
background: #fffff;
color: #333;
height: 40px;
line-height: 40px;
letter-spacing: 1px;
width: 100%;
}
<div class="menu">
Top
Middle
Bottom
</div>
<div id="top">
Top</div>
<div id="middle">
Middle</div>
<div id="bottom">
Bottom</div>
the solution would be to use both html and body in JQ -> $('html,body').animate
see below ( i removed the scrollspy code as it's not relevant to this question, but you should keep it )
$(document).ready(function() {
// Add scrollspy to <body>
// Add smooth scrolling on all links inside the navbar
$("a").on('click', function(event) {
// Make sure this.hash has a value before overriding default behavior
if (this.hash !== "") {
// Prevent default anchor click behavior
event.preventDefault();
// Store hash
var hash = this.hash;
// Using jQuery's animate() method to add smooth page scroll
// The optional number (800) specifies the number of milliseconds it takes to scroll to the specified area
$('html,body').animate({
scrollTop: $(hash).offset().top
}, 1200, function() {
// Add hash (#) to URL when done scrolling (default click behavior)
window.location.hash = hash;
});
} // End if
});
});
div {
height: 500px;
width: 100%;
background: red;
border-top: 10px solid blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>Section1</li>
<li>Section2</li>
<li>Section3</li>
</ul>
<div id ="section1">
</div>
<div id ="section2">
</div>
<div id ="section3">
</div>
I am working on a website redesign for my personal portfolio website. I had a cool feature in mind where my header/navigation bar would change colour depending on what section of the webpage it is on (The website is one page only).
The only way i could think of doing this is adding onclick events to the links that go to the different sections of the page, however this would not allow me to change the colour of the header/navigation bar for when the user scrolls manually to a new section.
I was wondering if someone could point me in the right direction as I'm not sure where to start.
Here is the website as it stands now if people want to view it:
www.kylebinger.com
Here is my HTML markup regarding the header
<header>
<div class="container">
<nav>
Welcome
Work
Case Study
About
Contact
</nav>
</div>
</header>
Thanks in advance for any help.
JQuery's offset and scrollTop functions should do the trick. .offset() gets the current coordinates of the element, while .scrollTop() will get the current scrollbar position. Compare them and change CSS when conditions are met. See example:
var top1 = $('#home').offset().top;
var top2 = $('#featuredWork').offset().top;
var top3 = $('#caseStudy').offset().top;
$(document).scroll(function() {
var scrollPos = $(document).scrollTop();
if (scrollPos >= top1 && scrollPos < top2) {
$('#change').css('background-color', '#f00');
} else if (scrollPos >= top2 && scrollPos < top3) {
$('#change').css('background-color', '#0f0');
} else if (scrollPos >= top3) {
$('#change').css('background-color', '#00f');
}
});
body {
margin: 0;
padding-top: 30px
}
header {
position: fixed;
top: 0;
width: 100%;
height: 30px;
background-color: #000;
}
section {
height: 500px;
background-color: #aaa;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header id="change">
<div class="container">
<nav>
Welcome
Work
Case Study
</nav>
</div>
</header>
<section id="home">Content</section>
<section id="featuredWork">Content</section>
<section id="caseStudy">Content</section>
I currently have a number of div tags that can be seen below that are each the height of the viewport.
<!-- .current represents the div the user is currently viewing -->
<div class="full-height current" id="id1">
<div class="container">
</div>
</div>
<div class="full-height" id="id2">
<div class="container">
</div>
</div>
<div class="full-height" id="id3">
<div class="container">
</div>
</div>
<div class="full-height" id="id4">
<div class="container">
</div>
</div>
<div class="full-height" id="id5">
<div class="container">
</div>
</div>
I am attempting to implement a feature where upon a user scrolling, the window will scroll to the next div tag, always having only one div in view at a time. The way I implemented it works great, except for the fact that the animation triggers the scroll event again, resulting in an endless loop of the page scrolling once the user scrolls at all. I attempted to fix this by having a variable that will stop the event from triggering if the animation is in progress, but it does not seem to work. I am aware that I didn't do it for the scroll up, but I just wanted to see if it worked for the down first.
$(window).scroll(function(event) {
var scrollTop = $(this).scrollTop();
// If user scrolls down
if ((scrollTop > lastScrollTop) && $(".current").next("div").length > 0) {
if (animating == false) {
console.log("down");
$(".current").next("div").addClass("current");
$(".current").first().removeClass("current");
animating = true;
$("html, body").animate({
scrollTop: $(".current").offset().top
}, 1000, function() {animating = false});
}
// If user scrolls up
} else {
if ($(".current").prev("div").length > 0) {
console.log("up");
$(".current").prev("div").addClass("current");
$(".current").last().removeClass("current");
$("html, body").animate({
scrollTop: $(".current").offset().top
}, 1000);
}
}
lastScrollTop = scrollTop;
});
CSS included just in case. The 100vh - 111px is due to a fixed navbar at the top that is 111px high
/* Makes the element take up the entire height of the screen */
.full-height{
height: -o-calc(100vh - 111px); /* opera */
height: -webkit-calc(100vh - 111px); /* google, safari */
height: -moz-calc(100vh - 111px); /* firefox */
}
#id1 {
background-color: red;
}
#id2 {
background-color: blue;
}
#id3 {
background-color: yellow;
}
#id4 {
background-color: green;
}
#id5 {
background-color: purple;
}
If anyone could give me any ideas for fixing my problem, that would be great.
You'll want to stop the event and preventDefault. Here is some code from a current landing page:
$(document).ready(function () {
$('a.page-scroll').on('click', function(event) {
var link = $(this);
$('html, body').stop().animate({
scrollTop: $(link.attr('href')).offset().top - 50
}, 500);
event.preventDefault();
});
$('body').scrollspy({
target: '.navbar-fixed-top',
offset: 80
});
});
It uses bootstrap scrollspy so just ignore that. But notice that it stops any scroll animation that could be running and then also calls event.preventDefault() to stop the scroll event from bubbling and thus becoming recursive.
EDIT:
O.k. so I've a better look and the basic problem re: infinite scrolling is the code doesn't check if the scrollTop is already at 'where it needs to be'. You need an additional check to short circuit the scroll:
if (animating == false) {
if ($(this).scrollTop() == lastScrollTop) return;
if (($(this).scrollTop() > lastScrollTop) && $(".current").next("div")) {
console.log("down");
$(".current").next("div").addClass("current");
$(".current").first().removeClass("current");
animating = true;
$("html, body").stop().animate({
scrollTop: $(".current").offset().top
}, 1000,
function () { lastScrollTop = $(this).scrollTop(); animating = false; });
// If user scrolls up
} else {
if ($(".current").prev("div").length > 0) {
console.log("up");
$(".current").prev("div").addClass("current");
$(".current").last().removeClass("current");
$("html, body").stop().animate({
scrollTop: $(".current").offset().top
}, 1000, function () { lastScrollTop = $(this).scrollTop(); animating = false; });
}
}
}
Otherwise as it stands it will always either scroll up or down and never settle. That said with that "working" it's a terrible user experience. It will jump about since your scroll to code will fight the user on current scrollTop if they keep scrolling. i.e. your code will make it jump back to a previous position.
Try defining scroll event handler as named function ; defining lastScrollTop outside of scroll handler ; substituting .one() for .on() to allow animation to complete before re-attaching scroll event ; use .promise() which should be called at most once to avoid .animate() complete callback being called twice with selector "html, body" ; substituting single if to check for next or previous element .length and .animate() call for multiple if..else conditions and statements, animation function calls ; re-attach scroll event at .then() following animation completion .promise()
var lastScrollTop = 0;
function scroller(event) {
var scrollTop = $(this).scrollTop();
var direction = scrollTop > lastScrollTop ? "next" : "prev";
var el = $(".current")[direction](".full-height");
console.log(direction === "next" ? "down" : "up");
if (el.is("*")) {
$("html, body").animate({
scrollTop: el.offset().top
}, 1000).promise().then(function() {
console.log(this)
lastScrollTop = $(window).scrollTop();
$(".current")
.removeClass("current")[direction]("div")
.addClass("current")
setTimeout(function() {
$(window).one("scroll", scroller)
})
});
} else {
lastScrollTop = scrollTop;
$(window).one("scroll", scroller)
}
}
$(window).one("scroll", scroller);
/* Makes the element take up the entire height of the screen */
.full-height {
height: -o-calc(100vh - 111px);
/* opera */
height: -webkit-calc(100vh - 111px);
/* google, safari */
height: -moz-calc(100vh - 111px);
/* firefox */
}
#id1 {
background-color: red;
}
#id2 {
background-color: blue;
}
#id3 {
background-color: yellow;
}
#id4 {
background-color: green;
}
#id5 {
background-color: purple;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- .current represents the div the user is currently viewing -->
<div class="full-height current" id="id1">
<div class="container">
</div>
</div>
<div class="full-height" id="id2">
<div class="container">
</div>
</div>
<div class="full-height" id="id3">
<div class="container">
</div>
</div>
<div class="full-height" id="id4">
<div class="container">
</div>
</div>
<div class="full-height" id="id5">
<div class="container">
</div>
</div>
If you define height 100vh ,scroll event wont trigger
I have a fixed header with on my website at 65px tall. I have a secondary navigation about 3/4 down the page that I want to fix to the bottom of my header once scrolled to it.
I've used Josh Lee's answer on this post to get the functionality to work, however, because my header is fixed, the secondary navigation scrolls right past it and becomes fixed once it hits the top of the page.
Since it completely bypasses my header, how can I set an offset for the trigger so that it happens 65px from the top of the screen?
In my <head>:
<script>
function moveScroller() {
var move = function() {
var st = $(window).scrollTop();
var ot = $("#scroller-anchor").offset().top;
var s = $("#mydiv");
if(st > ot) {
s.css({
position: "fixed",
top: "65px"
});
} else {
if(st <= ot) {
s.css({
position: "relative",
top: ""
});
}
}
};
$(window).scroll(move);
move();
}
</script>
On my page:
<div id="scroller-anchor"></div>
<div id="mydiv" class="">
<ul class="wrap">
<li> ... </li>
<li> ... </li>
<li> ... </li>
<li> ... </li>
</ul>
</div>
<script type="text/javascript">
$(function() {
moveScroller();
});
</script>
I believe you will need to account for the space when you are checking when to change the position to fixed for example change ot variable to
var ot = $("#scroller-anchor").offset().top - 65;
I don't know if this could be considered the "correct" way of solving my problem, but it seemed to have worked for me... I added top:-65px to the scroller-anchor element.
<div id="scroller-anchor" style="top: -65px;"></div>
I have a website, it has a sticky nav placed at the bottom of a <header> element, as long as I scroll to a section it actives a class using data-attributes , the bug here is: when I scroll the class active adds on the half of the section even the scroll does not scroll according to the section.
What I want is to turn on the active class as long as I get the anchor of each section, I leave my code below followed by a jsfiddle you can see what is the problem, I hope you guys can help me.
The HTML:
<header class="testheader">
<nav id="cloud_nav" class="absolute">
<ul>
<li>Section 1</li>
<li>Section 2</li>
<li>Section 3</li>
</ul>
</nav>
</header>
<section data-anchor="overview" style="background: red; font-size: 25px;">
</section>
<section data-anchor="readiness" style="background: green; font-size: 25px;">
</section>
<section data-anchor="collaboration" style="background: #ccc; font-size: 25px;">
</section>
</div>
Javascript:
<script type="text/javascript">
// Sticky Nav
$('#cloud_nav a').on('click', function() {
var scrollAnchor = $(this).attr('data-scroll'),
scrollPoint = $('section[data-anchor="' + scrollAnchor + '"]').offset().top;
$('body,html').animate({
scrollTop: scrollPoint
}, 500);
return false;
})
var navOffset = $('#cloud_nav').offset().top;
$(window).scroll(function(){
var scrollPos = $(window).scrollTop();
if (scrollPos >= navOffset){
$('#cloud_nav').removeClass('absolute');
$('#cloud_nav').addClass('fixed_cloud_nav');
$('section').each(function(i) {
if ($(this).position().top <= scrollPos - 50) {
$('#cloud_nav a.active').removeClass('active');
$('#cloud_nav a').eq(i).addClass('active');
}
});
} else {
$('#cloud_nav').removeClass('fixed_cloud_nav');
$('#cloud_nav').addClass('absolute');
$('#cloud_nav a.active').removeClass('active');
$('#cloud_nav a:first').addClass('active');
}
});
</script>
The Fiddle:
http://jsfiddle.net/qfaeqo2w/
Thanks in advance, regards.
Is this what you were after?
http://jsfiddle.net/0ytvjtme/
First, I changed calculating the scrollPoint to take into account the size of the header:
scrollPoint = $('section[data-anchor="' + scrollAnchor + '"]').offset().top - $('#cloud_nav').outerHeight();
Then, rather than subtract 50 pixels, we add the height of the nav where it's detecting the scroll position:
if ($(this).position().top <= scrollPos + $('#cloud_nav').outerHeight())
The anchors now scroll to the right place and the active classes look to be switched correctly.