preface

Compared with PC, the input mode of mobile terminal is virtual keyboard, pop-up keyboard will cause some unique compatibility problems on mobile terminal, and as long as it involves form input, it can be encountered, which is also a relatively common mobile H5 compatibility problem. Thanks to this article, I learned a lot: maybe these are the compatibility solutions for h5 keyboard that you want. This article uses a lot of points from this article.

On the keyboardAndroidiosThe performance of the

iniosOn the performance of the

  • After the input box is focused, the keyboard will automatically scroll to make the input box visible. After the keyboard is folded, the scroll bar will not return
  • After clicking the keyboard, the keyboard will collapse and the input box will be out of focus. Clicking other areas of the page will not remove the focus of the input box

inAndroidOn the performance of the

  • After the input box is focused, the keyboard will not automatically scroll to the visible position (some mobile browsers will also automatically scroll to the visible position, but most of our H5 is spread on wechat, so we only discuss the situation of wechat browser here).
  • The input box does not lose focus after the keyboard is retracted
  • In addition to clicking the keyboard fold button to cause fold, clicking on other areas of the page also works

PS: here is the test page address in the GIF above, interested readers can use their own mobile phone to try: test H5 keyboard

According to the above comparison, ios has a better user experience for keyboard up and down. Will not automatically input box in android scroll to visible region will give people a very bad feeling of web pages, and raise the keyboard input box will not automatically out-of-focus also caused by no means the blur event of listening input box to judge whether the keyboard up, so this also leads to the next question, how to monitor the keyboard pops up and pack up?

Listen for the keyboard to pop up

On ios, the keyboard pops up when the input box is focused, and automatically loses focus when the input box is closed. Therefore, it is easy to know that the pop-up state of the keyboard can be judged by the focus or blur events of the input box itself.

The code is shown below

/** Listen for ios keyboard up and down through focus and blur events */
const inputs = document.querySelectorAll(
  "input,textarea,*[contenteditable=''],*[contenteditable='true']"
);
inputs.forEach((input) = > {
  input.addEventListener("focus".() = > {
    console.log("Ios keyboard pops up.");
  });
  input.addEventListener("blur".() = > {
    console.log("Put away the ios keyboard");
  });
});
Copy the code

Unfortunately, the keyboard collapse on Android does not cause the input box to lose focus. In other words, the keyboard collapse cannot be monitored through the blur event.

Here we will mention another performance caused by the keyboard popping up and folding on Android, that is, it will cause the height change of the WebView, we can judge the status of the keyboard by listening to the height change.

The following code

/** Get visibility height */
function getClientHeight() {
  return document.documentElement.clientHeight || document.body.clientHeight;
}

let origin = getClientHeight();
window.addEventListener("resize".() = > {
  const resize = getClientHeight();
  if (origin > resize) {
    console.log("Android keyboard pops up");
  } else {
    console.log("Put away the Android keyboard");
  }
  origin = resize;
});
Copy the code

But listening to the keyboard pop up and down isn’t the goal, optimizing the keyboard experience is. The experience is obviously better on ios, so we changed the behavior on Android to be consistent with ios.

let origin = getClientHeight();
window.addEventListener("resize".() = > {
  const resize = getClientHeight();
  if (origin > resize) {
    console.log("Android keyboard pops up");
    // Be consistent with ios: automatically scroll to the focused input box
    // const focusEl = document.querySelector(
    // "input:focus,textarea:focus,*[contenteditable='']:focus,*[contenteditable='true']:focus"
    // );
    const focusEl = document.activeElement; // There are compatibility issues, older browsers may not support it
    if (focusEl)
      focusEl.scrollIntoView({ behavior: "smooth".block: "center" });
  } else {
    console.log("Put away the Android keyboard");
    // Be consistent with ios: remove focus after the keyboard is down
    // const focusEl = document.querySelector(
    // "input:focus,textarea:focus,*[contenteditable='']:focus,*[contenteditable='true']:focus"
    // );
    const focusEl = document.activeElement;
    if (focusEl) focusEl.blur();
  }
  origin = resize;
});
Copy the code

One important thing to note here is that I commented out the method to get focus elements using querySelector in favor of document.activeElement, because this method has some compatibility issues and may not be supported if your web page runs on older browsers.

aiosOn thebug

I believe that many students have encountered this bug, that is, in ios12 wechat, if the input box is close to the bottom, after the keyboard pops up and folds up, the page that is pushed up because of scrolling will not roll back to the bottom, resulting in the original position of the keyboard is empty.

The solution is simple: record the position of the scroll bar when the keyboard pops up and reset the scroll bar when the keyboard collapses.

/** Get wechat information */
function getWechatInfo() {
  const ua = window.navigator.userAgent.toLocaleLowerCase();
  const match = ua.match(/MicroMessenger\/((\d+)? \.(\d+)? \.(\d+)?) /i);
  return {
    match: match ! = =null.version: (match && match[1) | |""}; }/** Get the page scrollbar height */
function getPageScrollTop() {
  / / why do you write here you can refer to this article: https://www.jianshu.com/p/fb867e8109f7
  return document.documentElement.scrollTop || document.body.scrollTop;
}
/** Sets the scroll bar height */
function setPageScrollTop(height) {
  document.documentElement.scrollTop = height;
  document.body.scrollTop = height;
}

const wechatInfo = getWechatInfo();
const inputs = document.querySelectorAll(
  "input,textarea,*[contenteditable=''],*[contenteditable='true']"
);
let scrollTop = 0;
inputs.forEach((input) = > {
  input.addEventListener("focus".() = > {
    console.log("Ios keyboard pops up.");
    scrollTop = getPageScrollTop();
  });
  input.addEventListener("blur".() = > {
    console.log("Put away the ios keyboard");
    // for IOS12 and wechat 6.7.4 or later, reset the scroll bar position after the keyboard is folded up
    if(wechatInfo.match ! = =true) return;
    if (
      Number(wechatInfo.version.replace(/\./g.""> =))674 &&
      Number(osInfo.version) === 12) { setPageScrollTop(scrollTop); }}); });Copy the code

PS: This bug is also the cause of another weird phenomenon I encountered before, that is, in the popover, in order to prevent scrolling penetration, the body will be fixed to disable the page scroll bar. If there is a input box when the popup window, the pop-up keyboard will cause scrolling up whole, but this time the scroll bar has actually is disabled, but may be rendered in virtually mechanism, in fact the whole page or move up but due to disable the scroll bar and don’t see effect, by this time came strange scene 😱, You can no longer focus the input box by clicking on it, you have to click somewhere above and outside the input box to focus it, as if the entire rendering layout in response to the click has moved up as a whole, causing the click to fail, which is very weird. The good news is that this issue is limited to ios12 🤣

The last

This should be the end of the article, but there are certainly more keyboard input related problems, and there may be more bizarre bugs to be found in the future. There may be a sequel to this article 💀