How to properly set focus on an input element

Photo by Chase Clark on Unsplash

How to properly set focus on an input element

Managing focus on mount and dynamically controlling focus

Autofocus

When you want to draw the user's attention to a specific element upon initial rendering, the autofocus attribute can be a quick and effective solution.

This attribute tells the browser to automatically give the element focus when the page loads, allowing users to interact with it without having to click or tab through other elements first.

// plain html
<input autofocus type="text" />

// React (camel case syntax)
<input autoFocus type="text" />

Dynamic focus

To dynamically set focus on an element, you can utilize a ref in React to access the DOM node or React element and control its focus state. This behavior is typically performed as part of a side effect.

Here's an example of how you can implement this functionality:

const Form = () => {
  const ref = useRef(null);
  const setFocus = useCallback(() => ref?.current?.focus(), []);

  return (
    <div> 
      <button onClick={setFocus}>Start filling up your info!</button>
      <input ref={ref} type='text'/>
    </div>
  );  
}

After a click event occurs, the setFocus function will use the reference to the input element to dynamically control its focus state.

This technique can be helpful in situations where you need to programmatically set focus to an element, such as in response to user interactions or changes in the application's state.

Custom hook

Extracting the logic for controlling the focus state of an element can be beneficial since it allows for reuse across multiple components. To accomplish this, we can create a custom hook that is solely responsible for managing the focus state.

Here's an example of how you can create a custom focus management hook:

const useFocus = () => {
  const ref = React.useRef(null);
  const setFocus = useCallback(() => ref?.current?.focus(), []);

  return [ref, setFocus];
}

This is what the final implementation will look like:

const Form = () => {
  const [ref, setFocus] = useFocus();

  return (
    <div> 
      <button onClick={setFocus}>Start filling up your info!</button>
      <input ref={ref} type='text'/>
    </div>
  );  
}

Sprinkle some types

As an added bonus, we can refactor the custom hook to utilize TypeScript and ensure that it has proper type annotations:

export default function useFocus<T extends HTMLElement = HTMLElement>() {
  const ref = useRef<T>(null);
  const setFocus = useCallback(() => ref?.current?.focus(), []);

  return [ref, setFocus] as const;
}

Supported elements for autofocus

Only specific HTML elements are supported by the autofocus attribute. The list of supported elements is provided below:

  • <input>

  • <select>

  • <textarea>

  • <button>

What about accessibility?

It's worth noting that relying too heavily on autofocus can be frustrating for some users. For example, it can interfere with users who rely on keyboard navigation to navigate a website, as autofocus can disrupt the expected tab order.

To mitigate these potential issues, you can provide additional visual cues that draw attention to the element in question. This can include using contrasting colors, increasing the font size, or adding an animation to the element.

In addition, it's important to keep in mind accessibility best practices when using autofocus. For example, you should ensure that the focused element is highlighted in a way that's visible to users with color vision deficiencies. You can also provide alternative text for the element if it's an image or a button.