HTML5 Form Validation の ballooon をカスタマイズ

はじめに

HTML5 Form Validation は HTML5からサポートされているフロント側のバリデーション機能で、特にJavaScriptのライブラリを使用しなくても input element の属性に応じてフロント側のバリデーションを行ってくれます。

動作イメージ

警告バルーンのカスタマイズ

実際にスタイルの変更を行っていきたいと思います。警告メッセージの上書きもできるようですが、ブラウザが出力してくれるメッセージで全く問題ないことも多いと思うので今回は割愛します。

スタイルのカスタマイズの方法としてはCSSのみでの変更は難しく、JavaScriptを用いてデフォルトの警告の表示を出ないようにし、submit イベントが発生したときに invalid な input elemet を取得。
その input elemet の兄弟要素として予め配置しておいたballonの要素に警告メッセージを追加して表示する、
のような流れで実装してみたいと思います。

htmlは以下のような感じ

<form class="form" method="post" action="/">
  <div class="form-item">
    <input type="text" required="" minlength="10">
    <p class="error-message"></p>
  </div>
  <div class="form-item">
    <select required="">
      <option value="">選択して下さい</option>
      <option value="1">選択肢1</option>
      <option value="2">選択肢2</option>
    </select>
    <p class="error-message"></p>
  </div>
  <div class="form-item">
    <button class="submit-button">実行</button>
  </div>
</form>
HTML

cssは以下のような感じ

.form-item {
  width: 320px;
}
.error-message {
  background-color: #e12350;
  color: #fff; 
  font-size: 12px;
  padding: 4px;
  display: none;
}
.error-message.-show {
  display: block;
}
CSS

jsは以下

var form = document.querySelector('.form');
var submitButton = document.querySelector('.submit-button');

submitButton.addEventListener('click', function (e) {
  var invalids = form.querySelectorAll(':invalid');
  if (0 < invalids.length) {
    e.preventDefault();
    for (var i = 0; i < invalids.length; i++) {
      (function (idx) {
        var invalid = invalids[idx];
        var errorMessage = invalid.parentNode.querySelector('.error-message');
        errorMessage.innerText = invalid.validationMessage;
        errorMessage.classList.add('-show');
        invalid.addEventListener('change', function f() {
          this.removeEventListener('change', f);
          errorMessage.classList.remove('-show');
        });
      })(i);
    }
  }
});
JavaScript

完成イメージ

submitボタンををクリックしたときに、form内のinvalidな要素を取得して一つでもあれば妥当性がないとみなします。
妥当性がなかった場合はprevendDefaultでまずブラウザの実装によって処理される既定のアクションをとめてデフォルトで表示される警告のバルーンなどを出ないようにします。
その後にinvalidな要素を取得してinvalidな要素に対しては、validationMessageを取得後兄弟要素のバルーンを表示するようにします。
さらにchangeイベントも追加してinput elementの変更を検知。変更があればバルーンを非表示にする。
このような処理で最低限のバルーンの動きは実装できるかと思います。

まとめ

バルーンのスタイル変更の最低限の動作は以上のような形で実現できるかと思います。
後はより良い使いやすさを各自で拡張していければと。