Edited at

HTML5におけるinput要素のpattern、type属性のおさらい

More than 1 year has passed since last update.

おさらいシリーズ第4弾w

HTML5ではinput要素が拡張されて正規表現による入力値バリデーションができるようになっている。利用するには、 <input pattern=""> のように pattern 属性値にバリデーション用の正規表現を書いてやればよい。

──で、毎度UI作っていて正規表現パターンを調べるのが手間だったので、定形的な入力値については一度まとめておこうかと思った次第。

まぁ、正規表現の自分用チートシートみたいなものですな。


pattern属性用正規表現サンプル集

バリデーション内容
正規表現(pattern属性)
備考

3文字以上
.{3,}
バイト単位ではなく、半角・全角ともに1文字となる

半角英数字
^[0-9A-Za-z]+$

半角英数字6文字以上
^([a-zA-Z0-9]{6,})$

半角英字8文字
[A-Za-z]{8}

ファイル名チェック
^[-0-9a-zA-Z_.]+$
マルチバイト文字を含むファイル名は非対応

パスワード用
(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}
8文字以上で1文字以上の数字、小文字アルファベット、大文字アルファベットがそれぞれ含まれていること

郵便番号
\d{3}-\d{4}
※1

電話番号
\d{2,4}-\d{3,4}-\d{3,4}
※2

メールアドレス
[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$
※3

URL
https?://.+
※4

全角カタカナ

^[ァ-ンヴー]+$ , [\u30A1-\u30FF]*

出力されるHTMLがUTF-8である必要あり※5

半角カタカナ
[\uFF66-\uFF9D]*
出力されるHTMLがUTF-8である必要あり

全角ひらがな

^[ぁ-ん]+$ , [\u3041-\u309F]*

出力されるHTMLがUTF-8である必要あり※6

全角数字
[\uFF10-\uFF19]*
出力されるHTMLがUTF-8である必要あり

全角アルファベット
[\uFF21-\uFF3A|\uFF41-\uFF5A]*
パイプ「|」のところは半角で

半角英数字以外
[^\x20-\x7E]*

日時(Y-M-d H:i:s)
\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}
※7

正の整数
[1-9][0-9]*
※8

'"のクォーテーションを許可しない
[^\x22\x27]*
検索フォームのバリデーションに適しているかも

IPアドレス
^\d{1,3}(\.\d{1,3}){3}$
※9

浮動小数点
^-?\d{1,}\.\d*$


Notices

※1 ハイフンありなしを許容する場合は \d{3}-?\d{4} のようにする

※2 国番号付きを許容する場合は ^(+|)\d{2,4}-\d{3,4}-\d{3,4} のようにする

※3 もっと厳密にバリデーションしたい時は ^[a-zA-Z]{1}[0-9a-zA-Z]+[\w\.-]+@[\w\.-]+\.\w{2,}$ こんなのが良いかも

※4 もっと厳密にバリデーションしたい時は ^http(|s)://[0-9a-zA-Z/#&?%\.\-\+_=]+$ こんなのも良いかも

※5 全角空白と半角空白を許容する場合は [ァ-ンヴー| | ]+$ のようにする

※6 長音記号「ー」はカタカナだが、許容したい場合は、\u30FC をパターンマッチさせる

※7 もっと精密に、 ([1-2]{1}[0-9]{3})\-([0-1][0-9])\-([0-3][0-9]) (0[0-9]|1[0-9]|2[0-3])(:[0-5][0-9]){2} こんなのも良いかも

※8 0を許容するなら (0|[1-9][0-9]*) とする

※9 厳密にチェックするなら ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ が良い(な、長い…)


ちなみに、input要素すべてでpattern属性が有効になるわけではなく、input要素のtype属性の種類とブラウザによって有効対象が異なる。調べたところ、その対応表は下記の通りだった。

ちなみに、調べた各PCブラウザのバージョンは2015年7月14日時点の最新バージョンで、AndroidはOS 4.2.2、iPhoneは持ってないので不明である。


pattern属性が有効なtype属性

type属性
chrome
Firefox
IE11
Safari
Opera
Android

text



×

×

search



×

×

url



×

×

email



×

×

password



×

×

datetime



×

×

date
×


×
×
×

month
×


×
×
×

week
×


×
×
×

time
×


×
×
×

datetime-local
×


×
×
×

number
×
×
×
×
×
×

range
×
×
×
×
×
×

color
×
×

×
×
×

うーん、Safari(Windows版)と、同じWebkitブラウザであるAndroid標準ブラウザではPattern属性が使えなかった…。おそらく同じWebkit系ブラウザのiPhoneでも一緒だと思われる。

やっぱり難儀なクロスブラウザの壁…。


type属性によるバリデーション

さて、もうひとつ。HTML5でのinput要素の拡張は結構多くて、前述のpattern属性を使わなくても、type属性に入力候補値の型を適切に指定することで、入力フィールド自体のUIが最適化されるようになってもいる。HTML5の黎明期にはこのフィールド最適化に対応しているブラウザはOperaぐらいしかなかったんだが、そろそろ他のモダンブラウザも対応されているかなぁ…と思って調べてみた。

type値
Chrome
Firefox
IE11
Safari
Opera
Android

text
-
-
-
-
-
-

search
オートコンプリートが有効なフィールド
text と同じ
text と同じ
入力値クリア用のXボタンが付く
オートコンプリートが有効なフィールド
オートコンプリートが有効なフィールドになり実行ボタンが検索ボタンになる

url
[a-zA-Z]{1,}:.*
[a-zA-Z]{1,}:.*
.{1,}:.*
text と同じ
[a-zA-Z]{1,}:.*
text と同じ

tel
text と同じ
text と同じ
text と同じ
text と同じ
text と同じ
電話番号に利用できる文字しか入力できない

email
.{1,}@.*
.{1,}@.*
.{1,}@.*
.{1,}@.*
.{1,}@.*
text と同じ

password
半角英数記号のみ
半角英数記号のみ
半角英数記号のみ
半角英数記号のみ
半角英数記号のみ
半角英数記号のみ

datetime
text と同じ
text と同じ
text と同じ
スピンボックス
text と同じ
text と同じ

date
Dateピッカー(カレンダー付)
text と同じ
text と同じ
スピンボックス
Dateピッカー(カレンダー付)
text と同じ

month
Dateピッカー(カレンダー付)
text と同じ
text と同じ
スピンボックス
Dateピッカー(カレンダー付)
text と同じ

week
Dateピッカー(カレンダー付)
text と同じ
text と同じ
スピンボックス
Dateピッカー(カレンダー付)
text と同じ

time
タイムフィールド(スピンボックス型)
text と同じ
text と同じ
スピンボックス
タイムフィールド(スピンボックス型)
text と同じ

datetime-local
Dateピッカー(カレンダー付)+タイムフィールド
text と同じ
text と同じ
スピンボックス
Dateピッカー(カレンダー付)+タイムフィールド
text と同じ

number
スピンボックス
スピンボックス

^[-+]{,1}\d.* (※)
スピンボックス
スピンボックス
数値固定フィールド

range
レンジバー
レンジバー
レンジバー
レンジバー
レンジバー
レンジバー

color
カラーピッカー
カラーピッカー
text と同じ
text と同じ
カラーピッカー
text と同じ


※ IE11の type="number" のバリデーションはバグのような仕様。先頭が数値ならあとは文字列でも受け入れてしまう…これはひどい。


chromeとOperaのtype属性によるフィールド最適化はすばらしくリッチなのだが、ブラウザごとにここまで実装に差があると、やはりtype属性だけに頼ったUIではダメなことがわかる。また、email(a@aで通ってしまう)やurl(1:.で通ってしまう)など、type属性でバリデーションされる正規表現が貧弱すぎて、およそ役に立たないということもある。今のところ信頼して使えるのは type="range" だけだ。

うーん、この辺はブラウザ各社が足並みを揃えて実装して欲しいもんだなぁ…。


結論として…

だいだい予想はしていたんだが、HTML5のinput要素によるバリデーションはまだまだ使い物になるレベルではないということがわかった。

まぁ、フロントエンドで入力値のバリデーションがしっかりやられていたとしても、バックエンドに値が渡った時点でまたしっかりバリデーションするのは基本だ(クロスサイトスクリプティング攻撃にはHTML+ブラウザでのバリデートなんてほぼ無力だからね)。

…でも、そうなんだけど、少しでもバックエンド側のリスクが下がるならもうちょっとフロントエンド側でもしっかりバリデーションができるようになってくれると嬉しいもんだ。

今のところ、最低限input要素のtypeとpattern属性は入力候補値に合わせて最適化しておくと、まぁ気休め程度にはなるのかな…w