The problem has been discussed on the forum a few times however I cannot make it work so I ask for help.
I have a side contact menu (as a widget) in my WP website and made it position: fixed so it doesn't change position during scrolling. However, I want it to stop being fixed before it hits footer div because it just looks weird.
As far as I read I need jquery and a script that changes my fixed position to a relative at some point so I feel like I understand the basic mechanic of it and even found several scripts but all of them doesn't work at all.
I want something exactly like in here:
Stop fixed position at certain div or certain position
I created 3 files: html, css, js and put all the codes from the answer and it just does not work at all..
My js file - java.js
jQuery(document).ready(function() {
var navTop = $('#nav').offset().top;
var navStop = $('#stop').offset().top;
var lastMode = "absolute";
$(window).scroll(function() {
var mode;
if ($(this).scrollTop() >= navTop) {
if ($(this).scrollTop() - navStop + $('#nav').height() > 0)
mode = 'absolute';
else
mode = 'fixed';
} else {
mode = 'absolute';
}
if (lastMode !== mode) {
if (mode == 'fixed') {
$('#nav').css('position', 'fixed');
$('#nav').css('top', '0');
} else {
$('#nav').css('position', 'absolute');
$('#nav').css('top', navTop);
}
lastMode = mode;
}
});
}
My css file- style.css:
#nav {
background: rgba(0, 0, 0, 0.5);
position: absolute;
top: 200px;
width: 100px;
height: 50px;
}
#stop {
width: 100%;
background: blue;
height: 300px;
position: absolute;
top: 900px;
margin-top: 20px;
}
My html doc - index.html
<link rel="stylesheet" type="text/css" href="style.css">
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="javascript" src="java.js"></script>
<body style="height:5000px;">
<div id="nav"></div>
<div id="stop"></div>
</body>
Since the code above is just an answer from another topic - I wanted to change it for my needs but it seems I do something wrong because it does not work.
To detail: I want side contact menu <div class="widget-contact"> to start normally like it is right now (position fixed) and stop it from being fixed when it hits
<div id="colophon-inside" class="footer-three">
I am fine using html/css however I do not understand js and I feel my problem is quite easy to solve.
Could you help?
Your code works. You just missed out a ")" at the end of your javascript file. So completing your JS file it should be:
jQuery(document).ready(function() {
var navTop = $('#nav').offset().top;
var navStop = $('#stop').offset().top;
var lastMode = "absolute";
$(window).scroll(function() {
var mode;
if ($(this).scrollTop() >= navTop) {
if ($(this).scrollTop() - navStop + $('#nav').height() > 0)
mode = 'absolute';
else
mode = 'fixed';
} else {
mode = 'absolute';
}
if (lastMode !== mode) {
if (mode == 'fixed') {
$('#nav').css('position', 'fixed');
$('#nav').css('top', '0');
} else {
$('#nav').css('position', 'absolute');
$('#nav').css('top', navTop);
}
lastMode = mode;
}
});
})
Here I say this is "Solved"
https://jsfiddle.net/42muhgj3/1/
$(window).scroll(function() {
const pos = Math.max(5, 200 - $(this).scrollTop());
// maximum 200, minimum 5, according to scrollTop
$('#nav').css('top', pos + 'px');
console.log(pos);
});
css
#nav {
background: rgba(0, 0, 0, 0.5);
position: sticky;
top: 200px;
width: 100px;
height: 50px;
}
Related
This question already has an answer here:
scroll events: requestAnimationFrame VS requestIdleCallback VS passive event listeners
(1 answer)
Closed 8 months ago.
Sorry if this is a dumb question, I am super new to programming in html and Javascript.
I know, that I can change some transformation with the scrollpositon, but right now I'm a bit lost. I want to increase the height of a box, when the user scrolls down.
It starts with
"height: 60px;"
and then I'd like it to grow like "height ="60 + scrollY * a very small number + px".
Is there any way to achieve this?
Kind regards and greetings!
let height = 60;//default height
document.addEventListener("mousewheel", function(event){
if(event.wheelDelta >= 0){
height--
element.style.height = `${height}px`
}else{
height++
element.style.height = `${height}px`
}
})
You can use the scroll_event to enlarge the box when a user scrolls.
Here is an example of how to change the box height on scroll using dynamic calculation.
<html lang="en">
<head>
<title>Scroll large demo</title>
<style>
body {
min-height: 1000px;
background: aliceblue;
}
#box {
height: 60px;
background: red;
color: white;
vertical-align: middle;
text-align: center;
position: fixed;
margin: 0 auto;
padding: 15px;
}
</style>
</head>
<body>
<div id="box">
I am going to enlarge when you scroll
</div>
<script>
let lastKnownScrollPosition = 0;
let ticking = false;
function doSomething(scrollPos) {
document.getElementById("box").style.height = 60 + (scrollPos * 0.25) + "px";
}
document.addEventListener('scroll', function (e) {
lastKnownScrollPosition = window.scrollY;
doSomething(lastKnownScrollPosition);
if (!ticking) {
window.requestAnimationFrame(function () {
doSomething(lastKnownScrollPosition);
ticking = false;
});
ticking = true;
}
});
</script>
</body>
</html>
I'm trying to make my header disappear when scrolling down and only re-appear when scrolling up. I can't get it to work:
http://jsfiddle.net/mxj562qt/
Any ideas where I'm going wrong?
HTML:
<div id="header" class="custom-header">
This is your menu.
</div>
<main>
This is your body.
</main>
<footer>
This is your footer.
</footer>
Javascript:
// Hide Header on on scroll down
var didScroll;
var lastScrollTop = 0;
var delta = 5;
var navbarHeight = $("#header").outerHeight();
$(window).scroll(function(event){
didScroll = true;
});
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 250);
function hasScrolled() {
var st = $(this).scrollTop();
// Make sure they scroll more than delta
if(Math.abs(lastScrollTop - st) <= delta)
return;
// If they scrolled down and are past the navbar, add class .nav-up.
// This is necessary so you never see what is "behind" the navbar.
if (st > lastScrollTop && st > navbarHeight){
// Scroll Down
$("#header").addClass('nav-up');
} else {
// Scroll Up
if(st + $(window).height() < $(document).height()) {
$("#header").removeClass('nav-up');
}
}
lastScrollTop = st;
}
CSS:
body {
padding-top: 40px;
}
#header {
background: #f5b335;
height: 50px;
position: fixed;
top: 0;
transition: top 0.2s ease-in-out;
width: 100%;
}
.nav-up {
top: -50px;
}
main {
height: 2000px;
}
footer { background: #ddd;}
* { color: transparent}
It would appear that the CSS class doesn't get added but I'm not sure why. Am I referencing the Div in the wrong way?
So, I can see that the issue stems from this bit of code ...
// Scroll Up
if(st + $(window).height() < $(document).height()) {
$("#header").removeClass('nav-up');
}
In my tests, the doc height was always > than the st + window height.
I did this ...
// Scroll Up
console.log('doc height: ', $(document).height());
console.log('st+window height: ', st + $(window).height());
if(st + $(window).height() < $(document).height()) {
$("#header").removeClass('nav-up');
}
// results from scrolling up + down
// doc height: 2058
// st+window height: 313
// doc height: 2058
// st+window height: 280
// doc height: 2058
// st+window height 1614
// doc height: 2058
// st+window height: 1580
Changing the aforementioned JS to this seems to get you where you need to be.
$("#header").removeClass('nav-up');
Then your CSS needed some work ...
I noticed that your top element wasn't applying due to the CSS selector priority.
.nav-up {
top: -50px !important;
}
The result: scrolling down, the nav bar hides, scrolling up, the navbar shows.
I forked your code below;
http://jsfiddle.net/itsbjk/aw6qb2mr/16/
The problem here is with your CSS. You have specified position:fixed; in your code and that bit of CSS overrides all the JS you are writing. Fixed will force your header to be visible no matter what you are doing. Instead, you could try this in your CSS:
body {
padding-top: 40px;
}
#header {
background: #f5b335;
height: 50px;
position: absolute;
top: 0;
transition: top 0.2s ease-in-out;
width: 100%;
}
.nav-up {
top: -50px;
}
main {
height: 2000px;
}
footer { background: #ddd;}
* { color: transparent}
The absolute property should make it disappear on scrolling. And also, your referencing of the <div> tag isn't wrong!
I want the nav to hide scrolling down 60px and to show when scrolling up 60px, no matter in which part of the page.
I did this, but it's incomplete, what am I missing?
<script>
let y = 0;
</script>
<svelte:window bind:scrollY="{y}" />
<nav class:hideNav={y > 60}>
<ul>
<li>link</li>
</ul>
</nav>
<style>
nav {
position: fixed;
top: 0;
}
.hideNav {
top: -70px;
}
</style>
Your code seems to perfectly hide the navbar after you scroll the specified amount, here is a REPL of your code in action. maybe the body of your content has no scroll ?
here is another implementation REPL that further elaborates how to use scrolling position
<script>
import {onMount, onDestroy} from 'svelte'
const scrollNavBar = 60
let show = false
onMount(() => {
window.onscroll = () => {
if (window.scrollY > scrollNavBar) {
show = true
} else {
show = false
}
}
})
onDestroy(() => {
window.onscroll = () => {}
})
</script>
<style>
.scrolled {
transform: translate(0,calc(-100% - 1rem))
}
nav {
width: 100%;
position: fixed;
box-shadow: 0 -0.4rem 0.9rem 0.2rem rgb(0 0 0 / 50%);
padding: 10px;
transition: 0.5s ease
}
:global(body) {
margin: 0;
padding: 0;
height: 200vh;
}
</style>
<nav class:scrolled={show}>
elemnt
</nav>
In your REPL, it seems like the nav does not reappear on scrolling up. It does appear only at the top of the page.
I am also trying to show the nav when the user scrolls up by 30px anywhere on the page, for instance. I think that it was what OP is asking as well.
I found a REPL successfully doing it with jQuery but I am struggling to make it work in Svelte at the moment. Any clue?
I will revert back if I succeed.
// Hide Header on on scroll down
var didScroll;
var lastScrollTop = 0;
var delta = 5;
var navbarHeight = $('header').outerHeight();
$(window).scroll(function(event){
didScroll = true;
});
setInterval(function() {
if (didScroll) {
hasScrolled();
didScroll = false;
}
}, 250);
function hasScrolled() {
var st = $(this).scrollTop();
// Make sure they scroll more than delta
if(Math.abs(lastScrollTop - st) <= delta)
return;
// If they scrolled down and are past the navbar, add class .nav-up.
// This is necessary so you never see what is "behind" the navbar.
if (st > lastScrollTop && st > navbarHeight){
// Scroll Down
$('header').removeClass('nav-down').addClass('nav-up');
} else {
// Scroll Up
if(st + $(window).height() < $(document).height()) {
$('header').removeClass('nav-up').addClass('nav-down');
}
}
lastScrollTop = st;
}
The answers here couldn't help me. So here's a REPL I made for what I'm using to achieve this in svelte:window.
How I did it;
Create a variable that will store the scroll position (in px) at the end of the scroll event - [let's call it lastScrollPosition].
let lastScrollPosition = 0
At the beginning of a scroll event; inside svelte:window, get and compare the current scroll position to the last scroll position variable we created in [1.] (lastScrollPosition)
<svelte:window on:scroll={()=>{
var currentScrollposition = window.pageYOffset || document.documentElement.scrollTop; //Get current scroll position
if (currentScrollposition > lastScrollPosition) {
showNav = false
}else{
showNav = true
}
lastScrollPosition = currentScrollposition;
}}></svelte:window>
If current scroll Position is greater than lastScrollPosition, showNav is false else, true.
NB: You can use CSS or Svelte Conditional ({#if}) to achieve the hide on scroll down and show on scroll up (This example shows CSS..).
<main>
<div class="nav {showNav == true? "show": "hide" }" >
Nav bar
</div>
<div class="content">
Content
</div>
</main>
<style>
.nav{
background-color: gray;
padding: 6px;
position: fixed;
top: 0;
width: 100%;
}
.content{
background-color: green;
margin-top: 25px;
padding: 6px;
width: 100%;
height: 2300px;
}
.hide{
display: none;
}
.show{
display: unset;
}
</style>
I would like to create vertically a fixed navigation bar for my site. Currently i use the one that has been mentioned on various posts here:
HTML:
<html>
<head>
src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="{% static 'navbar.css' %}">
<script type="application/javascript">
$(document).ready(function () {
var navPos = $('.nav_menu').offset().top; //Sticky navbar
$(window).scroll(function () {
var scrollPos = $(this).scrollTop();
if (scrollPos >= navPos) {
$('.nav_menu').addClass('fixed');
} else {
$('.nav_menu').removeClass('fixed');
}
});
});
</script>
.....
<div class="nav-container">
<div class="nav_menu">
Bars go here
....
And CSS:
.nav-container .nav_menu.fixed {position: fixed; z-index: 10000; top: 0; width: 195px; padding-left: 8px}
This solution works great, the navbar is sticked, in my case the navbar is on the top left side of the page. If i scroll down it perfectly follows the scroll. In case i open the gape using a small window and i stoll down plus right the bar follows (as it should happen). However i would like the bar to only follow vertically, in case someone scrolls left or right the bar should stay where it is.
How can i achieve this?
You can stop the horizontal fixed by applying minus left scroll:
var $window = $(window);
var navPos = $('.nav_menu').offset().top; //Sticky navbar
$window.scroll(function() {
var scrollPos = $window.scrollTop();
var left = 0 - $window.scrollLeft();
if (scrollPos >= navPos) {
$('.nav_menu').addClass('fixed').css('left', left + 'px');
} else {
$('.nav_menu').removeClass('fixed').css('left', 0);
}
});
body,
html {
height: 1000px;
width: 2000px;
position: relative;
margin: 0;
padding: 0;
}
.nav_menu {
height: 50px;
background-color: blue;
width: 195px;
}
.fixed {
position: fixed;
top: 0;
left: 0;
z-index: 2;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<br><br><br>
<div class="nav_menu"></div>
I have the following code:
<html>
<head>
<script src="http://code.jquery.com/jquery.min.js" type="text/javascript"></script>
<script>
$(window).on("scroll",function(e){
var sidepos = parseFloat($('#footer').offset().top - $('#side').outerHeight());
if($(window).scrollTop() > 100 && $('#side').offset().top < sidepos) {
$('#side').css('position','fixed');
$('#side').css('top','0');
}
else if($(window).scrollTop() > 100 && $('#side').offset().top >= sidepos) {
$('#side').css('position','absolute');
$('#side').css('top','' + sidepos + 'px');
}
else if($(window).scrollTop() < 100) {
$('#side').css('position','');
$('#side').css('top','');
}
});
</script>
</head>
<body>
<div id="header"></div>
<div id="body">
<div id="side"></div>
</div>
<div id="footer"></div>
</body>
</html>
I want to keep the #side fixed while scrolling till before the #footer so that it doesn't overlap with it.
Now there are 2 problems:
If you scroll down quickly like pressing 'end' button on keyboard, the function will not execute and the side overlaps with the #footer ignoring the if condition.
After switching to position:absolute can't figure out how to fix again when scrolling up and the #side becomes permanently sticking with the #footer even if you scroll up again.
I created a fiddle for you to test: http://jsfiddle.net/JuD5h/
Here is your updated fiddle: http://jsfiddle.net/JuD5h/4/.
I made some changes to CSS:
#body {
height: 3000px;
position: relative;
}
#side {
width: 100px;
height: 350px;
float: left;
border: 1px solid #000000;
position: absolute;
top: 0;
}
And here is the updated Javascript:
$(function(){ // document ready
var maxAbsoluteTop = $('#body').outerHeight() - $('#side').outerHeight();
var minAbsoluteTop = 0;
$(window).scroll(function(){
var windowTop = $(window).scrollTop();
var actualTop = windowTop - 100;
if ( actualTop <= maxAbsoluteTop && actualTop >= minAbsoluteTop) {
$('#side').css({ top: windowTop - 100 });
} else if (actualTop > maxAbsoluteTop){
$('#side').css({ top: maxAbsoluteTop });
} else {
$('#side').css({ top: minAbsoluteTop });
}
});
});
Use of position: absolute has made the animation flickery but I hope that is something you can fix using a small delay.