JavaScript

改行可能なプレースホルダー(placeholder)を独自に作る方法

最終更新日:

テキストボックス、テキストエリアの、入力前に表示されるグレーの文字。HTML5から導入されたplaceholder属性の値で簡単に設定できるものですが、それだと改行をすることはできません。

JavaScriptを用いれば改行して表示することもできるので、その方法について未来の自分に向けてご紹介します。

プレースホルダ―(placeholder)とは?

プレースホルダー(placeholder)は、テキストボックスあるいは(複数行に渡る)エキストエリアにおいて、ユーザーがフォーカスを当てる前からグレーの文字で入力例を示すために用いられているアレです。

SEOに強いAIライティングツール「BringRitera(リテラ)」で
設定されているプレースホルダー

HTML5で導入された仕様であるplaceholder属性で次のように簡単に設定できます。

<textarea placeholder="記述内容"></textarea>

この仕様ができるまでは、開発者により独自に実装されていました。
ただし、placeholder属性による設定だと改行付きで表示させることはできません。

改行付きで表示させるには、独自実装が必要となりますので、その方法についてご紹介します。

ご紹介する独自プレースホルダーの仕様

例えば次の画像のように、改行して入力してください、というようなことを示すのには、改行させたくなるところです。また、Chromeではフォーカスが当たった時点だとplaceholderの文字が消えないのですが、フォーカスが当たった時点で消えた方が分かりやすいように思うので、ここでご紹介するのはそのような仕様とします。

コード

HTML

  1. <div class="multiline-placeholder-wrapper">
  2. <div class="placeholder" data-placeholder="例:\nhttps://www.example.com/page-01/\nhttps://www.example.com/page-02/"></div>
  3. <textarea id="demo" rows="5"></textarea>
  4. </div>
  5. <div class="multiline-placeholder-wrapper">
  6. <div class="placeholder" data-placeholder="例:りんご\nみかん"></div>
  7. <textarea id="demo" rows="5"></textarea>
  8. </div>

CSS

  1. .multiline-placeholder-wrapper {
  2. position: relative;
  3. width: 100%;
  4. }
  5. .placeholder {
  6. position: absolute;
  7. top: 10px;
  8. left: 10px;
  9. color: #C0C0C0;
  10. pointer-events: none;
  11. white-space: pre-wrap;
  12. font-family: inherit;
  13. font-size: 16px;
  14. }
  15. .multiline-placeholder-wrapper.textarea-focused .placeholder,
  16. .multiline-placeholder-wrapper.textarea-notempty .placeholder {
  17. display: none;
  18. }

JavaScript

  1. document.addEventListener('DOMContentLoaded', function() {
  2. const multiPlaceholderWrappers = document.querySelectorAll('.multiline-placeholder-wrapper');
  3. if (multiPlaceholderWrappers) {
  4. multiPlaceholderWrappers.forEach(wrapper => {
  5. const textarea = wrapper.querySelector('textarea');
  6. const placeholder = wrapper.querySelector('.placeholder');
  7. const placeholderContent = placeholder.getAttribute('data-placeholder').replace(/\\n/g, '\n');
  8. placeholder.textContent = placeholderContent;
  9. // 初期状態の処理
  10. if (textarea.value) {
  11. wrapper.classList.add('textarea-notEmpty');
  12. placeholder.style.display = 'none';
  13. } else {
  14. wrapper.classList.remove('textarea-notEmpty');
  15. placeholder.style.display = 'block';
  16. }
  17. // フォーカス時の処理
  18. textarea.addEventListener('focus', function() {
  19. wrapper.classList.add('textarea-focused');
  20. placeholder.style.display = 'none';
  21. });
  22. // フォーカスが外れた時の処理
  23. textarea.addEventListener('blur', function() {
  24. if (!textarea.value) {
  25. wrapper.classList.remove('textarea-focused');
  26. placeholder.style.display = 'block';
  27. }
  28. });
  29. // 入力内容の変更時の処理
  30. textarea.addEventListener('input', function() {
  31. if (textarea.value) {
  32. wrapper.classList.add('textarea-notEmpty');
  33. placeholder.style.display = 'none';
  34. } else {
  35. wrapper.classList.remove('textarea-notEmpty');
  36. placeholder.style.display = 'block';
  37. }
  38. });
  39. });
  40. }
  41. });

コードの解説

  • multiline-placeholder-wrappertextareaを囲い、textareaと同じ階層にplaceholderを設置。そのplaceholderの位置をmultiline-placeholder-wrapperに対する絶対位置指定にします。
  • フォーカスありなしと、入力ありなしでmultiline-placeholder-wrapperのクラス名を動的に変えることで、プレースホルダーの表示を制御します。
  • DOMContentLoadedでDOM読み込み後に発火としないと、デフォルトで入力がある状態の場合に、プレースホルダーが表示されてしまうケースがあります。
  • document.querySelectorAllmultiline-placeholder-wrapperのクラス名がついた要素を全て拾うので、画面内に複数あっても動きます。

アクセシビリティに関する注意点

placeholderを使えばテキストエリアにフォーカスが当たった時点でスクリーンリーダーで読み上げが可能なので、アクセシビリティについては、placeholder属性を使った方が標準で担保されます。
この方法を用いる場合、placeholderだけに説明を任せないようにするか、aria-labelを用いるなどの考慮が必要です。

まとめ

この実装内容についてみたい方はBringRitera(リテラ)のフリープランに登録してお試しください。