1. Qiita
  2. Items
  3. HTML5

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

  • 222
    Like
  • 4
    Comment

おさらいシリーズ第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