Jumping header on scroll using jQuery Waypoints - javascript

I have fixed bootstrap menu on the top of the page and an asbolutely positioned scroll button .btn-navigate at the bottom of the viewport (in #home-slide).
On (any) scroll, I want the fixed menu to change background from transparent to semigray and also the scroll button to disappear. The button should keep on being hidden from now on, but when I scroll to the top, I need the menu to become transparent again.
For this purpose I am using jQuery Waypoints. I have achieved both effects using the following code, but when I scroll, the menu jumps, EDIT: More specificaly it flashes as if the menu is not at fixed position all the time. When I scroll, it sometimes look as if the menu scroll out with the page and then suddenly jumps back in the fixed position. Sometimes after a while is starts to work correctly. It s not jumping if I remove the following two lines of code, but I need the same trigger for both events.
EDIT2: It is also not flashing if I don't use waypoints with the menu. The scrolling is smooth and the menu is always atop of all other elements in the page.
$("#home-slide .btn-navigate").removeClass("pulse animated");
$("#home-slide .btn-navigate").addClass("fadeOutUp animated2");
HTML:
<header id="masthead">
<nav class="navbar navbar-fixed-top">
<div class="container">
MENU CONTENT
</div>
</nav>
</header>
<section id="home-slide">
<div class="container">
<h1 class="heading">HEADING</h1>
<p class="font2">
TEXT</p>
Scroll Button
</div>
</section>
jQuery:
jQuery(document).ready(function ($) {
$(function () {
$("#masthead nav").waypoint(function () {
$("#masthead nav").toggleClass('scrolling');
$("#home-slide .btn-navigate").removeClass("pulse animated");
$("#home-slide .btn-navigate").addClass("fadeOutUp animated2");
}, { offset: '-20px' });
});
});
MY Navigation CSS:
#masthead {
nav {
min-height: 120px;
padding-top: 2.727rem;
background: rgba(51,58,64,0.0);
-webkit-transition: background-color 0.5s linear;
.container {
position: relative;
}
.navbar-nav {
a {
color: #lms-white;
font-weight: bold;
text-transform: none;
text-shadow: 1px 1px 2px rgba(50, 50, 50, 1);
padding: 7px 1.17rem;
border: 2px solid transparent;
.border-radius(5px);
&:hover {
background: transparent;
border: 2px solid #lms-pink;
}
}
}
.navbar-brand {
padding: 7px 15px;
}
&.scrolling {
background: rgba(51,58,64,0.9);
-webkit-transition: background-color 0.5s linear;
}
}
Bootstrap Navigation CSS:
.navbar-fixed-top {
top: 0;
border-width: 0 0 1px;
}
.navbar-fixed-top, .navbar-fixed-bottom {
position: fixed;
right: 0;
left: 0;
z-index: 1030;
}
.navbar {
position: relative;
min-height: 50px;
margin-bottom: 20px;
border: 1px solid transparent;
}
Any idea how to solve this? Thank you!

I have found the solution. The blinking was not cause by Waypoints. Adding
-webkit-backface-visibility: hidden; /* Chrome, Safari, Opera */
backface-visibility: hidden;
to nav solved the problem.

As described in the debugging guide, using a fixed-position element as a waypoint can lead to a bad time. A waypoint's element's position in the document (client offsetX/Y) determines where it triggers and fixed position elements' offsets are constantly changing as you scroll.
It looks like you already have a perfectly good statically positioned element you can use instead of that nav, the #masthead itself. You may also want to make some changes to your code to look at the direction the user is scrolling when the waypoint is crossed. I believe you want to undo some of these animated states if the user scrolls back up.
$("#masthead").waypoint(function (direction) {
$("#masthead nav").toggleClass('scrolling');
if (direction === 'down') {
$("#home-slide .btn-navigate").removeClass("pulse animated");
$("#home-slide .btn-navigate").addClass("fadeOutUp animated2");
}
else {
$("#home-slide .btn-navigate").addClass("pulse animated");
$("#home-slide .btn-navigate").removeClass("fadeOutUp animated2");
}
}, { offset: -20 });
This can be reduced a little bit using the toggleClass variation that takes a boolean as the second argument, where if that boolean is true the toggle will add the classes, and if it is false the classes are removed.
$("#masthead").waypoint(function (direction) {
$("#masthead nav").toggleClass('scrolling', direction === 'down');
$("#home-slide .btn-navigate")
.toggleClass("pulse animated", direction === 'up')
.toggleClass("fadeOutUp animated2", direction === 'down');
}
}, { offset: -20 });

Related

How do I hide a scrollbar after scrolling and make it visible again on scroll?

My intention is to hide my scrollbar (i.e, hidden by SLIDING TO THE RIGHT), after scrolling (let's say, like 2 or 3 seconds after I'm done scrolling)
And to make it visible again, soon as I start scrolling (i.e, visible by SLIDING IN FROM THE RIGHT)
VIEW CODE SNIPPET:
div::-webkit-scrollbar {
width: 8px;
/* helps remove scrollbar which resizes or shifts list items */
/* display: none; */
}
div::-webkit-scrollbar-track {
background-color: #444444;
}
div::-webkit-scrollbar-button:vertical:increment {
background-color: rgba(108, 92, 231, 0.65);
}
div::-webkit-scrollbar-button:vertical:decrement {
background-color: rgba(108, 92, 231, 0.65);
}
div::-webkit-scrollbar-thumb {
background-color: rgba(108, 92, 231, 0.7);
border-radius: 10px;
}
div::-webkit-scrollbar-thumb:hover {
background-color: rgba(108, 92, 231, 1);
}
div {
width: 500px;
height: 300px;
background-color: #ececec;
overflow: auto;
}
<div>
<p style="height: 300vh;">Just some tall paragraph to force DIV scrollbars....</p>
</div>
Please help me everyone (I'D BE SO GRATEFUL!)
:D
Since CSS does not have timeouts and clearing of timeouts - Use JavaScript
Use Element.classList to add and remove a class
Use setTimeout() set at 2500ms, but every time a scroll event is triggered remove the previous pending timeout using clearTimeout. Logically, after you finished scrolling the last timeout that was set will, after 2.5s trigger finally the class removal.
Use a CSS class like .is-scrolling to there define the desired scrollbar styles (which otherwise are transparent by default)
const showScrollbars = (evt) => {
const el = evt.currentTarget;
clearTimeout(el._scrolling); // Cancel pending class removal
el.classList.add("is-scrolling"); // Add class
el._scrolling = setTimeout(() => { // remove the scrolling class after 2500ms
el.classList.remove("is-scrolling");
}, 2500);
};
document.querySelectorAll("[data-scrollbars]").forEach(el => {
el.addEventListener("scroll", showScrollbars);
});
[data-scrollbars] {
width: 500px;
height: 180px;
background-color: #ececec;
overflow: auto;
}
[data-scrollbars]::-webkit-scrollbar {
width: 8px;
height: 8px;
}
[data-scrollbars]::-webkit-scrollbar-track {
background-color: transparent;
}
[data-scrollbars]::-webkit-scrollbar-thumb {
background-color: transparent;
border-radius: 10px;
}
[data-scrollbars].is-scrolling::-webkit-scrollbar-track {
background-color: #777;
}
[data-scrollbars].is-scrolling::-webkit-scrollbar-thumb {
background-color: gold;
}
<div data-scrollbars>
<p style="height: 300vh;">
Just some tall paragraph to force DIV scrollbars...<br>
Scroll me! (<<< PS: See the problem?!)
</p>
</div>
I would highly not advise you hide scrollbars. Scrollbars are a visual hint to the user that there's actually content to be scrolled. Do a simple A/B testing. For half of your visitors show the scrollbar. For the other half, do that funky stuff - and don't be surprised that your click trough-rate for the below-the-fold portion of the app (or element) has fewer-to-none interactions by that second group of users.
I am thinking about what if user do not have any mouse wheel for scrolling and if user scroll with the actually using scroll bar.
Anyway please search for slim fading scroll bar example at google. You will find some examples for the slim scroll maybe it’s not invisible but it’s transparent and have a good shape.

How do I prevent scroll back up with JavaScript or jQuery?

I have a webpage where there is a full height intro image. Underneath this image is the main body of the site with a regular site header at the top, I'm trying to create an effect where once the user scrolls down to the site header, they cannot scroll back up to view the intro image.
CSS Classes:
Main Intro Image: .cq-fullscreen-intro
Site Header: .nav-down
I had a poke around on StackOverflow but I can't find anything that addresses this circumstance, can anyone point me in the right direction to achieve this using jQuery?
you can use JQuery scrollTop function like this
$(function() {
$(window).scroll(function() {
var scroll = $(window).scrollTop();
// set the height in pixels
if (scroll >= 200) {
// after the scroll is greater than height then you can remove it or hide it
$(".intro-image").hide();
}
});
});
So instead of scrolling, I personally think it would be better to have it be actionable. Forcing the user to manually do the transition (and all in between states) is a bad idea. If the user scrolls half way, and see's something actionable (menu, button, input field) is it usable? If it is, what happens if they submit... very awkward. If it isn't usable, how do they know when it is? How do they know it's because they haven't scrolled all the way. It's very poor user experience.
In the following example, I've created a pseudo-screenport for you to see what's actually going on. The .body container in your real site would be the body element.
Code Pen Example
$(document).ready(function(){
$('.splash-screen').on('click', function(){
$('.splash-screen').addClass("is-hidden");
});
})
html, body{
background: #eee;
margin: 0;
padding: 0;
}
.flex-root {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
width: 100vw;
}
.web-container {
width: 640px;
height: 480px;
background: #fff;
}
.body {
font-size: 0; // this is only to prevent spacing between img placholders
position: relative;
}
.splash-screen{
position: absolute;
transition: transform 1s ease-in-out;
}
.splash-screen .fa {
position: absolute;
z-index: 1;
font-size: 24px;
color: #fff;
left: 50%;
bottom: 15px;
}
.splash-screen.is-hidden {
transform: translateY(-110%);
transition: transform 1s ease-in-out;
}
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="flex-root">
<div class="web-container">
<div class="body">
<div class="splash-screen">
<img src="https://via.placeholder.com/640x480?text=Splash+Screen"/>
<i class="fa fa-chevron-circle-up"></i>
</div>
<img src="https://via.placeholder.com/640x60/cbcbcb?text=Menu"/>
<img src="https://via.placeholder.com/640x420/dddddd?text=Site Body"/>
<div>
</div>
</div>
While its not direclty preventing you from scrolling up and its not jQuery, I would suggest to remove/hide the element once its out of view.
You could get the current scroll position, relative to the top of the page, and check if its greater than the elements height:
const target = document.getElementById('my-target')
const targetHeight = target.getBoundingClientRect().height
const scrollEventListener = () => {
if (
document.body.scrollTop > targetHeight ||
document.documentElement.scrollTop > targetHeight
) {
target.remove()
window.removeEventListener('scroll', scrollEventListener)
document.documentElement.scrollTop = 0
}
}
window.addEventListener('scroll', scrollEventListener)
Here is a codepen https://codepen.io/bluebrown/full/aboagov

Scrolling Nav Sticks to Top

My problem is along the lines of these previous issues on StackOverflow but with a slight difference.
Previous issues:
Stopping fixed position scrolling at a certain point?
Sticky subnav when scrolling past, breaks on resize
I have a sub nav that starts at a certain position in the page. When the page is scrolled the sub nav needs to stop 127px from the top. Most of the solutions I have found need you to specify the 'y' position of the sub nav first. The problem with this is that my sub nav will be starting from different positions on different pages.
This is the JS code i'm currently using. This works fine for one page but not all. Plus on mobile the values would be different again.
var num = 660; //number of pixels before modifying styles
$(window).bind('scroll', function () {
if ($(window).scrollTop() > num) {
$('.menu').addClass('fixed');
} else {
$('.menu').removeClass('fixed');
}
});
I'm looking for a solution that stops the sub nav 127px from the top no matter where on the page it started from.
You can use position: sticky and set the top of the sub-nav to 127px.
See example below:
body {
margin: 0;
}
.main-nav {
width: 100%;
height: 100px;
background-color: lime;
position: sticky;
top: 0;
}
.sub-nav {
position: sticky;
width: 100%;
height: 50px;
background-color: red;
top: 100px;
}
.contents {
width: 100%;
height: 100vh;
background-color: black;
color: white;
}
.contents p {
margin: 0;
}
<nav class="main-nav">Main-nav</nav>
<div class="contents">
<p>Contents</p>
</div>
<nav class="sub-nav">Sub-nav</nav>
<div class="contents">
<p>More contents</p>
</div>
Please see browser support for sticky here
You should change your code to the below, should work fine:
$(window).bind('scroll', function () {
if ($(window).scrollTop() > $(".menu").offset().top) {
$('.menu').addClass('fixed');
} else {
$('.menu').removeClass('fixed');
}
});
Maybe you can try this:
Find navigation div (.menu)
Find the top value of the .menu (vanilla JS would be menuVar.getBoundingClientRect().top, not sure how jQuery does this).
Get top value of browserscreen.
Calculate the difference - 127px.
When the user scrolls and reaches the top value of the menu -127px -> addClass('fixed').

In-page anchors not working properly in combination with "scroll-then-fix" JS navbar code

I use this nice little JavaScript to make my navigation bar (which is normally sitting 230px down from the top) stick to the top of the page once the page is scrolled down that 230 px. It then gives the "nav" element a "fixed" position.
$(document).ready(function() {
$(window).bind('scroll', function() {
if ($(window).scrollTop() > 230) {
$('nav').addClass('fixed');
} else {
$('nav').removeClass('fixed');
}
});
});
nav {
width: 90%;
display: flex;
justify-content: center;
max-width: 1400px;
height: 85px;
background-color: rgba(249, 241, 228, 1);
margin: auto;
border-top-left-radius: 0em;
border-top-right-radius: 0em;
border-bottom-left-radius: 2em;
border-bottom-right-radius: 2em;
}
.fixed {
position: fixed;
border-top: 0;
top: 0;
margin: auto;
left: 0;
right: 0;
z-index: 4;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav>
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
</ul>
</nav>
Now, the problem: i have positioned the corresponding anchor targets
within the page and have given them some "padding-top" to account for the fixed navbar (about 90px), so that they don't disappear behind the bar when the page jumps to them after clicking.
.anchor {
padding-top: 90px;
}
<a class="anchor" id="three">
This works fine AS LONG AS the navbar is already fixed to the top.
But if you click on a link while the navbar is still in its original mid-page position (e.g. the first click the user will do), it just disregards the offset i gave the anchor target and jumps to a weird position where the anchor target is hidden behind the navbar (and not even aligned with the top of the page)!
If i THEN click on the link again (now in the fixed bar on top of the page), it corrects itself and displays the page as i want to. But that first click always misses - i can't figure out why! Please help
EDIT: WORKING DEMO here: http://www.myway.de/husow/problem/problem.html
1st Add a new class name spacebody to your first div with class="space"
<nav>
...
</nav>
<div class="space spacebody">
</div>
2nd JS use the following should fix your problem:
$(document).ready(function() {
$(window).bind('scroll', function() {
if ($(window).scrollTop() > 230) {
$('nav').addClass('fixed');
$('.spacebody').css('margin-top', '85px');
} else {
$('nav').removeClass('fixed');
$('.spacebody').css('margin-top', '0px');
}
});
});
Reason Why?
because when your nav is not fixed, it has a height of 85px, when you scroll down it has no height which is 0 height. Then everything below move up by 85px causing your to go below the target of ONE or TWO etc. It is not you are missing the first click, it is when the nav are not fixed and the click you will be scroll more down by 85px. If you scroll to top and click you will miss again.
You can easily see this if you change your CSS for nav with background-color: transparent;
With the code above should fix it when you nav become fixed to add a margin-top as 85px to the div below so they keep the same height as you clicked.

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

Categories