I'm attempting to make a form sticky sidebar on my Squarespace website. This is the JQuery I'm using to achieve the sticky sidebar. I'm trying to create a fade in effect when the form attaches to the scrolling and fade out effect right before the form touches the footer (and vice versa for scrolling up).
Here is my JQuery script:
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
jQuery("document").ready(function($){
var nav = $('form');
var footerTop = $('footer').offset().top;
var navHeight = $('#form').outerHeight();
var stopPoint = footerTop - navHeight - 70;
$(window).scroll(function () {
if ($(this).scrollTop() >= 450) {
nav.addClass("form-fixed");
} else {
nav.removeClass("form-fixed");
}
if ($(this).scrollTop() >= 2740) {
nav.addClass("form-stop");
} else {
nav.removeClass("form-stop");
}
});
});
</script>
Here is my CSS:
/*Home V2*/
.form
{posiiton: relative;}
.form-fixed
{position: fixed;
background-color: #F5FFFB;
top: 80px;
right: 7%;
z-index: 9999;
width: 20%;}
.form-stop
{position: absolute;
bottom: 0;
top: auto;
left: 0;}
I've been trying to attach .fadeIn() or .fadeOut() at the ends of the add/remove class commands. It works, but it's either only complicit during one command or fading in and out repeatedly. Any help?
Related
I have a main nav bar which I am turning into a full width sticky on scroll. Now I am trying to incorporate a fade in/out for the full width white banner which appears on scroll (behind the nav).
Getting an undefined error when scrolling, and the fadeIn/Out is not working.
Here is my code.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<!-- STICKY HEADER -->
<script>
window.onscroll = function() {fadeFunction()};
var header = document.getElementById("head");
var sticky = header.offsetTop;
function fadeFunction() {
if (window.pageYOffset > sticky) {
header.classList.add("sticky").fadeIn();
} else {
header.classList.remove("sticky").fadeOut();
}
}
</script>
<style>
#head {
z-index: 10;
margin-right: auto;
margin-left: auto;
padding-left: 20%;
padding-right: 20%;
width: 100%;
}
.sticky {
position: fixed;
top: 0;
width: 100%;
background-color: #fff;
}
.sticky + .content {
padding-top: 102px;
}
</style>
Console error:
Cannot read property 'fadeIn' of undefined.
I suspect my jQuery is probably not correct?
UPDATED CODE - Except that it only runs after page load, but not every time page is scrolled:
$(document).ready(function() {
var header = document.getElementById("head");
var sticky = header.offsetTop;
function addSticky() {
header.classList.add("sticky");
$('.sticky').addClass('fadeInDown');
$('.sticky').removeClass('fadeInUp');
$('.sticky').addClass('animated');
$('.subnav-sticky').addClass('fadeInDown');
$('.subnav-sticky').removeClass('fadeOutUp');
$('.subnav-sticky').addClass('animated');
}
function removeSticky() {
header.classList.remove("sticky");
$('.subnav-sticky').addClass('fadeOutUp');
$('.subnav-sticky').removeClass('fadeInUp');
}
$(window).scroll(function() {
var scrollTop = $(window).scrollTop();
if (scrollTop > sticky) {
addSticky();
}
else {
removeSticky();
}
});
});
You are mixing javascript methods with jQuery ones, fadeIn/fadeOut are jQuery functions but you're not triggering those methods on a jQuery object.
In your case header should be wrapped with the dollar function:
var $header = $('#head')
And then you can use it like this:
$header.addClass('sticky').fadeIn()
I'll say that you may not even need jQuery and you could do these animations using the same sticky class.
Thank you to those who helped. I updated my script and created a new css class. Thew new css class is to handle the transition for the sticky nav.
Here is my solution.
$(window).scroll(function(){
var header = document.getElementById("head");
var sticky = header.offsetTop;
var scrollTop = $(window).scrollTop();
if (scrollTop > 0) {
header.classList.add("sticky");
header.classList.add("transitions");
$('.subnav-sticky').addClass('fadeInDown');
$('.subnav-sticky').removeClass('fadeOutUp');
$('.subnav-sticky').addClass('animated');
}
else {
header.classList.add("transitions");
header.classList.remove("sticky");
$('.subnav-sticky').addClass('fadeOutUp');
$('.subnav-sticky').removeClass('fadeInUp');
$('.subnav-sticky').addClass('animated');
}
});
And the new css class
.transitions {
transition: all 0.9s
}
I'm currently using bootstrap's navbar with built-in scrollspy function in an one page layout. (like in this example: http://blackrockdigital.github.io/startbootstrap-scrolling-nav/)
I want to place the navbar at the bottom in the #intro section and to become fixed at the top when scrolling down.
Question:
How to prevent the navbar from jumping up and down (both when scrolling and when clicking a navigation element)?
//////////////////////////////////////////////////////
Solution:
I solved the problem by adding some CSS to the demo mentioned above:
.navbar {
position: absolute;
bottom: 0;
width: 100%;
height: 50px;
margin: 0;
}
.navbar-fixed-top {
position: fixed;
right: 0;
left: 0;
top: 0;
z-index: 1030;
}
and changed the jQuery code to:
$(document).ready(function(){
$(window).bind('scroll', function() {
var navHeight = $( window ).height() - 50;
if ($(window).scrollTop() > navHeight) {
$('.navbar').addClass('navbar-fixed-top');
}
else {
$('.navbar').removeClass('navbar-fixed-top');
}
});
});
For demo look JSFiddle: https://jsfiddle.net/90jbhe54/
Now it works nice and fluently.
I want mynavbar to be transparent when the page is scrolled to the top, however when the user scrolls I would like it to be made opaque. I tried this with javascript, but something still isn't working.
http://jsfiddle.net/6A6qy/
function myFunction() {
if ($(window).scrollTop() < 50) {
document.getElementById("masthead").style.opacity = "0.5";
}
}
#masthead {
position: fixed;
top: 0;
left: 0;
z-index: 9999;
width: 100%;
height: 50px;
background-color: #00a087;
opacity: 1;
}
#container {
background-color: blue;
height: 1000px;
display: block;
margin-top: -50px;
}
<body onload="myFunction()">
<nav id="masthead">
<!-- Fixed navigation bar content -->
</nav>
<div id="container"></div>
</body>
How about this:
JS:
// listen for scroll
$(window).scroll( function() {
// apply css classes based on the situation
if ($(".masthead").offset().top > 100) {
$(".masthead").addClass("navbar-scrolled");
} else {
$(".masthead").removeClass("navbar-scrolled");
}
}
CSS:
.navbar-scrolled {
/* some css for navbar when scrolled */
}
JSFiddle example:
http://jsfiddle.net/8ruwnaam/
And then of course you could add some optimization to not apply the classes all the time if they are already there. But it works quite fine without such things as well.
Additional things:
The first version of this answer and your question use IDs for styling, which is not really a good idea according to a lot of people. Styling IDs goes against the DRY principles, and causes all these funny little problems when you forget to think about CSS specificity. IDs are quite alright for a lot of things when it comes to the logic in the JS or something, but try to use classes for styling.
You should create an .opaque css class and attach it based on actively scrolling or if scrollTop is < 50:
.opaque {
opacity: 0.5;
}
Then attach that class on('scroll') or at scrollTop (this is using the debounce plugin):
function myFunction() {
var $masthead = $('#masthead')
, $window = $(window);
// currently scrolling
$window.scroll($.debounce( 250, true, function(){
$masthead.addClass('opaque');
}));
// done scrolling
$window.scroll($.debounce( 250, function(){
// if at the top, add or keep opaque class
if($(this).scrollTop() < 50) {
if(!$masthead.hasClass('opaque')) {
$masthead.addClass('opaque');
}
} else {
$masthead.removeClass('opaque');
}
}));
}
You need to set it to be transparent by default (as it will be on the top) like that
#masthead {
position: fixed;
top: 0;
left: 0;
z-index: 9999;
width: 100%;
height: 50px;
background-color: #00a087;
opacity: 0.5; /*edited the opacity to be 50% by default*/
}
then use this script to achieve your needs:
$(document).ready(function () {
$(window).scroll(function(){
var ScrollTop = parseInt($(window).scrollTop());
if (ScrollTop < 100) {
document.getElementById("masthead").style.opacity = "0.5";
} else {
document.getElementById("masthead").style.opacity = "1";
}
});
});
I am using following code to make a menu sticky when the window is scrolled down. It works fine if the window height is enough to scroll down the full header area, but it it creates problem is the height is just close enough to scroll, in that case it starts flashing and does not let scroll.
Here is the demo of the problem, refresh couple of times and try to scroll down. I have set the body height to 622px to reproduce the problem:
http://jsbin.com/ipEROYO/1
Here's the code I'm trying:
$(document).ready(function() {
var stickyNavTop = $('.nav').offset().top;
var stickyNav = function(){
var scrollTop = $(window).scrollTop();
if (scrollTop > stickyNavTop) {
$('.nav').addClass('sticky');
} else {
$('.nav').removeClass('sticky');
}
};
stickyNav();
$(window).scroll(function() {
stickyNav();
});
});
CSS:
.sticky {
position: fixed;
width: 100%;
left: 0;
top: 0;
z-index: 100;
border-top: 0;
}
It's because when you are setting the navigation div to position:fixed you are shortening the length of the document (by the height of that div), which then causes the scroll bar to go away, which causes the scrollTop() value to be 0 which causes the .nav div to be position:static and it is an endless cycle if you keep scrolling down.
Here's my quick solution:
$(document).ready(function() {
var height = $('.nav').outerHeight();
$(window).scroll(function() {
if($(this).scrollTop() > height)
{
$('.nav').css('position','fixed');
$('body').css('padding-bottom',height+'px');
}
else if($(this).scrollTop() <= height)
{
$('.nav').css('position','static');
$('body').css('padding-bottom','0');
}
});
$(window).scroll();
});
Just modified the JSbin. Check it out. You were really close, just doing more than you needed to like setting the sticky class on load of the page rather than when the function first runs. Let me know if this helps.
try that
$(window).scroll(function () {
var scroll_top = $(this).scrollTop();
if (scroll_top > 66) {//height of header
$('.nav').addClass('sticky');
} else {
$('.nav').removeClass('sticky');
}
});
Strongly recommend a CSS only solution for this layout. No one seems to know what to call this method, so I've been referring to it as the absolute stretch technique, but in my experience it works beautifully across mobile devices and PC's including all major browsers except IE6 and below. There is some discussion of it here.
body, .header, .nav, .mainContent{
position: absolute;
top: 0;
left: 0;
right: 0;
}
body, .mainContent {
bottom: 0;
}
.header{
height: 120px;
}
.nav{
height: 70px;
top: 120px;
}
.mainContent{
top: 190px;
overflow: auto;
}
You'll find you can get very robust, concise, well organized layouts in this manner, and fixed headers, footers and sidebars follow very easily.
I have a specific problem on making a sticky header with jQuery. I tried the commonly used snippets around the web, but I perceived the same buggy thing everywhere.
At a specific document height (scrollable until a little more than calling of sticky-effect) the sticky header jumps between position: fixed and position: static.
HTML:
<header>
<div id="not-sticky"></div>
<div id="sticky"></div>
</header>
<div id="content"> ...
jQuery:
var $sticky = $("#sticky");
var offset = $sticky.offset();
var stickyTop = offset.top;
var windowTop = $(window).scrollTop();
$(window).scroll(function() {
windowTop = $(window).scrollTop();
if (windowTop > stickyTop) {
$sticky.css({
position: 'fixed',
top: 0
});
}
else {
$sticky.css({
position: '',
top: ''
});
}
});
CSS:
header {
width: 100%;
}
#not-sticky {
padding: 50px 0;
width: 100%;
}
#sticky {
padding: 24px 0;
position: relative;
width: 100%;
z-index: 25;
}
I also tried a margin-bottom on #not-sticky with the same height as the #sticky to keep a constant document-height, but the same jumpy-sticky-effect occurred.
Any idea to fix that thing?
Scroll fires too many times and trying to set an element style will always & inevitably create jumps (even barely noticeable but still jaggy).
The best way I've found is to
clone our element,
make that clone fixed
play with clone's visibility style.
Pure JS:
;(function(){ /* STICKY */
var sticky = document.getElementById("sticky"),
sticky2 = sticky.cloneNode(true);
sticky2.style.position = "fixed";
document.body.appendChild(sticky2);
function stickIt(){
sticky2.style.visibility = sticky.getBoundingClientRect().top<0 ? "visible" : "hidden";
}
stickIt();
window.addEventListener("scroll", stickIt, false );
}());
#sticky{
height:100px;
background:#ada;
height:50px;
position:relative;
/* needed for clone: */
top:0;
width:100%;
}
/* Just for this demo: */
*{margin:0;padding:0;}
#content{height:2000px; border:3px dashed #444;}
h1{padding:40px; background:#888;}
<h1>Logo</h1>
<div id="sticky">Sticky header</div>
<div id="content">Lorem ipsum...<br>bla bla</div>
So when you see the "header" fix, that's actually our fixed clone getting visible on-top.