How to fix viewport in place when virtual keyboard opens in mobile Safari?
With the help of JMathew, I found a solution for this problem.
See a working codesandbox example here.
- Put your navbar, message list, and input into container divs.
- Add refs to those container divs. For example:
const messageListContainerRef = useRef(null);
//...
return (
//...
//...
)
- When the virtual keyboard opens (when the dummy input is focused), add an event listener for the touchmove event to the
inputContainerRef
andnavbarContainerRef
. Use that topreventDefault()
on the touch move event, which will prevent the User from being able to slide the input and navbar up and down. For example:
if (inputContainerRef.current) {
inputContainerRef.current.addEventListener('touchmove', (e) => {
e.preventDefault();
});
}
- You will still want to be able to scroll through the message list, so you can't just
preventDefault()
on it. Instead, use this solution (link now dead) to prevent the User from scrolling past the bottom (and top) of the page by setting thescrollTop
value:
if (messageListContainerRef.current) {
messageListContainerRef.current.addEventListener('touchmove', (e: any) => {
if (!e.currentTarget) {
return;
}
if (e.currentTarget.scrollTop === 0) {
e.currentTarget.scrollTop = 1;
} else if (e.currentTarget.scrollHeight === e.currentTarget.scrollTop +
e.currentTarget.offsetHeight) {
e.currentTarget.scrollTop -= 1;
}
});
}
Depending on your want/need, you could set those touchmove
event listeners on component mount, rather than on input focus. You could even set them for the whole document.body, if that works for you.
iOS iPad Fixed position breaks when keyboard is opened
I really like this solution (http://dansajin.com/2012/12/07/fix-position-fixed/). I packaged it up into a little jQuery plugin so I could:
- Set which parent gets the class
- Set which elements this applies to (don't forget "textarea" and "select").
- Set what the parent class name is
- Allow it to be chained
- Allow it to be used multiple times
Code example:
$.fn.mobileFix = function (options) {
var $parent = $(this),
$(document)
.on('focus', options.inputElements, function(e) {
$parent.addClass(options.addClass);
})
.on('blur', options.inputElements, function(e) {
$parent.removeClass(options.addClass);
// Fix for some scenarios where you need to start scrolling
setTimeout(function() {
$(document).scrollTop($(document).scrollTop())
}, 1);
});
return this; // Allowing chaining
};
// Only on touch devices
if (Modernizr.touch) {
$("body").mobileFix({ // Pass parent to apply to
inputElements: "input,textarea,select", // Pass activation child elements
addClass: "fixfixed" // Pass class name
});
}
EDIT: Removed unnecessary element
Prevent virtual keyboard from pushing content up
You can take a look at this StackOverflow post, but I'll summarize the most useful parts for you:
Start off with the input's CSS as position: fixed;
. When in focus, change it to absolute
. Here is an example with JS:
if (document.getElementById("fixed") == document.activeElement) {
document.getElementById("fixed").class += "absolute"
}
Of course, that relies on CSS:
#fixed {
...
position: fixed;
}
#fixed.absolute {
position: absolute;
}
I hope this helps!
Related Topics
Programmatically Open Maps App in iOS 6
Nsphotolibraryusagedescription Key Must Be Present in Info.Plist to Use Camera Roll
How to Set Back Button Text in Swift
How to Scroll the Uiscrollview When the Keyboard Appears
How to Present Popover Properly in iOS 8
Custom Edit View in Uitableviewcell While Swipe Left. Objective-C or Swift
Error: Error Installing Cocoapods: Error: Failed to Build Gem Native Extension
iOS Uitextview or Uilabel with Clickable Links to Actions
Set the Maximum Character Length of a Uitextfield in Swift
Uipageviewcontroller Gesture Recognizers
How to Deserialize a JSON String into an Nsdictionary? (For iOS 5+)
Detect Permission of Camera in iOS
Unexpected Cfbundleexecutable Key