本文へスキップ

パスワード表示切替

目のアイコンをクリックするとパスワードの表示・非表示を切り替えられる。入力ミスを確認しやすい。

ENGLISH

Password Visibility Toggle

  • JS
83基本のUI部品 / フォーム入力 の一覧 →

プレビュー

入力

操作実際に入力して試せます。

使いどころ

ログインフォームやアカウント作成フォームのように、ユーザーが自分で入力した文字列を確認したい場面に向く。特にモバイルでの入力ミスは訂正コストが高いため、目のアイコンで表示に切り替えられる本実装は入力の信頼性を上げる効果が大きい。逆に、他人の画面を覗き見される可能性が高い共有端末や公共の場での利用が前提のプロダクトでは、デフォルトで表示に倒す運用は避け、あくまでユーザー自身の任意操作(このボタン)でのみ一時的に表示させる今の設計を保つべきである。また、確認コードやワンタイムパスワードのように元々見える前提の入力欄には表示切替自体が不要で、typeを最初からtextにしておく方がボタンを1つ減らせて簡潔になる。パスワード生成・強度チェックの機能とは独立した部品なので、それらと組み合わせる場合は別コンポーネントとして追加する設計になる。

仕組み

input要素のtype属性を"password"と"text"の間で直接書き換えるだけの実装で、状態はDOMのtype属性そのものが単一の情報源になっている(専用のJS変数を持たない)。ボタンクリックのたびにpwInput.type === "password"を判定し、目の開いたアイコン(eye-on)と閉じたアイコン(eye-off)をstyle.displayの"none"切り替えで入れ替え、同時にaria-labelを"パスワードを表示"⇔"パスワードを隠す"へ書き換える。2つのsvgアイコンを両方DOMに置いておき表示/非表示を切り替える方式は、アイコンを1つだけ用意してpathを書き換えるより実装が単純だが、常に2つ分のsvgノードがDOMに存在し続けるトレードオフがある。inputにはautocomplete="current-password"が指定されており、ブラウザのパスワードマネージャーとの連携(候補表示・自動入力)を妨げない配慮がされている。

実装の注意

type属性を書き換える実装は、ブラウザによってはtype変更時にカーソル位置や選択範囲がリセットされることがある(Safari系で報告例がある挙動)。入力途中の文字列の中間でこのボタンを押すと、カーソルが末尾に飛んで続きを打ちにくくなる場合があるため、厳密に対応するならselectionStart/selectionEndを変更前に保存し、type変更後に再設定する処理を足すとよい。次に、type="text"に切り替えている間はブラウザの自動入力候補や画面録画・肩越しの覗き見に対して無防備になるため、フォームを離れる(blur)タイミングやモーダルを閉じるタイミングでtype="password"へ戻す保険を入れる実装も検討に値する。現状はクリックし続けない限り表示のままなので、確認が終わったら手動で戻す前提のUIになっている点は利用者への説明(ヒント文言)でも補うとよい。

アクセシビリティ

ボタンのaria-labelがクリックのたびに"パスワードを表示"⇔"パスワードを隠す"へ動的に書き換えられており、スクリーンリーダー利用者にも次に押すとどうなるかが正しく伝わる設計になっている。ボタンはbutton要素にtype="button"を明示しているため、フォーム内でsubmitとして誤って扱われることもない(button要素はtype省略時にsubmit扱いになる仕様への配慮が既にされている)。focus-visibleに対するoutlineも用意されており、キーボード操作時の可視性は確保できている。ただし、表示/非表示が切り替わったこと自体をaria-live等で音声フィードバックする仕組みは無く、aria-labelの変化はフォーカスが当たっている要素でなければ次にその要素にフォーカスが移るまで読み上げられない。切替直後にボタンからフォーカスを外さない実装なので実用上の影響は小さいが、厳密には触れておくべき点である。

調整して使う

調整しやすいのは3つ。まずアイコンの出し分け方式で、現状は2つのsvgをDOMに並べてdisplayで切り替えているが、1つのsvgのd属性(パス)をJSで書き換える方式に変えればDOMノード数を減らせる。次に自動的にpasswordへ戻すタイミングで、一定時間(例えば10秒)経過後に自動で非表示へ戻すタイマーを足すと、表示したまま画面を離れてしまうケースの安全性が上がる(ただしタイマー中に読み終わらないと再度押す手間が増えるトレードオフがある)。最後に、確認用パスワード欄が並ぶ登録フォームでは、2つの入力欄それぞれに個別のトグルを付けるか、1つの操作で両方まとめて表示/非表示にするかという設計判断が生じる。個別トグルの方が誤操作は少ないが、まとめて切り替えられる方が確認の手間は減るため、フォームの複雑さで選ぶとよい。

コード(コピーして使えます)

<div class="pw-wrap">
  <label class="pw-label" for="pw-input">パスワード</label>
  <div class="pw-field">
    <input
      id="pw-input"
      class="pw-input"
      type="password"
      value="MySecret123"
      autocomplete="current-password"
    />
    <button class="pw-toggle" id="pw-btn" type="button" aria-label="パスワードを表示">
      <svg class="eye-icon" id="eye-on" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
      <svg class="eye-icon" id="eye-off" style="display:none" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94"/><path d="M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19"/><line x1="1" y1="1" x2="23" y2="23"/></svg>
    </button>
  </div>
  <p class="pw-hint">ボタンで表示/非表示を切替</p>
</div>

タグ

同じカテゴリ「フォーム入力」のほかのパーツ

関連パーツ