Webパーツ辞典

入力マスクInput mask

数字を打つそばからハイフンやスラッシュが自動で入る入力欄。090-1234-____ のように、まだ埋まっていない桁を下線で見せることもある。

表示例

数字だけで入力できます。ハイフンは自動で入ります

月/年 の順に4桁(例: 08/28)

別名・英語表記

  • 自動ハイフン入力
  • 書式つき入力欄
  • フォーマット入力
  • マスク入力
  • 電話番号の自動整形
  • Input mask

実装例

<div class="x-input-mask">
  <div class="x-input-mask__row">
    <label class="x-input-mask__l" for="x-input-mask-tel">携帯電話番号</label>
    <p class="x-input-mask__h" id="x-input-mask-tel-h">数字だけで入力できます。ハイフンは自動で入ります</p>
    <!-- 入力欄の後ろに、まだ埋まっていない書式の「_」を等幅で敷く。飾りなので読み上げから外す -->
    <div class="x-input-mask__f">
      <span class="x-input-mask__g" aria-hidden="true"><span class="x-input-mask__done">090-1234-</span>____</span>
      <input class="x-input-mask__i" id="x-input-mask-tel" type="tel" name="tel" value="090-1234-"
             autocomplete="tel-national" aria-describedby="x-input-mask-tel-h">
    </div>
  </div>
  <div class="x-input-mask__row">
    <label class="x-input-mask__l" for="x-input-mask-exp">カードの有効期限</label>
    <p class="x-input-mask__h" id="x-input-mask-exp-h">月/年 の順に4桁(例: 08/28)</p>
    <div class="x-input-mask__f x-input-mask__f--s">
      <span class="x-input-mask__g" aria-hidden="true"><span class="x-input-mask__done">08/28</span></span>
      <input class="x-input-mask__i" id="x-input-mask-exp" type="text" name="cc-exp" value="08/28"
             inputmode="numeric" autocomplete="cc-exp" aria-describedby="x-input-mask-exp-h">
    </div>
  </div>
</div>

AIへの指示文

「入力マスク(Input mask)」を実装してください。

## これは何か
数字を打つそばからハイフンやスラッシュが自動で入る入力欄。090-1234-____ のように、まだ埋まっていない桁を下線で見せることもある。

## 使いどころ
- 電話番号・郵便番号・カードの有効期限(MM/YY)のように、区切り方が決まった値を入れてもらうとき
- 区切りを見せたほうが桁の打ち間違いに気づきやすいとき

## 実装の要件
- label + 補足文 + input[type=tel または inputmode=numeric][autocomplete]。必要なら input の後ろに同じ等幅書体で「090-1234-____」の飾りを aria-hidden で敷く
- input イベントで数字だけ取り出し、書式に合わせて区切りを入れ直す。書き換えの前後で「キャレットより前にある数字の個数」を数え、その位置へ setSelectionRange で戻す
- event.isComposing が true の間(IME の変換中)は書き換えず、compositionend のあとで整える。beforeinput で入力そのものを止めない
- 送信する値は区切りを除いた数字にそろえる。サーバー側でも同じ正規化をかけ、マスクが動かなかった入力も受け取れるようにする
- テキストフィールドとの違い: 入力に合わせて区切り文字を足し、書式を整えながら受け取る。形式が決まっていない値にはマスクをかけない
- 形式を押し付けて入力を拒まない。GOV.UK Design System は電話番号について、空白・ハイフン・括弧を含むなじみのある書き方を受け入れるよう勧めている。ハイフンあり・なし・全角のどれで打たれても、受け取ってから整える
- マスクは貼り付け・自動入力・日本語入力(IME)の変換中の入力とぶつかりやすい。変換が確定するまでは書き換えず、貼り付けた値は数字だけ取り出してから整える
- 書き換えるたびにキャレットが末尾へ飛ぶ実装が多い。途中の桁を直したときも、キャレットを打った位置に保つ
- 書式はプレースホルダーではなく補足文に書く。打ち始めると消えて、どう打つのか分からなくなる

## アクセシビリティの要件
- どんな書式で入るのか、区切りを打つ必要があるかを、ラベルか補足文に言葉で書き aria-describedby で結ぶ(3.3.2 ラベル又は指示)
- 未入力の桁を示す「_」の飾りは aria-hidden="true" にする。読み上げが「アンダースコア」を何度も読まないようにする
- autocomplete を付ける(電話番号は tel-national / tel、郵便番号は postal-code、有効期限は cc-exp)。自動入力で入った値もマスクで整える(1.3.5 入力目的の特定)
- 桁が足りない・範囲外(13月など)のときは、欄を離れたときに何が違うかを文言で伝える(3.3.1 エラーの特定)

## 参考にする実装
この形を出発点にして、プロジェクトの命名規則・色・余白に合わせて調整してください。

```html
<div class="x-input-mask">
  <div class="x-input-mask__row">
    <label class="x-input-mask__l" for="x-input-mask-tel">携帯電話番号</label>
    <p class="x-input-mask__h" id="x-input-mask-tel-h">数字だけで入力できます。ハイフンは自動で入ります</p>
    <!-- 入力欄の後ろに、まだ埋まっていない書式の「_」を等幅で敷く。飾りなので読み上げから外す -->
    <div class="x-input-mask__f">
      <span class="x-input-mask__g" aria-hidden="true"><span class="x-input-mask__done">090-1234-</span>____</span>
      <input class="x-input-mask__i" id="x-input-mask-tel" type="tel" name="tel" value="090-1234-"
             autocomplete="tel-national" aria-describedby="x-input-mask-tel-h">
    </div>
  </div>
  <div class="x-input-mask__row">
    <label class="x-input-mask__l" for="x-input-mask-exp">カードの有効期限</label>
    <p class="x-input-mask__h" id="x-input-mask-exp-h">月/年 の順に4桁(例: 08/28)</p>
    <div class="x-input-mask__f x-input-mask__f--s">
      <span class="x-input-mask__g" aria-hidden="true"><span class="x-input-mask__done">08/28</span></span>
      <input class="x-input-mask__i" id="x-input-mask-exp" type="text" name="cc-exp" value="08/28"
             inputmode="numeric" autocomplete="cc-exp" aria-describedby="x-input-mask-exp-h">
    </div>
  </div>
</div>
```

```css
/* 貼った先のリセットに頼らないよう、この部品の中だけ border-box にする */
.x-input-mask,
.x-input-mask *:not([class*="fa-"]),
.x-input-mask *:not([class*="fa-"])::before,
.x-input-mask *:not([class*="fa-"])::after {
  box-sizing: border-box;
  /* 貼った先の既定の書体に引きずられないようにする。書体が変わると
     文字の幅と高さが変わり、枠のサイズまでずれる */
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Hiragino Sans", "Noto Sans JP", "Yu Gothic UI", Meiryo, sans-serif;
}

.x-input-mask {
  display: grid;
  gap: 14px;
  width: 270px;
  max-width: 100%;
  color: #1b2028;
}
.x-input-mask__l {
  display: block;
  font-size: 12px;
  font-weight: 700;
}
.x-input-mask__h {
  margin: 2px 0 6px;
  color: #5b6472;
  font-size: 11px;
}
/* 敷く書式と入力欄は、同じ等幅の書体・大きさ・左の余白にする。ずれると「_」と数字が重なる */
.x-input-mask .x-input-mask__g,
.x-input-mask .x-input-mask__i {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
  font-size: 16px;
  letter-spacing: 0.04em;
}
.x-input-mask__f {
  position: relative;
  width: 200px;
  max-width: 100%;
  height: 44px;
  border: 1px solid #7f8a99;
  border-radius: 8px;
  background: #fff;
}
.x-input-mask__f--s {
  width: 110px;
}
.x-input-mask__f:focus-within {
  outline: 2px solid #1d4ed8;
  outline-offset: 1px;
}
.x-input-mask__g {
  position: absolute;
  top: 0;
  left: 0;
  display: flex;
  align-items: center;
  height: 100%;
  padding: 0 12px;
  color: #5b6472;
  white-space: pre;
  pointer-events: none;
}
/* 入力済みの部分は入力欄の文字と重なるので、敷く側では透明にして二重に描かない */
.x-input-mask__done {
  color: transparent;
}
.x-input-mask__i {
  position: relative;
  width: 100%;
  height: 100%;
  padding: 0 12px;
  border: 0;
  border-radius: 8px;
  outline: none;
  background: none;
  color: #1b2028;
}
```

## 出力の約束
- HTML と CSS を分けて出す。JavaScript が要るときは素の JavaScript で書き、UIフレームワークは使わない。
- 参考実装がアイコンに Font Awesome のクラスを使っている場合は、プロジェクトで使っているアイコンかインライン SVG に置き換えてよい。
- 上のアクセシビリティ要件を満たす。満たせない箇所があるときは、理由を添えて先に知らせる。
- 色・角丸・余白は既存のデザイントークンがあればそれを使う。無ければ CSS 変数として切り出す。

使いどころ

  • 電話番号・郵便番号・カードの有効期限(MM/YY)のように、区切り方が決まった値を入れてもらうとき
  • 区切りを見せたほうが桁の打ち間違いに気づきやすいとき

注意点

  • テキストフィールドとの違い: 入力に合わせて区切り文字を足し、書式を整えながら受け取る。形式が決まっていない値にはマスクをかけない
  • 形式を押し付けて入力を拒まない。GOV.UK Design System は電話番号について、空白・ハイフン・括弧を含むなじみのある書き方を受け入れるよう勧めている。ハイフンあり・なし・全角のどれで打たれても、受け取ってから整える
  • マスクは貼り付け・自動入力・日本語入力(IME)の変換中の入力とぶつかりやすい。変換が確定するまでは書き換えず、貼り付けた値は数字だけ取り出してから整える
  • 書き換えるたびにキャレットが末尾へ飛ぶ実装が多い。途中の桁を直したときも、キャレットを打った位置に保つ
  • 書式はプレースホルダーではなく補足文に書く。打ち始めると消えて、どう打つのか分からなくなる

アクセシビリティの要点

  • どんな書式で入るのか、区切りを打つ必要があるかを、ラベルか補足文に言葉で書き aria-describedby で結ぶ(3.3.2 ラベル又は指示)
  • 未入力の桁を示す「_」の飾りは aria-hidden="true" にする。読み上げが「アンダースコア」を何度も読まないようにする
  • autocomplete を付ける(電話番号は tel-national / tel、郵便番号は postal-code、有効期限は cc-exp)。自動入力で入った値もマスクで整える(1.3.5 入力目的の特定)
  • 桁が足りない・範囲外(13月など)のときは、欄を離れたときに何が違うかを文言で伝える(3.3.1 エラーの特定)

作るときに使えるツール

関連するパーツ