After testing in BrowserStack, I've concluded that using scrollTo()
with option parameter behavior: smooth
does not work in Chrome and Edge since version 81. Version 80 of both Edge and Chrome was working as expected. According to MDN, it should be working with no asterisk. (unlike Safari)
In popular answers such as this one, using behavior: smooth
is the remended way to enable smooth-scrolling in your web application.
Here's a small reproducible:
<html>
<button onclick="goToAnchor('b')">Scroll to B</button>
<div id="a" style="height: 1000px; background-color: blue;">Blue</div>
<div id="b" style="height: 1000px; background-color: red;">Red</div>
<div id="c" style="height: 1000px; background-color: green;">Green</div>
</html>
<script>
function goToAnchor(anchor) {
let rect = document.getElementById(anchor).getBoundingClientRect();
window.scrollTo({
left: rect.left + window.pageXOffset,
top: rect.top + window.pageYOffset,
behavior: 'smooth',
});
}
</script>
After testing in BrowserStack, I've concluded that using scrollTo()
with option parameter behavior: smooth
does not work in Chrome and Edge since version 81. Version 80 of both Edge and Chrome was working as expected. According to MDN, it should be working with no asterisk. (unlike Safari)
In popular answers such as this one, using behavior: smooth
is the remended way to enable smooth-scrolling in your web application.
Here's a small reproducible:
<html>
<button onclick="goToAnchor('b')">Scroll to B</button>
<div id="a" style="height: 1000px; background-color: blue;">Blue</div>
<div id="b" style="height: 1000px; background-color: red;">Red</div>
<div id="c" style="height: 1000px; background-color: green;">Green</div>
</html>
<script>
function goToAnchor(anchor) {
let rect = document.getElementById(anchor).getBoundingClientRect();
window.scrollTo({
left: rect.left + window.pageXOffset,
top: rect.top + window.pageYOffset,
behavior: 'smooth',
});
}
</script>
The expected behavior would be that the browser window smoothly interpolate the view down to the red div. It does this properly in all versions of Firefox I've tested. In all of the versions of Chrome since v81, and all versions of Edge since v81, it seems to use the behavior of behavior: auto
- i.e. it jumps to the div rather than smoothly interpolating the view.
In version 80 of both Edge and Chrome, it behaves just like Firefox, meaning this bug (?) must've been introduced in version 81 - perhaps in the shared Chromium code-base?
I find it very unlikely that I am the first person to find this issue, as it has been not been working since April, and must therefore conclude I am doing something wrong. Can someone point towards the error in the code? Or is the Chrome and Edge APIs really broken? Is the behavior hidden behind a feature flag, like in Safari?
Share Improve this question edited Dec 14, 2020 at 11:27 mplungjan 179k28 gold badges182 silver badges240 bronze badges asked Dec 14, 2020 at 11:19 Emanuel StrömgrenEmanuel Strömgren 3833 silver badges11 bronze badges 5- Works in my Chrome 87.0.4280.66 and Edge 87.0.664.60 – mplungjan Commented Dec 14, 2020 at 11:25
- On what platform? I've tried it via BrowserStack in Win10, Win7 and Mac, not working in any of those cases for me. – Emanuel Strömgren Commented Dec 14, 2020 at 11:26
- Win 10 for me... Smooth – mplungjan Commented Dec 14, 2020 at 11:27
- 1 Interesting. Could this have something to do with user preferences? – Emanuel Strömgren Commented Dec 14, 2020 at 11:28
- W10 x64, Chrome 87.0.4280.88, Edge 87.0.664.60 - Both jump w/o animation to the red div (FF83 works) – Andreas Commented Dec 14, 2020 at 11:30
2 Answers
Reset to default 5I believe I've found the culprit, and interestingly, it seems it is Firefox that is the odd one out.
In this StackOverflow thread about detecting RDP connections, the current top answer says:
You can use the following media query:
@media screen and (prefers-reduced-motion: reduce) { . . . }
The prefers-reduced-motion
part is interesting. It seems in my testing that this also changes scrollTo()
calls with scroll-behavior: 'smooth'
to jump rather than interpolate.
I did an addendum to the question's code example to demo the feature:
<html>
<button onclick="goToAnchor('b')">Scroll to B</button>
<p class="reduced-motion">Reduced motion is enabled.</p>
<div id="a" style="height: 1000px; background-color: blue;">Blue</div>
<div id="b" style="height: 1000px; background-color: red;">Red</div>
<div id="c" style="height: 1000px; background-color: green;">Green</div>
</html>
<style>
.reduced-motion {
display: none;
}
@media (prefers-reduced-motion) {
.reduced-motion {
display: inline;
}
}
</style>
<script>
function goToAnchor(anchor) {
let rect = document.getElementById(anchor).getBoundingClientRect();
window.scrollTo({
left: rect.left + window.pageXOffset,
top: rect.top + window.pageYOffset,
behavior: 'smooth',
});
}
</script>
It will now say "Reduced motion is enabled." next to the button depending on your OS and browser configuration. In that case, the scrollTo call will simply jump rather than interpolate.
In short, the issue is that BrowserStack's remote desktop control is also enabling this flag.
I try to make a test with the MS Edge Version 87.0.664.60 and Google Chrome Version 87.0.4280.88.
On my side, the code works fine on both browsers.
Here is my test result: (Above is the MS Edge and below one is the Google Chrome browser)
You are making this test using the BrowserStack. It is can be possible that the issue is related to BrowserStack.
I suggest you try to make a test using the actual browsers. It may help you to find the cause of the issue.