How to override the CSS scroll behavior with scrollTo in JavaScript
You can set the inline style of your container's scroll to auto
, then reverting the change by altering the value of html.style.scrollBehavior
before and after scrolling programmatically. JS's ScrollToOptions
's behavior
key-value pair cannot override CSS's scroll-behavior
. The CSSOM draft mentions this:
If the user agent honors the scroll-behavior property and one of the following are true:
• behavior is "auto" and element is not null and its computed value of
the scroll-behavior property is smooth• behavior is smooth
...then perform a smooth scroll of box to position. Otherwise, perform an instant scroll of box to position.
Your user agent honors the scroll-behavior
property; this means that we're going to check one of the two conditions. When you're using window.scroll({..., behavior: 'auto'})
, we're entering the first condition. The behavior
we're setting is indeed auto
, element is indeed not null
, and the computed value of scroll-behavior
property is indeed smooth
. Therefore, a smooth scroll will happen. To make the condition false, we can override the computed value of the scroll-behavior
property to auto
by using an inline style.
Here's a simple example. Scroll programmatically without smooth behavior by clicking the Scroll down 200
button. Scroll smoothly by clicking the links.
function scrollNoSmooth() { // Setting inline style of scroll-behavior to 'auto' temporarily html.style.scrollBehavior = 'auto' // This 'behavior' cannot override the CSS 'scroll-behavior' // Do scroll window.scroll({ top: window.scrollY + 200, left: 0, // behavior: 'smooth' }) // Reverting inline style to empty html.style.scrollBehavior = ''}
const html = document.querySelector('html')const fixed = document.querySelector('.fixed')
fixed.addEventListener('click', scrollNoSmooth)
html { scroll-behavior: smooth; position: relative;}
a { display: block; height: 400px; width: 100%; display: flex; justify-content: center; align-items: center;}
.fixed { display: flex; justify-content: center; align-items: center; position: fixed; width: 150px; height: 50px; border-radius: 5px; background: #121212; color: white; cursor: pointer;}
<div class="fixed">Scroll down 200</div><a name="A" href="#B">A</a><a name="B" href="#C">B</a><a name="C" href="#A">C</a>
How to override scroll functions in a window?
The window.scroll
, window.scrollTo
and window.scrollBy
methods do not refer to the native scrolling functionality. They are used to scroll to specific locations on the webpage. If you want to implement a completly custom scrolling functionality/behaviour you need to listen to the wheel
event, prevent the default and define your custom behaviour.
Note: changed scroll to wheel event as comment mentioned error
document.addEventListener("wheel", (event) => {
event.preventDefault();
event.stopPropagation();
// now define custom functionality
}, { passive: false });
Instead of window you can also apply it to any other element on the page that has a scrollbar and therefore being scrollable.
Futhermore the wheel event has values for deltaX and deltaY so you can see how much would have been scrolled since the last scroll and you can use the properties x and y to see how much had been scrolled since the beginning.
I have the scroll behavior set to smooth in CSS but how to write it in JS?
scroll-behavior CSS property make the contents within an element scroll smoothly.
While Element.scrollIntoView is used to programmatically scroll to an element.
If you want for example scroll to the header of the page with scroll-behavior: smooth
you can opt-in the behavior
option and set it to smooth
.
var header = document.getElementById("header")
header.scrollIntoView({ behavior: "smooth" })
Scroll instantly to the top when smooth is set with CSS
This is because you have set the css property scroll-behavior
to smooth.
The window.scrollTo
behavior option doens't override the css value.
Replace
window.scrollTo({ top: 0, behavior: 'auto' });
With
document.documentElement.style = "scroll-behavior: auto";
document.documentElement.scrollTo({ top: 0, behavior: 'auto' }); // or just leave it window.scrollTo(...), doens't matter. I just like it this way ;)
let button = document.getElementById("test");
button.addEventListener('click', () => { // Reset the CSS scroll-behavior property document.documentElement.style = "scroll-behavior: auto"; document.documentElement.scrollTo({ top: 0, behavior: 'auto' }); // or just leave it window.scrollTo(...), doens't matter // Do more stuff here, like setting the 'scroll-behavior' back to smooth .....});
html { height: 100000px; scroll-behavior: smooth;}
button { position: fixed;}
<button id="test">Scroll down then click me</button>
CSS overflow-y: scroll overwrite my code and other functions not working
What is happening here?
Since your animation works with window.innerHeight
whenever you try to add overflow: scroll
to your container
it will disable the window scrolling, in order to have only one active scrollbar at the same time (This is not actually happening but it is the problem(ish)). So the calculation of document.body.scrollHeight - window.innerHeight;
will be 0
then your header animation wont fill ever due to this equation var percentage = scrollPosition / scrollableHeight * 100;
(the scrollableHeight is zero so the result will be infinity).
How to fix it?
So the best way to fix this issue is to determine the active scrollbar and assign scroll-behaviour
to it's parent. Since in normal flow your active scrollbar is depended on body
itself you should remove overflow-y: scroll;
from your container and then add scroll-behavior: smooth;
to the active scrollbar parent
So your final output should be something like this:
html,body {
scroll-behavior: smooth;
}
#container {
width: 100%;
height: 100vh;
}
...
Override scroll up/down function if scrollTop is equal to 0
Here you go: just add a catch for when the scrollTop value is 0.
$(window).scroll(
{
previousTop: 0
},
function () {
var currentTop = $(window).scrollTop();
if (currentTop < this.previousTop ) {
if (currentTop != 0 ) { // new if statement here prevents fadein if at top of page
header.fadeIn('slow');
header.css('background', 'rgba(0,0,0,.9)');
}
} else {
header.fadeOut();
}
this.previousTop = currentTop;
});
Related Topics
Get Current CSS Property Value During a Transition in JavaScript
How to Check If Text Is Truncated by CSS Using JavaScript
Adding Custom CSS and Js to Shopify
Grunt Plugin for Assets Versioning
How to Make Specific Part of a String Bold in Angular 2
Remove Styles from Text When Copying/Cutting Using CSS or JavaScript
Absolute Positioned Floating Header Jitters in Safari
Handle Webpack CSS Imports When Testing with Mocha and Babel
JavaScript .Replace Alternative
The Best Way of Checking for -Moz-Border-Radius Support
Does Animating the Value of a CSS3 Transform with JavaScript Rule Out Hardware Acceleration
How to Combine Fixed Height Header with Flexible Page Layout
How to Parse CSS Font Shorthand Format
How to Show the Only Part of the Image
How to Detect Device Name in Safari on iOS 13 While It Doesn't Show the Correct User Agent