How to keep an input in focus when clicking on other elements in React

Sometimes in a React application you want to have an input which is the main focus. You might want the cursor to stay focussed on that input even if you click around on different things. Some apps, like dictionaries, have a main search bar, and the user might not want to have to keep refocussing there.

You could try using the onBlur attribute to set the focus back on the element whenever it moves off of it:

<input
    id="search-bar"
    type="text"
    onBlur={e => e.target.focus()}
/>

But there’s a big problem with this. You won’t be able to use any other text input elements because whenever you try to type in them, the focus will just go back to the first element. This is not good.

We need to be able to keep our main text focused when we click on other parts of the page, but allow the focus to change when we select another input element.

It turns out that when on onBlur event occurs, you can find out what element the focus went away to by accessing realatedTarget.

<input
    id="search-bar"
    type="text"
    onBlur={e => {
        // 👇 This will give us the element the user clicked on
        e.relatedTarget
        // We can look at this and decide if we still want to
        // re-focus our original element
        e.target.focus();
    }}
/>

If the user clicked on something that was not an input element (or something without a tabIndex attribute), then e.relatedTarget will be null. Because of this we can do something really simple like this:

<input
    id="search-bar"
    type="text"
    onBlur={e => {
        // only re-focus if the user clicked on something
        // that was NOT an input element
        if (e.relatedTarget === null) {
            e.target.focus();
        }
    }}
/>

Now we have the solution we want:

  • When you click somewhere else that’s not an input element, your original input will stay focussed and the cursor will keep blinking away.
  • When you on another input element the focus/cursor will happily move over there.

When you set an element up with this kind of aggressive focus-holding, it will always stay focussed until you tab-out or click on another input element.

You could also add your own logic to affect the behaviour depeding on what type of input element a user clicked on.

This is a bit of an unusual use case, so use it wisely. Most of the time you would not want the input to stay this aggressively focussed, especially on mobile.


Profile picture

Written by Adam Dueck who likes learning about languages human, or digital.

© 2024