# Autofocus for Speed

**SHOULD** · **ID:** `interactions-autofocus` · **Category:** interactions
**Source:** [Vercel](https://github.com/vercel-labs/agent-skills/blob/main/skills/web-design-guidelines/SKILL.md)
**Interactive version:** https://ui-guides-agent-rules.netlify.app/principles/interactions-autofocus

> SHOULD: Autofocus on desktop when there's a single primary input; rarely on mobile (to avoid layout shift)

On desktop, autofocus single primary inputs; rarely on mobile

For desktop interfaces with a clear primary action (like a search box), autofocus saves users a click. On mobile, avoid autofocus because the virtual keyboard opening causes jarring layout shifts and may scroll the page unexpectedly.

## Bad — do not do this

`interactions-autofocus-bad`

```tsx
export function AutofocusBad() {
  return (
    <div className="w-full max-w-sm">
      <div className="bg-card border border-border rounded-lg p-4">
        <h3 className="font-semibold mb-3">Mobile Search Page</h3>
        <div className="bg-error/10 border border-error/20 rounded-lg p-3 mb-3">
          <code className="text-xs text-error-foreground font-mono">
            {'<input autoFocus />'}
          </code>
        </div>
        <div className="border-2 border-dashed border-border rounded-lg p-4 text-center">
          <p className="text-sm text-muted-foreground mb-2">📱 On mobile:</p>
          <p className="text-xs text-muted-foreground">
            Autofocus opens the keyboard immediately, causing layout shift and potentially hiding important content above the input.
          </p>
        </div>
      </div>
      <p className="text-xs text-error mt-4">
        Autofocus on mobile causes keyboard layout shift
      </p>
    </div>
  );
}
```

## Good — do this

`interactions-autofocus-good`

```tsx
import { useEffect, useRef } from 'react';

export function AutofocusGood() {
  const inputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    // Only autofocus on desktop (pointer: fine indicates mouse/trackpad)
    const isDesktop = window.matchMedia('(pointer: fine)').matches;
    if (isDesktop && inputRef.current) {
      inputRef.current.focus();
    }
  }, []);

  return (
    <div className="w-full max-w-sm">
      <div className="bg-card border border-border rounded-lg p-4">
        <h3 className="font-semibold mb-3">Search</h3>
        <input
          ref={inputRef}
          type="search"
          placeholder="Search..."
          className="w-full px-3 py-2 border border-border rounded-lg text-base focus:outline-hidden focus:ring-2 focus:ring-ring"
        />
        <div className="mt-3 bg-success/10 border border-success/20 rounded-lg p-3">
          <code className="text-xs text-success-foreground font-mono block whitespace-pre">
{`// Conditional autofocus
const isDesktop =
  matchMedia('(pointer: fine)').matches;
if (isDesktop) input.focus();`}
          </code>
        </div>
        <p className="text-xs text-muted-foreground mt-2">
          Desktop: autofocus saves a click. Mobile: no autofocus, no keyboard jump.
        </p>
      </div>
      <p className="text-xs text-success mt-4">
        Autofocus only on desktop, skip on mobile
      </p>
    </div>
  );
}
```

## References

- [Autofocus](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/autofocus)
