モバイルブラウザのキーボードの種類は制御できない

スマートフォンなどのモバイル端末のブラウザでは、input要素をフォーカスするとキーボードが出現する。
このキーボードは、「英語」「日本語 - かな」などの種類があり、日本語利用者なら切り替えながら使っているだろう。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31785/46b5bac3-5083-79d6-19c4-91b3a4a8d87b.png" width="320px">

で、input要素をフォーカスした時に出てくるこのキーボードの種類を制御したい、という要望はままあるだろう。
たとえば、英数字のみからなる何らかのシリアルコードのようなものの入力欄は、日本語ではなく英語キーボードを表示させたいだろう。
結論からいうと、**キーボードの種類は制御できない。**
もう少し正確に言うと、**日本語ではなく英語キーボードを常に表示させるようにすることはできない。**

## type属性で制御できるのではないか
巷の技術系ブログなどではよく書かれている。

```html
<!-- email入力用だから、英語キーボードであるべき？ -->
<input type="email">

<!-- URL入力用だから、英語キーボードであるべき？ -->
<input type="url">
```
たしかに、多くのモバイルブラウザは、type属性を`email`や`url`に指定することによって、それに適したキーボードを表示する機能をサポートしてはいる。
iOS Safariの場合、`type="email"`のときは、スペーキーの隣に`@`や`.`など、メールアドレスによく使う文字キーが配置されている。（前掲のスクリーンショット画像がまさにそれだ）

一見すると、求めていた挙動が実現されているように思うが、ちょっと待って欲しい。

### 日本語キーボードに切り替えしてみる
`type="email"`をフォーカスしてキーボードを表示したら、わざと日本語に切り替えた上でinput要素のフォーカスをはずしてみよう。そして、再び同要素をフォーカスしてキーボードを表示させてみる。
このとき日本語キーボードが表示されるだろう。これはあなたの求めている挙動だろうか。  
次にページをリロードしてみて、再び同要素をフォーカスする。やはり日本語キーボードが出るだろう。  
同じページ内に、別要素の`type="email"`があるならば、そちらにフォーカスを当ててみよう。やはり日本語キーボードが出るはずだ。これはあなたの求めている挙動だろうか。  
なんなら、他のページの`type="email"`要素でキーボードを日本語にした後、当該サイトの`type="email"`にフォーカスしてみよう。iOS Safariでは日本語キーボードが出るだろう。（Androidでは英語キーボードが出る）
何度も言うが、これはあなたが求めている挙動だろうか。[^1]  
あなたが求めているのは、当該要素をフォーカスしたときには常に英語キーボードが表示されることではないのか。[^2]その要素に入力されるべきは英数字だけなのだから。

## メールアドレスはマルチバイト文字が含まれ得る
なぜこんなことになるのか。
メールアドレス入力用のtype属性値ならば、英語キーボードだけ表示されればいいのではないのか。
現に、`input[type="tel"]`は数字キーボードのみ、`input[type="password"]`は英語キーボードのみであり、キーボードの種類を変更することはできない。
理由は、メールアドレスの入力には英語キーボードだけでは不十分だからだ。  
RFCの定義によれば、メールアドレスに使われる文字には制限があり、マルチバイト文字は含まれないらしいのだが、[Gmailではマルチバイト文字を含むメールアドレスへの受送信が可能](https://googleblog.blogspot.com/2014/08/a-first-step-toward-more-global-email.html)だ。
本来の規格としてNGだったとしても、Gmailがサポートしている以上、マルチバイト文字を含むメールアドレスは存在する。存在する以上は、入力できなければならない。入力するためには、日本語キーボードに切り替え可能でなければならないのだ。
そして、ひとたびユーザが`type="email"`要素で日本語キーボードに切り替えたならば、ブラウザは「ユーザーは日本語でemailを入力しようとしている」と解釈し、それ以後`type="email"`フォーカス時には日本語キーボードを表示するようになると考えられる。ユーザビリティとしては筋が通っている。

これは、`input[type="url"]`についても同様だ。
日本語ドメインは存在している。そうでなくても、ディレクトリ名やパラメータにマルチバイト文字が含まれることは普通にある。[^3]
であるならば、日本語キーボードが表示されうる。

### inputmodeという属性もあるが
`inputmode="email"` `inputmode="url"`とすることで、入力キーボードを指定できるという属性値だが、これとてもtype属性と同じ挙動だ。

### 入力値が英数字でなければならないtype属性は存在しない
ただし、パスワード`type="password"`を除く。
`type="password"`は当然ながら伏字になるので、通常はパスワード以外には使えない。
というわけで、常に英語キーボードを表示させるようにする手段は、我々には与えられていない。


## 我々はどうすべきか
諦めよ。そして、ユーザを信頼せよ。
たとえ日本語キーボードが開いたとしても、英数字で書くべきことを理解すれば、ユーザーは自らの手で英語キーボードに切り替えて入力するであろう。

### バリデーションと入力補助
通常は誤った値が入力された場合には、それと分かるエラー文言を表示するものだろう。ユーザに気づかせて軌道修正させればよい。
全角文字が入力された際には、JavaScriptで半角に自動変換する機能くらいは実装しておくと親切かもしれない。

## なぜこの記事を書いたか
> この入力欄に入力する値は英数字なので、英語キーボードが出るようにします。
その方がユーザに負担がかからないので。

あなたはこのように仕様を決めた手前、フォーカス時に日本語キーボードが出てしまう挙動を何とかしたいと思うかもしれない。
だが、立ち止まってよく考えてみて欲しい。これはそれほど問題なことなのか。
ユーザは自分でキーボードを切り替えることができ、適切に入力するのに何の支障もないではないか。  
ユーザは自分がどうすべきか（英数字で入力）をきちんと理解できるようになっていれば、「英語キーボードを出す」などという些末な事象にとらわれる必要はどこにもない。

スマホで「英語キーボードを出す」ということについて、できる、できる、と書いてある記事ばかりなので、当然実装しなければならなくなってしまう。確かに概ね期待通りにできるのだが、重箱の角をつつくようなデバッグ[^4]には耐えられず、不具合として報告されてしまう。報告された以上は、何とか対応しようとするものの、完璧に制御することはできないのだと理解した。
このことについて触れている記事がなく、とても困ったので書いた。[^5]
実装を担当しているあなたが、クライアントやディレクターに、この記事を見せて、
> ここに書いてある通り、表示するキーボードを完璧に制御することはできません。
> type属性を`email`にしておけば、初回フォーカス時には（100％ではないですが）概ね英語キーボードで開くようですので、このくらいの対応で手を打ちましょう。

と適当な妥結点を見出してくれることを期待する。



[^1]: `type="url"`でも同様。
[^2]: もちろん、ユーザ手動で英語キーボードに戻しておけば、再度フォーカス時には英語キーボードが出る。
[^3]: Wikipediaを見よ。
[^4]: これがデバッガーの仕事なので当然である。
[^5]: 問題の性質上当然なのだが、検索しても英語の記事は全く出てこない。