# IMEの変換確定のEnterで送信される入力欄

Source: https://easeweb.dev/learn/ime-composition
Topics: フォーム > 日本語変換中のEnterで送信や選択が起きない (WCAG 2.1.1, 3.2.2)
The fix: 欄をフォームに入れて、フォームのsubmitイベントで検索し、どのEnterで送信するかをブラウザーに任せます。チャット欄や候補のリストのように、Enterをスクリプトで扱う必要がある場合は、event.isComposingがtrueか、event.keyCodeが229の間、keydownハンドラーの最初で処理を終えます。
Test with: keyboard, input method, screen reader
References: https://www.w3.org/WAI/WCAG22/Understanding/keyboard.html https://www.w3.org/WAI/WCAG22/Understanding/on-input.html https://www.w3.org/WAI/WCAG22/Techniques/failures/F36 https://w3c.github.io/uievents/#events-composition-key-events https://developer.mozilla.org/en-US/docs/Web/API/Element/keydown_event https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/isComposing https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#implicit-submission https://bugs.webkit.org/show_bug.cgi?id=165004

よくある問題を再現した学習用のサンプルです。実在のクライアントの診断結果ではありません。コードは出発点となる実装例のため、実際の製品でも確認してください。ここでは支援技術でのテスト結果は報告していません。

## 場面

生活雑貨のショップのヘッダーに検索欄があります。検索は `keydown` のハンドラーで実行され、キーがEnterなら検索結果のページを読み込みます。日本語で買い物をする人が折りたたみ傘を探そうと、「傘 折りたたみ」と入力し始めます。日本語はIME（インプットメソッドエディター）で入力します。「かさ」とかなで打ち、Spaceで漢字の候補を出し、「傘」を選んで、Enterで確定します。このEnterまで、語はIMEがまだ変換中の下書きで、欄の中に下線付きで表示されます。これを「変換中（コンポジション）」と呼びます。このEnterはIMEに向けたものですが、ページのハンドラーにも届き、MacのChromeとSafariでは、そのキーは「Enter」です。2つ目の語を入力する前に、「傘」の検索結果のページが読み込まれます。変換が必要な語のたびに同じことが起き、2語で検索しようとしても、語ごとに、入力を終える前に検索が実行されます。

Enterをスクリプトで扱う場所では、同じハンドラーがどこでも問題になります。

- Enterで送信し、Shift + Enterで改行するチャットやコメントの欄：最初に確定した語の時点でメッセージが送られます。
- Enterで強調中の候補を選ぶ候補のリスト：確定のEnterで、入力中の語の代わりに候補が欄に入ります。このパターンのほかの問題は、「[候補を読み上げず、キーボードで選べないオートコンプリート](/ja/learn/combobox)」を参照してください。
- 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で入力する人は、能力にかかわらず、このような欄に入力するたびにこの問題に出会います。下に挙げるのは、特に負担が大きい人です。

## 自動チェックとAIの限界

マークアップはラベル付きの検索欄なので、スキャンでは何も見つかりません。スキャンは文字を入力せず、IMEを使わずに確認する人は変換を始めないため、確定のEnterは一度も起きません。IMEを使う開発者でも気づかないことがあります。WindowsのChromeとFirefoxは、このEnterのキーを「Process」と報告するとされており、問題はまずMacで現れます。「Enterで検索」とAIアシスタントに頼むと、下の修正前のコードが書かれることがよくあります。EaseWebの診断は、スクリプトで作った変換のイベントでページのテキスト欄（最大8つ）に入力し、ChromeとSafariが送る形でEnterを押して、そのEnterでページが送信、別のページの読み込み、通信、欄の消去、フォーカスの移動を行う欄を報告します。実際のキー入力にだけ反応するハンドラーや、リッチテキストエディターのように入力できない欄は確認できません。

## 修正前：keydownのEnterで検索する

```html
<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>
```

ハンドラーは、変換を確定するEnterも含め、すべてのEnterで動作します。IMEが変換中かどうかを確認していません。

## 修正後：フォームにして、ブラウザーに任せる

```html
<form role="search" action="/search">
  <label for="q">検索</label>
  <input id="q" name="q" type="search">
</form>
```

検索欄をフォームにすると、Enterでブラウザーが送信します。これを暗黙的な送信と呼びます。Chrome、Safari、FirefoxはEnterキーの `keypress` イベントで送信し、UI Eventsの仕様は、IMEを使っているときは `keypress` を発生させてはならないとしているため、変換を確定するEnterは確定だけを行います。次のEnterで送信されます。テキスト欄が1つだけのフォームはボタンがなくてもEnterで送信されますが、それを知らない人のために「検索」ボタンがあると助かります。シングルページのサイトでは、フォームの `submit` イベントを受け取り、`preventDefault()` を呼んでからスクリプトで結果を読み込みます。どのEnterで送信するかは、引き続きブラウザーが判断します。

## 修正後：変換を確定するEnterを除外する

```html
<div role="search">
  <label for="q">検索</label>
  <input id="q" type="search">
</div>

<script>
  const input = document.getElementById('q');
  input.addEventListener('keydown', (event) => {
    // IMEの変換を確定するEnter。ChromeとFirefoxではisComposingがtrue。
    // Safariは先に変換を終えるが、keyCodeは229のまま。
    if (event.isComposing || event.keyCode === 229) return;
    if (event.key === 'Enter') search(input.value);
  });
  function search(query) {
    location.assign(`/search?q=${encodeURIComponent(query)}`);
  }
</script>
```

ハンドラーは残し、IMEがキーを使っている間は、キーを見る前に処理を終えます。ChromeとFirefoxは、UI Eventsのとおり、確定のEnterの `keydown` を `isComposing` がtrueの状態で送ります。MacのSafariは先に `compositionend` を送るため `isComposing` は既にfalseですが、古い `keyCode` は、IMEが処理したキーを示す229のままです。`keyCode` は非推奨ですが、MDNは今も `isComposing` と合わせてこの確認を勧めています。Enterをフォームに任せられない場所では、こちらを使います。Enterで送信してShift + Enterで改行するチャット欄や、Enterで強調中の候補を選ぶ候補のリストです。IMEが使うすべてのキーに効くよう、確認はハンドラーの最初に置きます。

## どの方法を選ぶか

どちらも基準を満たします。検索欄や登録の欄のように、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で確認してください。

## 修正の確認

1. Macで日本語入力をオンにする。SafariとChromeで、欄に「かさ」と入力し、Spaceで「傘」に変換して、Enterで確定する。語は欄に残り、検索、送信、候補の選択は起きない。
2. WindowsのMicrosoft IMEで、Chrome、Edge、Firefoxでも同じ操作をする。利用者が使う場合は、中国語や韓国語の入力も試す。
3. 確定した後にもう一度Enterを押す。検索、送信、候補の選択が、期待どおりに行われる。
4. チャット欄では、語を変換して確定してから、Shift + Enterで改行する。候補を出す欄では、変換中に↓キーを押す。IMEの変換候補の選択は移動し、欄の候補の強調は動かない。
5. スクリーンリーダーを起動し、IMEをオンにして変換を確定する。フォーカスは欄に残り、ページは変わらない。

OS、ブラウザー、IME、支援技術のバージョン、ビルド、実施日、各手順の実際の結果を記録してください。検索、チャット、フォームのコンポーネントを変更した際は、再度確認します。

## 制限

このサンプルは、どのアプリケーションでも同じ結果になることを保証するものではありません。例は日本語で入力する1つの検索欄です。中国語のIMEは確定の仕方が異なります。韓国語のIMEは、音節を確定するEnterを通常のEnterとしても渡すことが多く、SafariがそのEnterをkeyCode 229で送るか13で送るかは報告が分かれています。2つ目の修正が、意図したEnterまで無視するおそれがあるため、利用者が韓国語を使う場合はSafariで確認してください。スマートフォンのキーボードは独自の順序でイベントを送るため、利用者が使うIMEで確認してください。リッチテキストエディターは変換を独自に扱うため、別に確認が必要です。検索の処理自体は省略しています。

---

このガイドをコーディングエージェントで使う: MCP https://easeweb.dev/mcp（設定は https://easeweb.dev/ja/services/developers）
