クレジットカード番号の入力欄を input[type=number] で作ると、フォーカスした状態でホイールを回すだけで値が変わります。桁数を間違えても、どこがおかしいのかは画面に出ません。私はこの要素の用途を誤解したまま使っていたので、選ぶ基準を整理します。
input[type=number] はスピンボタンである
値を一定量ずつ増減する操作が役立つ場合に、input[type=number] を使います。MDNでも、数値を段階的に増減する用途へ使うよう説明されています。
<input type=“number”> 要素の暗黙のロールは spinbutton (en-US) です。もしスピンボタンがフォームコントロールにとって重要な機能でないなら、 type=“number” を使用しないよう検討してください。代わりに inputmode=“numeric” を使用し、 pattern 属性で文字列を数字とそれに付随する文字に限定してください。 <input type=“number”> では、ユーザーが何か他のことをしようとしているときに、誤って数値を増加してしまう危険性があります。さらに、ユーザーが数字でないものを入力しようとした場合、何が間違っているのか明示的なフィードバックがありません。
この要素には暗黙のARIAロールとして spinbutton が付与されます。「数字だけを入力する欄」ではなく、範囲内の数値を増減できる入力です。
商品の個数のように増減操作が適しているなら、まずネイティブの input[type=number] と min、max、step の利用を検討します。見た目を変えたいという理由だけで独自の role="spinbutton" を作ると、キーボード操作や値の通知まで自前で実装する必要があります。
数字の入力をしたい場合
クレジットカード番号や郵便番号は数字だけで構成されますが、計算に使う「数値」ではありません。このような値には type="text" を使い、必要に応じて inputmode="numeric" で数字向けの仮想キーボードを提示します。桁数などの制約には pattern を利用できます。
入力条件は、title 属性だけに頼らず、画面上の説明として示したうえで aria-describedby から関連付ける方が確実です。ユーザーが入力する前に条件を理解できるようにします。
<form>
<input name="digit" type="text" pattern="[\d]{3}" title="3 digit number" />
<button>submit</button>
</form>
<form>
<input
name="digit"
type="text"
pattern="[\d]{3}"
aria-describedby="digit-description" />
<span id="digit-description">3 digit number</span>
<button>submit</button>
</form>
独自のエラーメッセージを表示する場合は、入力欄とメッセージを aria-describedby で関連付け、無効な状態を aria-invalid で伝えます。送信後などに動的にメッセージを追加する場合は、role="status" や aria-live の利用も検討します。
<label>
<input
name="digit"
type="text"
inputmode="numeric"
pattern="\d{3}"
aria-invalid="true"
aria-describedby="digit-error" />
<p id="digit-error" role="status" aria-live="polite">
<span>3 digit number</span>
</p>
</label>
判断の基準は、その値を数値として扱うか、増減操作が役立つかです。見た目が数字であることは基準になりません。input[type=number] が扱いづらかったのではなく、想定されていない用途へ使っていたことが問題でした。
input[type=date]を選ぶときの注意
少し寄り道して、input[type=date] にも触れます。送信される値は、表示形式にかかわらず yyyy-mm-dd 形式の日付文字列、または空文字です。表示されるUIや操作方法は、ブラウザとOSによって異なります。
まずは、ローカライズやキーボード操作をブラウザに任せられるネイティブ入力を検討します。特定の日付だけを選べるようにする、複数の日付を扱うなど、要件を満たせない場合に限ってDate Pickerを検討します。独自実装ではアクセシビリティと操作性の確保が難しいため、見た目だけを理由に置き換えない方が安全です。
さいごに
使い慣れた要素ほど、わかったつもりになります。入力要素は、見た目ではなく、値の意味とユーザーが行う操作で選びます。