Skip to content

Instantly share code, notes, and snippets.

@cathyxz
Created April 18, 2018 21:03
Show Gist options
  • Save cathyxz/73739c1bdea7d7011abb236541dc9aaa to your computer and use it in GitHub Desktop.
Save cathyxz/73739c1bdea7d7011abb236541dc9aaa to your computer and use it in GitHub Desktop.

iOS restrictions re: bringing up the keyboard on programmatic focus

I can't find exact specifications on this, but it seems that iOS restricts bringing up the keyboard via programmatically focusing on <input>. It only brings up the keyboard in response to explicit user interaction.

  1. iOS focus on input field only brings up keyboard when called inside a click handler.
  2. It doesn’t work if the focus is async.

This presents a curious problem when you want to autofocus an input inside a modal or lightbox, since what you generally do is click on a button to bring up the lightbox, and then focus on the input after the lightbox has been opened. Without anything fancy, it actually works ok. The problem shows up when you try to add something fancy like a setTimeout or a promise.then(). I don't know why people would want to use a setTimeout here, but waiting for a promise is actually a pretty common use case. E.g. we try to batch dom manipulations like getting a lightbox to show up inside requestAnimationFrame. Also, it's possible that people would want to asynchronously wait for XHRs / data fetches. In any case, that use case is currently not supported by webkit / iOS.

Examples

References

I spent a long time searching for this without success, so I'm documenting it here for anyone else that runs into the same issue.

For reference, we ran into this issue, which was hackily solved by this solution.

@fabb
Copy link

fabb commented Mar 3, 2023

A setTimeout solution: https://stackoverflow.com/a/55652503

wow that's ugly 😅

@cvializ
Copy link

cvializ commented Dec 12, 2024

Thanks for aggregating and publishing this information!! Saved us a lot of time this week 🥇

@Venegrad
Copy link

nothing helps in vuejs

@Fasteroid
Copy link

Fasteroid commented Jul 2, 2025

If anyone needs the opposite (prevent keyboard from showing up when they tap an input), this code may serve your needs...

let running: boolean = false;
let input: HTMLInputElement

async function cursedFocus(this: HTMLInputElement, e: FocusEvent) {
    if( !running ){
        running = true;
            inp.readOnly = true;
            inp.blur();
            inp.focus()
            inp.readOnly = false;
        running = false;
    }
}

input.addEventListener('focusin', cursedFocus);

Text selection otherwise still works... so if you want to just use your own software keyboard, this is your workaround 😉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment