Last active
May 11, 2024 10:21
-
-
Save MartijnHols/e9f4f787efa9190885a708468f63c5bb to your computer and use it in GitHub Desktop.
React hooks for getting the document height that updates when the On Screen Keyboard/Virtual Keyboard toggles
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
The latest version is available at https://martijnhols.nl/gists/how-to-get-document-height-ios-safari-osk |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useEffect } from 'react' | |
const useOnScreenKeyboardScrollFix = () => { | |
useEffect(() => { | |
const handleScroll = () => { | |
window.scrollTo(0, 0) | |
} | |
window.addEventListener('scroll', handleScroll) | |
return () => { | |
window.removeEventListener('scroll', handleScroll) | |
} | |
}, []) | |
} | |
export default useOnScreenKeyboardScrollFix |
Thanks you so much .
…On Thu, Nov 9, 2023 at 4:39 PM Martijn Hols ***@***.***> wrote:
***@***.**** commented on this gist.
------------------------------
@dylan0805 <https://github.com/dylan0805> This is pretty hacky; at the
limits of what is reasonable to do in a browser. I'd only use if you
*really* need to.
import { useEffect, useRef } from 'react'
import findNearestScrollContainer from './utils/findNearestScrollContainer'
// On iOS in the browser you can pull on elements down / make the page bounce// similar to pull to refresh. This causes weird behavior when trying to// simulate a full screen app.// This is a partial fix for edge cases where this is still possible (e.g. on// iOS 15 when hiding the button bar via the Aa button on the address bar). Most// regular cases are fixed properly by ensuring the page content height isn't// larger than the viewport.const usePreventOverScrolling = () => {
const container = useRef<HTMLDivElement>(null)
useEffect(() => {
const elem = container.current
if (!elem) {
return
}
let startTouch: Touch | undefined = undefined
const handleTouchStart = (e: TouchEvent) => {
if (e.touches.length !== 1) {
return
}
startTouch = e.touches[0]
}
const handleTouchMove = (e: TouchEvent) => {
if (e.touches.length !== 1 || !startTouch) {
return
}
const deltaY = startTouch.pageY - e.targetTouches[0].pageY
const deltaX = startTouch.pageX - e.targetTouches[0].pageX
if (Math.abs(deltaX) > Math.abs(deltaY)) {
// Horizontal scroll probably
return
}
const target = e.target as HTMLElement
const nearestScrollContainer = findNearestScrollContainer(target)
if (!nearestScrollContainer) {
console.log('Preventing scroll: no nearest scroll container')
e.preventDefault()
return
}
const isScrollingUp = deltaY < 0
const isAtTop = nearestScrollContainer.scrollTop === 0
if (isScrollingUp && isAtTop) {
console.log(
'Preventing scroll: already at top of nearest scroll container',
)
e.preventDefault()
return
}
const isAtBottom =
nearestScrollContainer.scrollTop ===
nearestScrollContainer.scrollHeight -
nearestScrollContainer.clientHeight
if (!isScrollingUp && isAtBottom) {
console.log(
'Preventing scroll: already at bottom of nearest scroll container',
)
e.preventDefault()
return
}
}
elem.addEventListener('touchstart', handleTouchStart)
elem.addEventListener('touchmove', handleTouchMove)
return () => {
elem.removeEventListener('touchstart', handleTouchStart)
elem.removeEventListener('touchmove', handleTouchMove)
}
}, [container])
return container}
export default usePreventOverScrolling
const findNearestScrollContainer = (
elem: HTMLElement,): HTMLElement | undefined => {
if (elem.scrollHeight > elem.offsetHeight) {
return elem
}
const parent = elem.parentElement
if (!parent) {
return undefined
}
return findNearestScrollContainer(parent)}
export default findNearestScrollContainer
—
Reply to this email directly, view it on GitHub
<https://gist.github.com/MartijnHols/e9f4f787efa9190885a708468f63c5bb#gistcomment-4755106>
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ARGPXRKGH46ARBU5OJAG3ITYDSQFRBFKMF2HI4TJMJ2XIZLTSKBKK5TBNR2WLJDHNFZXJJDOMFWWLK3UNBZGKYLEL52HS4DFQKSXMYLMOVS2I5DSOVS2I3TBNVS3W5DIOJSWCZC7OBQXE5DJMNUXAYLOORPWCY3UNF3GS5DZVRZXKYTKMVRXIX3UPFYGLK2HNFZXIQ3PNVWWK3TUUZ2G64DJMNZZDAVEOR4XAZNEM5UXG5FFOZQWY5LFVEYTAOJYGA2TGNZQU52HE2LHM5SXFJTDOJSWC5DF>
.
You are receiving this email because you were mentioned.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>
.
Thanks, Martijn 🙏
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@dylan0805 This is pretty hacky; at the limits of what is reasonable to do in a browser. I'd only use if you really need to.