angular/components · warning

Element matching '[cdkFocusInitial]' is not focusable.

Error message

Element matching '[cdkFocusInitial]' is not focusable.

What it means

When a focus trap initializes, the element matching [cdkFocusInitial] must be focusable. If the FocusTrapChecker determines it is not (disabled, hidden, non-interactive, display:none), the trap warns in dev mode and instead falls back to focusing the first tabbable child of that element (or fails if none).

Source

Thrown at src/cdk/a11y/focus-trap/focus-trap.ts:244

      if (
        (typeof ngDevMode === 'undefined' || ngDevMode) &&
        redirectToElement.hasAttribute(`cdk-focus-initial`)
      ) {
        console.warn(
          `Found use of deprecated attribute 'cdk-focus-initial', ` +
            `use 'cdkFocusInitial' instead. The deprecated attribute ` +
            `will be removed in 8.0.0`,
          redirectToElement,
        );
      }

      // Warn the consumer if the element they've pointed to
      // isn't focusable, when not in production mode.
      if (
        (typeof ngDevMode === 'undefined' || ngDevMode) &&
        !this._checker.isFocusable(redirectToElement)
      ) {
        console.warn(`Element matching '[cdkFocusInitial]' is not focusable.`, redirectToElement);
      }

      if (!this._checker.isFocusable(redirectToElement)) {
        const focusableChild = this._getFirstTabbableElement(redirectToElement) as HTMLElement;
        focusableChild?.focus(options);
        return !!focusableChild;
      }

      redirectToElement.focus(options);
      return true;
    }

    return this.focusFirstTabbableElement(options);
  }

  /**
   * Focuses the first tabbable element within the focus trap region.
   * @returns Whether focus was moved successfully.

View on GitHub (pinned to 0411926e7d)

Solutions

  1. Make the cdkFocusInitial element focusable: remove disabled/hidden states or use tabindex="0" / tabindex="-1" as appropriate
  2. Point cdkFocusInitial at an actually focusable element (button, input, link) that is visible when the trap opens
  3. Ensure the element exists and is rendered before the trap is initialized
  4. If intentional, target a container and rely on the fallback: the first tabbable child will receive focus

Example fix

// before
<div cdkFocusInitial>Summary</div>
// after
<div tabindex="-1" cdkFocusInitial>Summary</div>
Defensive patterns

Strategy: validation

Validate before calling

const initial = trapElement.querySelector('[cdkFocusInitial]');
if (initial && (initial.matches(':disabled, [hidden]') || !initial.offsetParent)) {
  console.warn('[cdkFocusInitial] target is not focusable/visible');
}

Type guard

function isFocusable(el: HTMLElement): boolean {
  return !el.hasAttribute('disabled') && el.tabIndex >= -1 &&
    !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length);
}

Prevention

When it happens

Trigger: focusInitialElement resolves redirectToElement via the cdkFocusInitial attribute query, then this._checker.isFocusable(redirectToElement) returns false in dev mode, triggering the console.warn.

Common situations: Pointing cdkFocusInitial at a disabled button, an element hidden with CSS (display:none/visibility:hidden) at trap open time, or a plain non-interactive div; conditionally rendering the initial element after the trap opens.

Related errors


AI-assisted analysis of angular/components@0411926e7d (2026-08-31). Data as JSON: /api/errors/72932527b5435a49. Report an issue: GitHub.