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
・タイミング調整・ヒストリ復元時の再適用までワンセットでハンドリングすると、プロダクション品質に到達する。
テスト自動化でフォーカス検証をルーチン化 し、リグレッションの温床を潰すのが上級者のたしなみ。