Fixed div on scroll - javascript

I'm trying to create a div which will get a class only on scrolling and when the value of scroll is 210. I have next code :
$(document).ready(function() {
var pageWidth = $(window).width();
if(pageWidth > 700){
var contentLeft = $('#content-left');
var height = 210;
$(window).scroll(function () {
if ($(window).scrollTop() < height) {
contentLeft.attr('class', 'content-left');
} else {
contentLeft.attr('class', 'content-left leftContentFixed');
}
});
}
});
I try to apply this only on desktops.
Thus, I do not need the class leftContentFixed if it's on a smartphone or tablet.
If I try something like :
$(document).ready(function() {
var pageWidth = $(window).width();
if(pageWidth > 700){
alert("Bigger than 700");
}else{
alert("Smaller than 700");
}
});
Than it works perfect, but with my code it isn't working. The class leftContentFixed is added although the screen is smaller than 700.
Any advice?

You need to check screen size on resize event and check for its value when user scrolls the page. You could create mobile variable and make it true/false depends on screen size, then in scroll callback check for its value and choose correct class.
$(document).ready(function() {
var pageWidth = $(window).width(),
height = 210,
contentLeft = $('.content-left'),
mobile = false;
$(window).on('load resize', function() {
pageWidth = $(this).width();
// Save mobile status
if (pageWidth > 700) {
mobile = false;
} else {
mobile = true
}
})
$(window).on('scroll', function() {
if ($(window).scrollTop() > height) {
// Set default class
var _class = 'content-left leftContentFixed';
// If mobile then modify class
if (mobile) {
_class = 'content-left';
}
contentLeft.attr('class', _class);
} else {
var _class = 'content-left';
contentLeft.attr('class', _class);
}
});
});
html {
height: 2000px
}
.content-left {
background: gold;
width: 50px;
height: 100px;
}
.content-left.leftContentFixed {
position: fixed;
top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="content-left"></div>

Related

Refresh skrollr-stylesheets using id

Im using Skrollr for my website. It has to change from a horizontal scroll, for larger screens, to a vertical scroll, for phones. But the s.refresh didn't refresh the data-* values. I tried two codes, both of which changes the id, but skrollr didn't update accordingly.
Code 1:
<style>
#MainX {
-skrollr-animation-name: ScrollsX;
}
#-skrollr-keyframes ScrollsX {
0 {transform: translateX(0%);}
4000 {transform: translateX(-400%);}
}
#MainY {
-skrollr-animation-name: ScrollsY;
}
#-skrollr-keyframes ScrollsY {
0 {transform: translateY(0%);}
4000 {transform: translateY(-400%);}
}
#media (max-width: 991px) {
.container {
display: flex;
flex-direction: column;
height: auto;
}
.navbar {
position: relative;
}
}
</style>
<div id="MainX" class="container">
... Whole Code ...
</div>
<script>
var Func = function(){
if (window.innerWidth < 991) {
var Size = document.getElementById("MainX");
Size.id = "MainY";
skrollr.init();
skrollr.destroy();
skrollr.init();
}
if(window.innerWidth >= 991) {
var Size = document.getElementById("MainY");
Size.id = "MainX";
skrollr.init();
skrollr.destroy();
skrollr.init();
}
};
window.addEventListener("resize", Func);
window.addEventListener("onload", Func);
</script>
Code 2 (Style block code is unchanged):
<script>
window.onload = function(){
if (window.innerWidth < 991) {
var Size = document.getElementById("Gg");
Size.id = "MainY";
}
if(window.innerWidth >= 991) {
var Size = document.getElementById("Gg");
Size.id = "MainX";
}
};
var Func = function(){
if (window.innerWidth < 991) {
var Size = document.getElementById("MainX");
Size.id = "MainY";
}
if(window.innerWidth >= 991) {
var Size = document.getElementById("MainY");
Size.id = "MainX";
}
};
window.addEventListener("resize", Func);
</script>
<div id="Gg" class="container">
... Whole Code ...
</div>
<script type="text/javascript" src="js/ScrollX.js"></script>
<script type="text/javascript" src="js/ScrollAll.js"></script>
<script type="text/javascript">
var s = skrollr.init();
</script>
ScrollX.js is skrollr.min.js whilst ScrollAll.js is skrollr.stylesheets.min.js
For code 1, if the screen width initially is > 991, the id is MainX, and the data-0, and data-4000 are transform:translateX(*%);, while if I resize it to < 991, the id changes to MainY, but the corresponding data-0 and data-4000 are not updated to transform:translateY(*%);. if the width is initially < 991, the id is still MainX, and changes id only when resized, with no changes to the data-* variables. Moreover, this also adds a "no-skrollr" class in the head automatically, might be the reason why the skrollr doesn't works.
For code 2, the initial detection, and resize detection of screen width works fine, but does not even create the class skrollable skrollable-between nor the data-*.
What am I doing wrongly? Any help will be greatly help me. (p.s. this is for my e-portfolio website, wanted to make it a lil fun.)

Code not working correctly in Safari and responsive browsers

I have the following code which 'shows/hides' my navigation up off the top of the screen, and brings it down again.
jQuery(document).ready(function($){
var didScroll;
var lastScrollTop = 0;
var delta = 5;
var navbarHeight = $('nav').outerHeight(true);
$(window).scroll(function(event) { didScroll = true; });
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 0);
function hasScrolled() {
if($( window ).width() > 768) {
var st = $(this).scrollTop();
if (Math.abs(lastScrollTop - st) <= delta)
return;
if (st > lastScrollTop) {
// Scroll Down
$('#screen-nav').removeClass('nav-down').addClass('nav-up');
} else {
$('#screen-nav').removeClass('nav-up').addClass('nav-down');
}
}
lastScrollTop = st;
}
});
css
#screen-nav {
position: fixed;
top: 0; left: 0; right: 0;
}
#screen-nav.nav-up { top: -100px; }
#screen-nav.nav-down { top: 0; }
The problem is that on the safari browser and when the screen changes from mobile size (<768px on all browsers) to screen size sometimes the .nav-up class gets added and the navigation doesn't show. But only when the user scrolls to the top of the page.
Not sure if there is a better way to write the code to ensure proper functionality.
I see you are using this example. He has the fiddle working well too. the only thing is that on browser resize nothing regarding show the nav is in place. You should be able to just add that separately.
$(window).resize(function(){
$('#screen-nav').removeClass('nav-up').addClass('nav-down')
});
I updated his original fiddle to reflect the addition of window resize handling.

Fade in on Scroll Plain JavaScript No JQuery

I'm trying to implement a text fade in on scroll similar to this https://codepen.io/hollart13/post/fade-in-on-scroll.
$(function(){ // $(document).ready shorthand
$('.monster').fadeIn('slow');
});
$(document).ready(function() {
/* Every time the window is scrolled ... */
$(window).scroll( function(){
/* Check the location of each desired element */
$('.hideme').each( function(i){
var bottom_of_object = $(this).position().top + $(this).outerHeight();
var bottom_of_window = $(window).scrollTop() + $(window).height();
/* If the object is completely visible in the window, fade it it */
if( bottom_of_window > bottom_of_object ){
$(this).animate({'opacity':'1'},1500);
}
});
});
});
However, I do not want to use JQuery. I want to accomplish this using plain JavaScript. Unfortunately, most of the examples online are JQuery based and there's very little with plain JavaScript.
This is what I've attempted so far to "translate" this JQuery into plain JS. It's not working. Could anyone point at where I went wrong?
window.onscroll = function() {myFunction()};
function myFunction() {
var elements = document.getElementsByClassName("target");
for(var i = 0; i < elements.length; i++){
var bottomOfObject = elements[i].getBoundingClientRect().top +
window.outerHeight;
var scrollTop = (window.pageYOffset !== undefined) ? window.pageYOffset :
(document.documentElement || document.body.parentNode ||
document.body).scrollTop;
var bottomOfWindow = scrollTop + window.innerHeight;
if(bottomOfWindow > bottomOfObject){
$(this).animate({'opacity': '1'}, 1500);
}
}
console.log(bottomOfObject);
}
Thanks in advance!
Try this simple vanilla JavaScript solution
var header = document.querySelector("#header");
window.onscroll = function() {
if (document.body.scrollTop > 50) {
header.className = "active";
} else {
header.className = "";
}
};
#header {
background-color: black;
transition: all 1s;
position: fixed;
height: 40px;
opacity: 0;
right: 0;
left: 0;
top: 0;
}
#header.active {
opacity: 1;
}
#wrapper {
height: 150vh;
}
<html>
<body>
<div id="header"></div>
<div id="wrapper"></div>
</body>
</html>
Essentially there is an element positioned on the top of the screen which is invisible at first (with opacity 0) and using javascript I add an class to it that makes it visible (opacity 1) what makes it slowly visible instead of instantly is the transition: all 1s;
Here's my version with dynamic opacity based on scroll position, I hope it helps
Window Vanilla Scroll
function scrollHandler( event ) {
var margin = 100;
var currentTop = document.body.scrollTop;
var header = document.querySelector(".header");
var headerHeight = header.getBoundingClientRect().height;
var pct = (currentTop - margin) / ( margin + headerHeight );
header.style.opacity = pct;
if( pct > 1) return false;
}
function addListeners() {
window.addEventListener('scroll' , scrollHandler );
document.getElementById("click" , function() {
window.scrollTop = 0;
});
}
addListeners();

Mask/overlay over page when menu is opened

I've some trouble with my script, I'm trying to figure out how I can make a mask/filter over the website when the menu is opened. In the HTML is a class called cmask and there is also a class called cmask is-active
It only has to do this when the screen is smaller than 900px. I've been trying to use cmask.addClass("is-active") and removeclass but its not working like that and it keeps crashing(makes the other part of the script not working anymore). Does someone knows what im doing wrong?
//scrolling----------------
//scrolling----------------
//scrolling----------------
var nav = $("#nav_id");
var nav_overflow = $("#nav_overflow");
var page_end_logo_nav = $("#page_end_logo_nav").visible();
var logo_container = $("#logo_container");
var nav_ani_speed = 200 //in ms
var nav_state = 0 // 0 is nav 1 is hamburger visable
var hamburger = $("#hamburgermenu") //hamburger elemnt
var distanceY;
var shrinkOn;
var winkel_mand = $("#winkel_mand")
//set scroll for desktop nav
function nav_desktop_check() {
distanceY = window.pageYOffset || document.documentElement.scrollTop;
shrinkOn = 100;
//run the header script
if (distanceY > shrinkOn) {
if (nav_state === 0) {
nav_hamburger();
}
} else {
if (nav_state === 1 ){
if ($(window).width() >= 900){
nav_normal_desktop();
}
}
}
}
//tablet nav check
function tablet_nav_check() {
if (nav_state === 0){
if ($(window).width() <= 900){
nav_hamburger();
}
}
}
tablet_nav_check()
//hambutton onclikc
hamburger.click(function() {
if (nav_state === 1){
if ($(window).width() >= 900){
nav_normal_desktop();
} else {
nav_normal_mobile();
}
logo_animation();
remove_winkel_icon_check()
} else{
nav_hamburger()
}
});
//nav to hamburger
function nav_hamburger() {
hamburger.removeClass("active")
nav_overflow.animate({
width: 0
}, nav_ani_speed, function() {
hamburger.addClass("active")
});
nav_state = 1;
logo_animation();
}
//hamburger to nav
function nav_normal_desktop() {
hamburger.addClass("active");
hamburger.removeClass("active");
nav_overflow.css("width", "auto");
nav_witdh = nav_overflow.innerWidth();
nav_overflow.css("width", 0);
nav_overflow.animate({
width: nav_witdh
}, nav_ani_speed, function() {
hamburger.removeClass("active")
});
nav_state = 0;
}
function nav_normal_mobile() {
nav_overflow.animate({
width: "100%"
}, nav_ani_speed, function() {
hamburger.removeClass("active")
});
nav_state = 0;
}
First I would add semicolons to all statements where it could fit, just to be sure you are not missing a mandatory one.
I've made a small overlay mask example
Javascript
$('#element').on("click",function() {
if($('#overlay').length == 0) {
$(this).wrap('<div id="overlay"><div>');
} else {
$(this).unwrap();
}
});
CSS
#element {
width:200px;
height:200px;
background-color:#f00;
}
#inner {
width:100px;
height:100px;
background-color:#0ff;
}
#overlay
{
background-color:#000;
opacity:0.3;
width:200px;
height:200px;
}
http://jsfiddle.net/5aw0wsy4/

Add/remove class with jquery based on vertical scroll?

So basically I'd like to remove the class from 'header' after the user scrolls down a little and add another class to change it's look.
Trying to figure out the simplest way of doing this but I can't make it work.
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll <= 500) {
$(".clearheader").removeClass("clearHeader").addClass("darkHeader");
}
}
CSS
.clearHeader{
height: 200px;
background-color: rgba(107,107,107,0.66);
position: fixed;
top:200;
width: 100%;
}
.darkHeader { height: 100px; }
.wrapper {
height:2000px;
}
HTML
<header class="clearHeader"> </header>
<div class="wrapper"> </div>
I'm sure I'm doing something very elementary wrong.
$(window).scroll(function() {
var scroll = $(window).scrollTop();
//>=, not <=
if (scroll >= 500) {
//clearHeader, not clearheader - caps H
$(".clearHeader").addClass("darkHeader");
}
}); //missing );
Fiddle
Also, by removing the clearHeader class, you're removing the position:fixed; from the element as well as the ability of re-selecting it through the $(".clearHeader") selector. I'd suggest not removing that class and adding a new CSS class on top of it for styling purposes.
And if you want to "reset" the class addition when the users scrolls back up:
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 500) {
$(".clearHeader").addClass("darkHeader");
} else {
$(".clearHeader").removeClass("darkHeader");
}
});
Fiddle
edit: Here's version caching the header selector - better performance as it won't query the DOM every time you scroll and you can safely remove/add any class to the header element without losing the reference:
$(function() {
//caches a jQuery object containing the header element
var header = $(".clearHeader");
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll >= 500) {
header.removeClass('clearHeader').addClass("darkHeader");
} else {
header.removeClass("darkHeader").addClass('clearHeader');
}
});
});
Fiddle
Pure javascript
Here's javascript-only example of handling classes during scrolling.
const navbar = document.getElementById('navbar')
// OnScroll event handler
const onScroll = () => {
// Get scroll value
const scroll = document.documentElement.scrollTop
// If scroll value is more than 0 - add class
if (scroll > 0) {
navbar.classList.add("scrolled");
} else {
navbar.classList.remove("scrolled")
}
}
// Use the function
window.addEventListener('scroll', onScroll)
#navbar {
position: fixed;
top: 0;
left: 0;
right: 0;
width: 100%;
height: 60px;
background-color: #89d0f7;
box-shadow: 0px 5px 0px rgba(0, 0, 0, 0);
transition: box-shadow 500ms;
}
#navbar.scrolled {
box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.25);
}
#content {
height: 3000px;
margin-top: 60px;
}
<!-- Optional - lodash library, used for throttlin onScroll handler-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
<header id="navbar"></header>
<div id="content"></div>
Some improvements
You'd probably want to throttle handling scroll events, more so as handler logic gets more complex, in that case throttle from lodash lib comes in handy.
And if you're doing spa, keep in mind that you need to clear event listeners with removeEventListener once they're not needed (eg during onDestroy lifecycle hook of your component, like destroyed() for Vue, or maybe return function of useEffect hook for React).
Example throttling with lodash:
// Throttling onScroll handler at 100ms with lodash
const throttledOnScroll = _.throttle(onScroll, 100, {})
// Use
window.addEventListener('scroll', throttledOnScroll)
Add some transition effect to it if you like:
http://jsbin.com/boreme/17/edit?html,css,js
.clearHeader {
height:50px;
background:lightblue;
position:fixed;
top:0;
left:0;
width:100%;
-webkit-transition: background 2s; /* For Safari 3.1 to 6.0 */
transition: background 2s;
}
.clearHeader.darkHeader {
background:#000;
}
Its my code
jQuery(document).ready(function(e) {
var WindowHeight = jQuery(window).height();
var load_element = 0;
//position of element
var scroll_position = jQuery('.product-bottom').offset().top;
var screen_height = jQuery(window).height();
var activation_offset = 0;
var max_scroll_height = jQuery('body').height() + screen_height;
var scroll_activation_point = scroll_position - (screen_height * activation_offset);
jQuery(window).on('scroll', function(e) {
var y_scroll_pos = window.pageYOffset;
var element_in_view = y_scroll_pos > scroll_activation_point;
var has_reached_bottom_of_page = max_scroll_height <= y_scroll_pos && !element_in_view;
if (element_in_view || has_reached_bottom_of_page) {
jQuery('.product-bottom').addClass("change");
} else {
jQuery('.product-bottom').removeClass("change");
}
});
});
Its working Fine
Is this value intended? if (scroll <= 500) { ... This means it's happening from 0 to 500, and not 500 and greater. In the original post you said "after the user scrolls down a little"
In a similar case, I wanted to avoid always calling addClass or removeClass due to performance issues. I've split the scroll handler function into two individual functions, used according to the current state. I also added a debounce functionality according to this article: https://developers.google.com/web/fundamentals/performance/rendering/debounce-your-input-handlers
var $header = jQuery( ".clearHeader" );
var appScroll = appScrollForward;
var appScrollPosition = 0;
var scheduledAnimationFrame = false;
function appScrollReverse() {
scheduledAnimationFrame = false;
if ( appScrollPosition > 500 )
return;
$header.removeClass( "darkHeader" );
appScroll = appScrollForward;
}
function appScrollForward() {
scheduledAnimationFrame = false;
if ( appScrollPosition < 500 )
return;
$header.addClass( "darkHeader" );
appScroll = appScrollReverse;
}
function appScrollHandler() {
appScrollPosition = window.pageYOffset;
if ( scheduledAnimationFrame )
return;
scheduledAnimationFrame = true;
requestAnimationFrame( appScroll );
}
jQuery( window ).scroll( appScrollHandler );
Maybe someone finds this helpful.
For Android mobile $(window).scroll(function() and $(document).scroll(function() may or may not work. So instead use the following.
jQuery(document.body).scroll(function() {
var scroll = jQuery(document.body).scrollTop();
if (scroll >= 300) {
//alert();
header.addClass("sticky");
} else {
header.removeClass('sticky');
}
});
This code worked for me. Hope it will help you.
This is based of of #shahzad-yousuf's answer, but I only needed to compress a menu when the user scrolled down. I used the reference point of the top container rolling "off screen" to initiate the "squish"
<script type="text/javascript">
$(document).ready(function (e) {
//position of element
var scroll_position = $('div.mainContainer').offset().top;
var scroll_activation_point = scroll_position;
$(window).on('scroll', function (e) {
var y_scroll_pos = window.pageYOffset;
var element_in_view = scroll_activation_point < y_scroll_pos;
if (element_in_view) {
$('body').addClass("toolbar-compressed ");
$('div.toolbar').addClass("toolbar-compressed ");
} else {
$('body').removeClass("toolbar-compressed ");
$('div.toolbar').removeClass("toolbar-compressed ");
}
});
}); </script>

Categories

Resources