30% offEnding soon
useFocusWithinLoading saved progress…

useFocusWithin

useFocusWithin is a React hook that reports whether keyboard focus is currently on a container element or any element inside it — the JavaScript equivalent of the CSS :focus-within pseudo-class. You reach for the boolean version when CSS alone is not enough: to keep a dropdown open while focus is on any of its options, to announce a form group as active, or to drive any other state from "is focus somewhere in here."

Return a [isFocusWithin, ref] pair. The caller attaches ref to the container they want to watch, and reads isFocusWithin to know whether focus is on that container or any of its descendants.

Signature

function useFocusWithin(): [
  isFocusWithin: boolean,      // true while focus is on the container OR any descendant
  ref: React.RefObject<HTMLElement>, // attach to the container you want to watch
];

Examples

const [isFocusWithin, ref] = useFocusWithin();

// attach the ref to a container that wraps focusable children
<div ref={ref} style={{ outline: isFocusWithin ? '2px solid dodgerblue' : 'none' }}>
  <input placeholder="first name" />
  <input placeholder="last name" />
</div>;
focus the first input             ->  isFocusWithin becomes true
tab from the first to the second  ->  isFocusWithin stays true   (no flicker)
tab out of the group entirely     ->  isFocusWithin becomes false

Notes

  • Bubblingfocus and blur do not bubble, so a listener on the container never hears a child gain focus. Use their bubbling counterparts, focusin and focusout.
  • No flicker — moving focus from one child to another must keep isFocusWithin true the whole time. When focus moves inside the container, the browser fires focusout on the old child before focusin on the new one.
  • relatedTarget — on focusout, event.relatedTarget is the element focus is moving to. It is your signal for whether focus stayed inside the container.
  • Return shape — return [isFocusWithin, ref] and attach the ref to the container. If the ref is never attached, the hook stays false and does nothing.
  • Scope — you are tracking whether focus is present, not whether it came from the keyboard or the mouse. You do not need focus-visible behavior.