I want to call focus()
on an input after the widow scrolled. I\'m using the smooth behavior for the scrollTo()
method. The problem is the foc
Other answers didn't fully work for me, therefore based on @Fabian von Ellerts answer, I wrote my own solution.
My problems were that :
The element I was scrolling (and all its parents along the hierarchy) always had a offsetTop
of 0, so it was not working.
I needed to scroll a nested element.
Using getBoundingClientRect
and a container element as reference works :
const smoothScrollTo = (
scrollContainer,
scrolledContent,
offset,
callback
) => {
const fixedOffset = (
scrollContainer.getBoundingClientRect().top + offset
).toFixed()
const onScroll = () => {
if (
scrolledContent.getBoundingClientRect().top.toFixed() ===
fixedOffset
) {
scrollContainer.removeEventListener('scroll', onScroll)
callback()
}
}
scrollContainer.addEventListener('scroll', onScroll)
onScroll()
scrollContainer.scrollTo({
top: offset,
behavior: 'smooth',
})
}
I found a way to achieve what I want but I think it's a bit hacky, isn't it?
let el = document.getElementById('input')
let elScrollOffset = el.getBoundingClientRect().top
let scrollOffset = window.pageYOffset || document.documentElement.scrollTop
let padding = 12
let target = elScrollOffset + scrollOffset - padding
window.scrollTo({
top: target,
behavior: 'smooth'
})
window.onscroll = e => {
let currentScrollOffset = window.pageYOffset || document.documentElement.scrollTop
// Scroll reach the target
if (currentScrollOffset === target) {
el.focus()
window.onscroll = null // remove listener
}
}
I wrote a generic function based on the solution of George Abitbol, without overwriting window.onscroll:
/**
* Native scrollTo with callback
* @param offset - offset to scroll to
* @param callback - callback function
*/
function scrollTo(offset, callback) {
const fixedOffset = offset.toFixed(),
onScroll = function () {
if (window.pageYOffset.toFixed() === fixedOffset) {
window.removeEventListener('scroll', onScroll)
callback()
}
}
window.addEventListener('scroll', onScroll)
onScroll()
window.scrollTo({
top: offset,
behavior: 'smooth'
})
}