The autofocus attribute automatically places the cursor in an input field as soon as the page loads, letting users start typing right away.
HTML の autofocus は、ページが読み込まれた直後(厳密には DOM が完全に構築され、描画キューが落ち着いた段階)でブラウザに “このコントロールへフォーカスを当てよ” と指示するシンプルなブール属性です。フォームで最初に入力してほしい箇所へカーソルを置く、といった ユーザーの手間を 1 クリックでも減らす 目的で導入されました。
ただし「フォーカスを奪う」という行為はアクセシビリティ・ユーザー体験・セキュリティの三面で影響が大きく、使い方次第では UX を悪化させる諸刃の剣となります。
特に、ページが読み込まれた直後にフォーカスを当てると、キーボード操作を行うユーザーにとっては便利ですが、マウス操作を行うユーザーには混乱を招く可能性があります。そのため、autofocus 属性は慎重に使用する必要があります。
HTML
<form action="/search" method="get">
<input type="search" name="q" placeholder="Enter keywords" autofocus>
<button>Search</button>
</form>
ブール属性なので autofocus="autofocus" や autofocus="" と書いても同義。慣例的に短縮形を使います。
ページ内で 最初に見つかった 1 要素だけ が有効。複数指定しても最初のもの以外は無視されます。
disabled / hidden / display:none / visibility:hidden / inert などでフォーカス可能でない場合はスキップされ、次の候補も自動では選ばれません(結果として “どこにもフォーカスが当たらない” 状態になり得る点に注意)。
focus() イベントをディスパッチEarly 2020 s の仕様変更で セキュリティ警戒レベルが高いコンテキスト(例:クロスオリジン iframe)では自動フォーカスが抑制 されるようになりました。
Chrome 102+ は バックフォワードキャッシュ復元時 にあらためて autofocus を適用します。一方 Safari は復元時には走査しないため挙動差に留意。
スクリーンリーダー利用者はフォーカス移動を “ページ読み上げ中に突然飛ばされる” と感じやすい。<h1> 見出し直後に配置し、文脈をつなぐナレーションがあると混乱を抑えられます。
モバイルではソフトキーボードが即座に現れ、レイアウトが大きく押し上がるため、ユーザーが “コンテンツを一瞥” できなくなる。重要度とページタイプ(検索専用 vs. 読み物)で使い分ける。
フォームが複数あるページでは、ユーザーが入力意図を持たないエリアで勝手にフォーカスを奪わない。“明確に主目的のフォーム only” が原則。
display:none → 後から表示mounted / useEffect で el.focus() を明示呼び出し。autofocus 自体は有効だが、シャドウ境界を跨いでフォーカスリングが隠れると UX が悪化。pageshow イベントで再フォーカス。JavaScript
// Progressive Enhancement: まず HTML の autofocus を書き、
// 動的レンダリング時のみ JS で fallback
function safeFocus(el) {
if (!el) return;
requestAnimationFrame(() => {
// 非表示判定を自前でチェック
const rect = el.getBoundingClientRect();
const visible = rect.height > 0 && rect.top >= 0 && rect.bottom <= window.innerHeight;
if (visible) el.focus({ preventScroll: true });
});
}
preventScroll:true で 即スクロールによる CLS (Cumulative Layout Shift) を回避。
複雑な UI では “初回ロード直後はスクロールさせず、ユーザー操作でスクロール時にだけフォーカス” という UX も選択肢。
autofocus は キーロガー系攻撃 で乱用されることがある(例:見えないパスワードフィールドへ自動フォーカス → 努力せずパスワードを盗む)。
ブラウザは “同一オリジン+ユーザーの信頼済みジェスチャ” かつ “フィールドが表示領域内” という条件でフォーカス制限を行うが 完全防御ではない。
CSP (Content Security Policy) の frame-ancestors を併用し、怪しい iframe 埋め込みをブロックするのが望ましい。
JavaScript
const SearchBox = () => {
const ref = useRef(null);
useEffect(() => {
ref.current?.focus();
}, []);
return <input ref={ref} type="search" placeholder="Search…" />;
};
SSR(Next.js 等)で autofocus を書くと Hydration ミスマッチ が起こる場合があるため、クライアント側で useEffect へ寄せるのが安全。
HTML
<script setup>
import { onMounted, ref } from 'vue';
const el = ref();
onMounted(() => el.value?.focus());
</script>
<template>
<input ref="el" placeholder="検索語…" />
</template>
Vue の <input autofocus> 自体は動作するが、遅延マウント時にはズレるのでディレクティブ化(v-focus)して制御粒度を上げると保守しやすい。
HTML
<input #box />
TypeScript
@ViewChild('box', { static: true }) box!: ElementRef<HTMLInputElement>;
ngAfterViewInit() { this.box.nativeElement.focus(); }
ルーター遷移で再描画される際、Resolver でデータ待ちする場合は ngAfterViewInit 内でタイマーを挿む とチラツキが軽減。
autofocus 時に scrollIntoView() 相当の挙動。古いレイアウトで “画面最下部へジャンプ” ケースがあるため、条件付きクラスで回避推奨。cy.focused().should('have.attr', 'name', 'q')await expect(page.locator('[name=q]')).toBeFocused();:focus-visible スタイルを整備しておくと false positive を減らせる。autofocus が存在し、どちらも display:none だったら?autofocus を効かせたい。どう設計?afterEach)で “スクリーントップ/ダイアログ開閉” を検知し、対象ノードへ focus({preventScroll:true})。:tabindex="-1" を一時付与し、キーボードタブ順を壊さない工夫を添えると自然。position:fixed のステルスプレースホルダーを読み込み直後に表示 → 実際の UI が描画されたら focus() → プレースホルダーを除去。視覚的なジャンプを 0 に近づけられる(ただし実装難度高)。autofocus は “1 クリック削減” の即効薬 だが、アクセス環境・ユーザー意図・セキュリティの三要素を考慮したうえで “ここぞ” に限って使用する。
SPA & モバイルが当たり前の 2025 年では、JavaScript 補完が実質標準。preventScroll・タイミング調整・ヒストリ復元時の再適用までワンセットでハンドリングすると、プロダクション品質に到達する。
テスト自動化でフォーカス検証をルーチン化 し、リグレッションの温床を潰すのが上級者のたしなみ。