トピックを検索
IMEの変換確定のEnterで送信される入力欄
ショップの検索欄が、どのEnterのkeydownでも検索するため、日本語の変換を確定するEnterで、入力途中の語が検索されてしまいます。
if (event.key === 'Enter') search(input.value); 問題
日本語や中国語をIMEで入力する人の、検索や送信が、入力の途中で実行されてしまいます。
生活雑貨のショップのヘッダーに検索欄があります。検索は keydown のハンドラーで実行され、キーがEnterなら検索結果のページを読み込みます。日本語で買い物をする人が折りたたみ傘を探そうと、「傘 折りたたみ」と入力し始めます。日本語はIME(インプットメソッドエディター)で入力します。「かさ」とかなで打ち、Spaceで漢字の候補を出し、「傘」を選んで、Enterで確定します。このEnterまで、語はIMEがまだ変換中の下書きで、欄の中に下線付きで表示されます。これを「変換中(コンポジション)」と呼びます。このEnterはIMEに向けたものですが、ページのハンドラーにも届き、MacのChromeとSafariでは、そのキーは「Enter」です。2つ目の語を入力する前に、「傘」の検索結果のページが読み込まれます。変換が必要な語のたびに同じことが起き、2語で検索しようとしても、語ごとに、入力を終える前に検索が実行されます。
Enterをスクリプトで扱う場所では、同じハンドラーがどこでも問題になります。
- Enterで送信し、Shift + Enterで改行するチャットやコメントの欄:最初に確定した語の時点でメッセージが送られます。
- Enterで強調中の候補を選ぶ候補のリスト:確定のEnterで、入力中の語の代わりに候補が欄に入ります。このパターンのほかの問題は、「候補を読み上げず、キーボードで選べないオートコンプリート」を参照してください。
- Enterで次の欄に移るフォーム:名前や住所の途中で、カーソルが別の欄に移ります。
IMEはキー入力を文字に変えます。確定のEnterも、そのキー入力の1つです。達成基準2.1.1は、すべての機能をキーボードインターフェースで操作できることを求めています。欄への入力も機能の1つですが、この欄は入力の一部を命令として受け取るため、変換が必要な文字を一度に入力できません。達成基準3.2.2は、コンポーネントの設定を変えても、事前に知らせない限り、新しいページのようなコンテキストの変化を起こしてはならないとしています。その解説書は、テキスト欄への文字の入力を、設定の変更に含めています。確定のEnterは文字の入力の一部で、それによって新しいページが読み込まれます。W3Cが文書にしている失敗例で最も近いのはF36です。利用者がまだ値を入力している途中で、予告なしにフォームが自動で送信されるもので、F36は「送信ボタンとEnterキーによる標準のフォームの動作」に頼るよう勧めています。確定のEnterは、この標準の動作には当たりません。ブラウザー自身のフォームも、そのEnterでは送信しないからです。
どちらの達成基準もIMEには触れておらず、Enterはどれも送信の要求だと主張することもできます。このガイドは逆に考えます。利用者は語を選んだことをIMEに伝えるためにEnterを押しており、ブラウザー自身もそのEnterではフォームを送信せず、ハンドラーは1行でその違いを判別できるためです。Enterで新しいページではなくメッセージが送られる場合は、コンテキストの変化ではないため、2.1.1だけが当てはまります。
日本語や中国語をIMEで入力する人は、能力にかかわらず、このような欄に入力するたびにこの問題に出会います。下に挙げるのは、特に負担が大きい人です。
10グループ中3グループに影響
- 全盲 (影響あり)
- 弱視 (影響なし)
- 色覚 (影響なし)
- ろう (影響なし)
- 難聴 (影響なし)
- 発話 (影響なし)
- 手の操作 (影響あり)
- 届く範囲・力 (影響なし)
- 認知 (影響あり)
- 光過敏 (影響なし)
- 手の操作が限られる ゆっくり入力する人、片手やマウススティック、スクリーンキーボードで入力する人は、1語ごとに何度もキーを押します。最初の語を確定した時点で検索されると、欄に戻って文字の終わりを探し、残りを入力し直すことになり、次の語でも同じことが起きます。
- 言語・認知・学習の能力が限られる 入力し終える前に検索されると、サイトに言葉を読み違えられたように見えます。変換のために押したEnterとのつながりが分からないため、何が起きたのか、どうすれば避けられるのかが分かりにくくなります。
- 視覚を使わない 語を確定したスクリーンリーダーの利用者には、検索結果のページが先頭から読み上げられます。検索語が途中で切れたことに自分で気づき、検索欄を探し直す必要があります。
マークアップはラベル付きの検索欄なので、スキャンでは何も見つかりません。スキャンは文字を入力せず、IMEを使わずに確認する人は変換を始めないため、確定のEnterは一度も起きません。IMEを使う開発者でも気づかないことがあります。WindowsのChromeとFirefoxは、このEnterのキーを「Process」と報告するとされており、問題はまずMacで現れます。「Enterで検索」とAIアシスタントに頼むと、下の修正前のコードが書かれることがよくあります。EaseWebの診断は、スクリプトで作った変換のイベントでページのテキスト欄(最大8つ)に入力し、ChromeとSafariが送る形でEnterを押して、そのEnterでページが送信、別のページの読み込み、通信、欄の消去、フォーカスの移動を行う欄を報告します。実際のキー入力にだけ反応するハンドラーや、リッチテキストエディターのように入力できない欄は確認できません。
試してみる
ウィンドウの上の日本語入力で、変換が必要な語を入力してから、欄でEnterを押して検索してください。
「傘」を確定するEnterは、IMEに向けたものです。ページがそのEnterで検索するか、ページに何が届いたかを見てください。日本語入力を使える場合は、欄に実際に入力しても試せます。
問題あり 修正できますか?
Linden Home
梅雨に備えて
毎日使える傘、長靴、カバー。
ページに届いたEnter: まだなし
修正方法
Enterをフォームに任せるか、変換を確定するEnterを除外します。
- 1欄はフォームで送信するか、
isComposingがtrueかkeyCodeが229の間はEnterを無視する。 - 2Enterの処理はkeydownで行い、keyupでは行わない。
- 3実際のIMEで、ChromeだけでなくSafariでも確認する。
<div role="search"> <label for="q">検索</label> <input id="q" type="search"></div> <script> const input = document.getElementById('q'); input.addEventListener('keydown', (event) => { if (event.key === 'Enter') search(input.value); }); function search(query) { location.assign(`/search?q=${encodeURIComponent(query)}`); }</script>フォームにして、ブラウザーに任せる
<form role="search" action="/search"> <label for="q">検索</label> <input id="q" name="q" type="search"></form>この方法を選ぶ理由:まずHTMLの要素を使う
ハンドラーは、変換を確定するEnterも含め、すべてのEnterで動作します。IMEが変換中かどうかを確認していません。
検索欄をフォームにすると、Enterでブラウザーが送信します。これを暗黙的な送信と呼びます。Chrome、Safari、FirefoxはEnterキーの keypress イベントで送信し、UI Eventsの仕様は、IMEを使っているときは keypress を発生させてはならないとしているため、変換を確定するEnterは確定だけを行います。次のEnterで送信されます。テキスト欄が1つだけのフォームはボタンがなくてもEnterで送信されますが、それを知らない人のために「検索」ボタンがあると助かります。シングルページのサイトでは、フォームの submit イベントを受け取り、preventDefault() を呼んでからスクリプトで結果を読み込みます。どのEnterで送信するかは、引き続きブラウザーが判断します。
どちらも基準を満たします。検索欄や登録の欄のように、Enterで送信する欄にはフォームを使ってください。スクリプトが不要で、非推奨のプロパティに頼らず、ブラウザーがイベントの順序を変えても動き続けます。textarea、チャットの入力欄、コンボボックスのように、Enterにほかの役割があるか、Enter以外のキーも扱い、フォームでは対応できない場所には、keydownでの確認を使います。たいていのサイトでは、場所に応じて両方が必要です。
確認は2つとも残してください。2016年に登録されたWebKitのバグ165004には、macOSのSafariが keydown の前に compositionend を送る順序が記録されています。WebKitは2026年4月に仕様どおりの順序に切り替えましたが、不具合の報告が相次いだため、6月に再び無効にしました。そのため、Safariは今も確定のEnterを isComposing がfalseの状態で送ります。isComposing で除外できる環境では、keyCode の確認は何の負担にもなりません。代わりにキーが「Process」かどうかを調べる方法は使えません。MacのChromeとSafariは「Enter」と報告します。
compositionstart で立てて compositionend で下ろすフラグだけでは足りません。Safariでは compositionend が確定の keydown より先に来るため、Enterが届いたときにはフラグが既に下りています。
Enterの処理は keyup ではなく keydown で行います。確定のEnterの keyup は compositionend の後に来て isComposing はfalseで、MDNによると keyup にはIME用の特別な keyCode もないため、送信のためのEnterと区別できません。
候補のリストでは、同じ確認によって矢印キーがIMEに残ります。変換中は上下の矢印キーでIMEの変換候補を選ぶため、コンボボックスのハンドラーが同じキーで自分の強調を動かすと、2つのリストが混乱します。
フレームワークでは、欄に渡すハンドラーに同じ確認を入れます。チャットの入力欄やタグの入力欄など、独自にEnterを扱うコンポーネントライブラリーも、頼る前に実際のIMEで確認してください。
AI コーディングアシスタントで修正しますか? このガイドを Markdown で取得、または全ガイドをコーディングエージェントで使う。
修正の確認
マウスを使わない5つの確認
確認方法: キーボード、日本語入力(IME)、スクリーンリーダー
OS、ブラウザー、IME、支援技術のバージョン、ビルド、実施日、各手順の実際の結果を記録してください。検索、チャット、フォームのコンポーネントを変更した際は、再度確認します。
制限
このサンプルは、どのアプリケーションでも同じ結果になることを保証するものではありません。例は日本語で入力する1つの検索欄です。中国語のIMEは確定の仕方が異なります。韓国語のIMEは、音節を確定するEnterを通常のEnterとしても渡すことが多く、SafariがそのEnterをkeyCode 229で送るか13で送るかは報告が分かれています。2つ目の修正が、意図したEnterまで無視するおそれがあるため、利用者が韓国語を使う場合はSafariで確認してください。スマートフォンのキーボードは独自の順序でイベントを送るため、利用者が使うIMEで確認してください。リッチテキストエディターは変換を独自に扱うため、別に確認が必要です。検索の処理自体は省略しています。
よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。
参考資料
- WCAG Understanding: keyboard(新しいタブで開きます)
- WCAG Understanding: on-input(新しいタブで開きます)
- WCAG Technique F36(新しいタブで開きます)
- w3c.github.io: uievents(新しいタブで開きます)
- developer.mozilla.org: keydown_event(新しいタブで開きます)
- developer.mozilla.org: isComposing(新しいタブで開きます)
- html.spec.whatwg.org: form-control-infrastructure(新しいタブで開きます)
- bugs.webkit.org: show_bug.cgi(新しいタブで開きます)
コードを更新しても、使いやすさを保つために
ガイドの内容を、コーディングエージェントやCIで使える開発ルールにまとめます。更新後は、キーボードとスクリーンリーダーで再テストし、問題が再発していないか確認します。