I am trying to fix and animate a header navigation so that it pops down from outside of the browser window when a user scrolls past 80px from the top. I then want to reverse the animation when the user scrolls back past <80px. I have gotten this far (have set throttle function earlier in the code):
var e = $(window).scrollTop();
$(window).on("scroll", throttle(function() {
var t = $(window).scrollTop();
t > 80 ? t > e ? $(header).animate({
top: "-150px"
}, 200) :
At the 'else' point I am totally stuck. I've been looking at other similar functions and trying to interpret the code but really struggling. Any help hugely appreciated.
Why are you comparing it with e (which will be usually 0). That's no point. If you want something to happen when the window's scrollTop becomes 80px, just use the following code. Also please not the single true parameter in the animate's stop() function.
$(function () {
$(".peek-a-boo").css({
top: -200
});
$(window).scroll(function () {
if ($(window).scrollTop() > 80)
$(".peek-a-boo").stop(true).animate({
top: 0
}, 200);
else
$(".peek-a-boo").animate({
top: -200
}, 200);
});
});
* {box-sizing: border-box;}
.peek-a-boo {position: fixed; background-color: #99f; width: 100%; top: 0; left: 0; padding: 5px; text-align: center;}
.heighter {height: 1000px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<header class="peek-a-boo">Peek</header>
<div class="heighter"></div>
Related
I would like to have a function that changes the opacity of div when I scroll down. For example, the more I scroll down, the more my divs appear more clearly and when I scroll back up, they do the opposite.
I found code that works well, but I want the opposite. A sort of "scrollBottom". Here's the code that I'm talking about:
$(document).ready(function() {
$(window).scroll(function() {
$(".four").css({
"opacity" : 1 - $(window).scrollTop()/1000})
})
})
I don't have any experience in Javascript, that's why I'm asking you guys! Thank you!
The logic is the mathematical inverse: 0 + $(window).scrollTop() / 1000
$(window).scroll(function() {
$(".four").css({
opacity: 0 + $(window).scrollTop() / 1000
});
});
html, body {
height: 2000px;
}
.four {
opacity: 0;
position: fixed;
top: 25;
left: 25;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="four">Lorem ipsum dolor sit</div>
Okay, I am attempting to get a single page (two divs), Primarily a splash screen, which when you click 'Enter site' and it will scroll down smoothly to the 'main site', However it jumps to it, rather than smooth scrolling to the element.
How would can I get it to scroll to that element smoothly without this jump effect?
Here is my a snippet:
splash = document.getElementById('intro');
content = document.getElementById('content');
function enterSite() {
content.scrollIntoView({
behaviour: "smooth"
});
}
body {
font-family: 'Archivo Narrow', sans-serif;
margin: 0 auto;
width: 100%;
height: 100%;
}
html,
body {
overflow: hidden;
}
main {
width: 100%;
height: 100%;
position: relative;
}
#intro {
background-image: url(https://i.imgsafe.org/51d0cf26df.jpg);
background-repeat: no-repeat;
background-size: cover;
display: flex;
text-align: center;
height: 100%;
}
#splash {
margin: auto;
width: 40%;
background-color: rgba(56, 56, 56, 0.4);
border-radius: 50px 50px;
}
#splash-p {
width: 70%;
font-size: 1.2em;
line-height: 1.5em;
margin: auto;
text-align: center;
padding-top: 10px;
color: #fff;
}
.btn {
width: 35%;
margin: auto;
margin-top: 10px;
margin-bottom: 10px;
}
/* Main Content Page */
article {
position: absolute;
width: 100%;
height: 100%;
background-color: red;
}
<div id="intro">
<div id="splash">
<p id="splash-p">Just a load of text repeated</p>
<input
type="image"
src="Images/Button.png"
class="btn"
onclick="enterSite()"
/>
</div>
</div>
<article id="content">Just a load of text repeated</article>
If you click the button it will jump to the next div, but i need it to scroll smoothly rather than jump to the next div, Using pure javascript, everywhere else i have looked seems to have plug ins or uses jquery.
If you don't want a straight jump, you should animate the scroll somehow.
With the help of jQuery is easy as that:
$("html, body").animate({ scrollTop: $([ELEMENT]).position().top }, 1000);
Look at this fiddle: https://jsfiddle.net/8501ckvn/
jQuery solves a lot of cross browser issues, but if you are looking for a pure javascript solution there are already many answers on Stackoverflow, i.e. look at Smooth scroll anchor links WITHOUT jQuery.
Your content.scrollIntoView({behaviour: "smooth"}); should work, however, I think 'behaviour' is spelt behavior.
I did develop a way of smooth scrolling with TypeScript, but you should be able to convert to JS quite easily:
View stackoverflow answer
For a more comprehensive list of methods for smooth scrolling, see my answer here.
To scroll to a certain position in an exact amount of time, window.requestAnimationFrame can be put to use, calculating the appropriate current position each time. setTimeout can be used to a similar effect when requestAnimationFrame is not supported.
/*
#param pos: the y-position to scroll to (in pixels)
#param time: the exact amount of time the scrolling will take (in milliseconds)
*/
function scrollToSmoothly(pos, time) {
var currentPos = window.pageYOffset;
var start = null;
if(time == null) time = 500;
pos = +pos, time = +time;
window.requestAnimationFrame(function step(currentTime) {
start = !start ? currentTime : start;
var progress = currentTime - start;
if (currentPos < pos) {
window.scrollTo(0, ((pos - currentPos) * progress / time) + currentPos);
} else {
window.scrollTo(0, currentPos - ((currentPos - pos) * progress / time));
}
if (progress < time) {
window.requestAnimationFrame(step);
} else {
window.scrollTo(0, pos);
}
});
}
Demo:
function scrollToSmoothly(pos, time) {
var currentPos = window.pageYOffset;
var start = null;
if(time == null) time = 500;
pos = +pos, time = +time;
window.requestAnimationFrame(function step(currentTime) {
start = !start ? currentTime : start;
var progress = currentTime - start;
if (currentPos < pos) {
window.scrollTo(0, ((pos - currentPos) * progress / time) + currentPos);
} else {
window.scrollTo(0, currentPos - ((currentPos - pos) * progress / time));
}
if (progress < time) {
window.requestAnimationFrame(step);
} else {
window.scrollTo(0, pos);
}
});
}
document.getElementById("toElement").addEventListener('click', function(e) {
var elem = document.querySelector("div");
scrollToSmoothly(elem.offsetTop);
});
document.getElementById("toTop").addEventListener('click', function(e){
scrollToSmoothly(0, 700);
});
<button id="toElement">Scroll To Element</button>
<div style="margin: 1000px 0px; text-align: center;">Div element
<button id="toTop">Scroll back to top</button>
</div>
For more complex cases, the SmoothScroll.js library can be used, which handles smooth scrolling both vertically and horizontally, scrolling inside other container elements, different easing behaviors, scrolling relatively from the current position, and more.
document.getElementById("toElement").addEventListener('click', function(e) {
smoothScroll({toElement: document.querySelector('div'), duration: 500});
});
document.getElementById("toTop").addEventListener('click', function(e){
smoothScroll({yPos: 0, duration: 700});
});
<script src="https://cdn.jsdelivr.net/gh/LieutenantPeacock/SmoothScroll#1.2.0/src/smoothscroll.min.js" integrity="sha384-UdJHYJK9eDBy7vML0TvJGlCpvrJhCuOPGTc7tHbA+jHEgCgjWpPbmMvmd/2bzdXU" crossorigin="anonymous"></script>
<button id="toElement">Scroll To Element</button>
<div style="margin: 1000px 0px; text-align: center;">Div element
<button id="toTop">Scroll back to top</button>
</div>
Alternatively, you can pass an options object to window.scroll which scrolls to a specific x and y position and window.scrollBy which scrolls a certain amount from the current position:
// Scroll to specific values
// scrollTo is the same
window.scroll({
top: 2500,
left: 0,
behavior: 'smooth'
});
// Scroll certain amounts from current position
window.scrollBy({
top: 100, // could be negative value
left: 0,
behavior: 'smooth'
});
Demo:
<button onClick="scrollToDiv()">Scroll To Element</button>
<div style="margin: 500px 0px;">Div</div>
<script>
function scrollToDiv(){
var elem = document.querySelector("div");
window.scroll({
top: elem.offsetTop,
left: 0,
behavior: 'smooth'
});
}
</script>
Modern browsers support the scroll-behavior CSS property, which can be used to make scrolling in the document smooth (without the need for JavaScript). Anchor tags can be used for this by giving the anchor tag a href of # plus the id of the element to scroll to). You can also set the scroll-behavior property for a specific container like a div to make its contents scroll smoothly.
Demo:
html, body{
scroll-behavior: smooth;
}
Scroll To Element
<div id="elem" style="margin: 500px 0px;">Div</div>
Assuming that you have JQuery as well.
You could make use of the following JQuery code to get a smooth scrolling effect
function enterSite(){
$('html, body').stop().animate({
scrollTop: $('#content').offset().top
}, 1500);
});
Let me know if it worked
I have a header on a website that is fixed 20px from the top of the page.
However, I want this to catch the top of the page when scrolling and become fixed to the top of the screen once the user has scrolled that 20px down.
CSS
#header{
padding: 0px 0px 0px 0px;
background: url(../images/header-fill2.jpg) repeat-x top;
position: fixed;
height: 60px;
width: 100%;
top: 20px;
z-index: 5000;
}
I imagine some form of JavaScript is required but have little to no JavaScript experience, so any help would be greatly appreciated.
Just listen for the scroll event and read the value of $(window).scrollTop() and set the top according to that.
Something like:
$(window).on('scroll', function() {
$('#header').css('top', $(window).scrollTop() > 20 ? '0px' : '20px');
});
Example on jsFiddle
The scroll event tells you when the window scrolls. Then, use the scrollTop to find out how much closer to 0 to go:
$(window).on("scroll", function() {
$("#header").css("top", Math.max(0, 20 - $(window).scrollTop()));
});
Live Example
Or to avoid constantly re-creating objects:
(function() {
var $wnd = $(window),
$header = $("#header");
$wnd.on("scroll", function() {
$header.css("top", Math.max(0, 20 - $wnd.scrollTop()));
});
})();
Live Example
Thats how I do that with jQuery.
The position is also cached, for performance reasons:
Here is a fiddle:
http://jsfiddle.net/StephanWagner/u3yrS/
$(document).ready(function() {
var cfixed_nav = false, wscroll;
var setScroll = function() {
wscroll = $(window).scrollTop();
var fixed_nav = wscroll > 20; // Set pixel amount here
if (fixed_nav != cfixed_nav) {
$('body')[fixed_nav ? 'addClass' : 'removeClass']('fixed');
cfixed_nav = fixed_nav;
}
};
setScroll();
$(document).scroll(setScroll);
});
With CSS you set the fixed position:
.fixed #header {
position: fixed;
top: 0;
left: 0;
right: 0;
width: 100%
}
Also remember, that when the header gets the fixed position, those 20px of the header are missing. So you can add a body padding for example:
.fixed {
padding-top: 20px;
}
Or you add an element with 20 Pixel height and swap display none / block depending on the .fixed class in the body
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 was working on this div animation where the original position of div from top is 70% and the div is absolute.
Now, when I click on button it slides to bottom of page with top:95%.
Now I want to check if the position is top:95% and if so, then i want to slide it back to top:70%;
Somehow the Div slides to 95% but dosent come back. what i am doing wrong here??
code
css:-
#mainMenu {
width: 100%;
height: 30px;
background-color: black;
top: 70%;
position: absolute;
}
body {
margin: 0px;
}
#clickToCheck {
font-size: 22px;
}
JQuery
<script>
$(document).ready(function () {
$('#mainMenu').click(function () {
$("#mainMenu").animate({ top: "95%" }, 1100);
});
});
$(document).ready(function () {
$('#clickToCheck').click(function () {
if ($('#mainMenu').position().top === '95%') {
$("#mainMenu").delay(1000).animate({ top: "70%" }, 1200);
} else {
alert('its not at bottom');
}
});
});
and Html
<body>
<span id="clickToCheck">Click to CHeck</span>
<div id="mainMenu"></div>
The problem is that the function
$('#mainMenu').position().top
Will return the value in pixels instead of percentage. So if you want to check if the top is 95% you will have to do the math based on the top and window height (or div height). here is the code:
$('#mainMenu').position().top/$(window).height()*100
Here you will have the the percentage of the #mainMenu in relation to the full window. If the #mainMenu is inside a div, just do based on the div's height. Also beware that you will probably get a number like 94.2343123. So when checking, I would not do and "if = 95". I would do something like "if >= 93" or something like it.
The basic problem is that .position(), .offset(), and .css() all work in pixels by default.
A reasonable workaround would be to store the the menu's original .offset() using .data() and just check to see if its offset has changed, like so:
Working Example
$(document).ready(function () {
$('#mainMenu').data('startPos', $('#mainMenu').offset().top); // when the doc is ready store the original offset top.
$('#mainMenu').click(function () {
$("#mainMenu").animate({
top: "95%"
}, 1100);
});
$('#clickToCheck').click(function () {
if ($('#mainMenu').offset().top > $('#mainMenu').data('startPos')) { // if new offset is greater than original offset
$("#mainMenu").delay(1000).animate({
top: '70%'
}, 1200);
} else {
alert('its not at bottom');
}
});
});