Help us understand the problem. What is going on with this article?

IE9でvalueを使わずにplacholderを表示する

More than 3 years have passed since last update.

IE9 向けに placeholder を提供するライブラリをいくつか試してみたものの、どうもしっくり来るものがなく、自前で実装したのでメモ。
ただし、やっつけ実装なので、あくまでも実現方法の参考として見て頂きたい。

試したライブラリ

既存ライブラリのイマイチポイント 1

  • ページをリロードすると placeholder が表示されなくなる
  • placeholder と同じテキストを入力できない (勝手に placeholder と判断されて削除される)
  • 何も入力していない状態で submit すると placeholder の内容が submit される

実装コード

$(function() {
  var isPlaceholderSupported = (function() {
    return 'placeholder' in document.createElement('input');
  }());

  if (isPlaceholderSupported) {
    return;
  }
  $('[placeholder]')
    .wrap('<div style="display:inline-block;position:relative"></div>')
    .parent()
      .on('mouseover', function() {
        var parent = $(this);
        var elm = parent.find('span');
        var input = parent.find('[placeholder]');
        elm.css('cursor', input.css('cursor'));
      })
      .end()
    .each(function() {
      var elm = $(this);
      var text = elm.attr('placeholder');
      var val = elm.val();
      var paddingTop = Number(elm.css('padding-top').replace('px', ''));
      var paddingLeft = Number(elm.css('padding-left').replace('px', ''));
      var borderTop = Number(elm.css('border-top-width').replace('px', ''));
      var borderLeft = Number(elm.css('border-left-width').replace('px', ''));

      $('<span style="color:#999;display:inline-block;position:absolute"></span>')
        .text(text)
        .css({
          top: paddingTop + borderTop,
          left: paddingLeft + borderLeft,
          visibility: (val === '' ? 'visible' : 'hidden')
        })
        .insertBefore(elm);
    })
    .on('focus', function() {
      $(this).prev().css('visibility', 'hidden');
    })
    .on('blur', function() {
      var elm = $(this);
      if (elm.val() === '') {
        elm.prev().css('visibility', 'visible');
      }
    })
    .prev()
      .on('mousedown', function() {
        var elm = $(this);
        var input = elm.next();
        if (input.prop('disabled') || input.prop('readonly')) {
          return;
        }
        elm.css('visibility', 'hidden');
        input.focus();
        return false;
      })
    ;
});

コード適用時のHTMLイメージ:

適用前
<input type="text" placeholder="値を入力してください" />
適用後
<div style="display:inline-block; position:relative">
  <span style="left:2px; top:3px; color:#999; display:inline-block; position:absolute; cursor:auto">値を入力してください</span>
  <input type="text" />
</div>

工夫ポイント

  • placeholder をサポートしているブラウザではそちらを使用するようにしている。
  • value を使う代わりに span を input 上に重ねて表示する方式のため、リロードや submit しても input の内容に影響を与えない。
  • placeholder が input の内容と同じ位置に表示されるよう、input の padding、border を考慮している。
  • input と同じカーソルを placeholder に設定するようにしている。2
  • placeholder にフォーカスが当たらないよう、placeholder の onmousedown で input にフォーカスを設定している。

やっつけポイント

  • jQuery に依存している。3
  • スタイルが style 属性にハードコーディングされている。4
  • input を勝手に div で囲むため、場合によってはスタイルが崩れる。5
  • input と placeholder のスタイル (フォントサイズ等) が微妙に違う6
  • 毎回、input や placeholder の Element を取得している。(prev() とか) 7
  • コードのコピペが多い (prev() とか placeholder の表示切替部分とか) 8
  • input ごとにイベントを登録している。 9

結論

IE9 をサポートしなくて良いように根回ししましょう。


  1. 具体的にどれがどのライブラリに該当したかは失念 

  2. Bootstrap を使っていると、input を無効にした場合のスタイルが用意されているので 

  3. 実装が楽だったので…。 頑張ればネイティブメソッドのみでも実装できるはず 

  4. ちゃんとクラスを用意して、そちらにスタイルを適用するべきでしょうね 

  5. 適用先の HTML にあわせて個別カスタマイズしてもらうということで… 

  6. これも個別カスタマイズで吸収ということで… 

  7. きちんと placeholder 用のクラスを用意して、そこに保持した方が良いかと 

  8. これもきちんとオブジェクト指向すれば解消できるはず 

  9. $(document).on('イベント', '要素', ハンドラ) を使った方が省エネのはず 

murank
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away