JavaScript
改行可能なプレースホルダー(placeholder)を独自に作る方法
テキストボックス、テキストエリアの、入力前に表示されるグレーの文字。HTML5から導入されたplaceholder属性の値で簡単に設定できるものですが、それだと改行をすることはできません。
JavaScriptを用いれば改行して表示することもできるので、その方法について未来の自分に向けてご紹介します。
プレースホルダ―(placeholder)とは?
プレースホルダー(placeholder)は、テキストボックスあるいは(複数行に渡る)エキストエリアにおいて、ユーザーがフォーカスを当てる前からグレーの文字で入力例を示すために用いられているアレです。
HTML5で導入された仕様であるplaceholder属性で次のように簡単に設定できます。
<textarea placeholder="記述内容"></textarea>
この仕様ができるまでは、開発者により独自に実装されていました。
ただし、placeholder属性による設定だと改行付きで表示させることはできません。
改行付きで表示させるには、独自実装が必要となりますので、その方法についてご紹介します。
ご紹介する独自プレースホルダーの仕様
例えば次の画像のように、改行して入力してください、というようなことを示すのには、改行させたくなるところです。また、Chromeではフォーカスが当たった時点だとplaceholderの文字が消えないのですが、フォーカスが当たった時点で消えた方が分かりやすいように思うので、ここでご紹介するのはそのような仕様とします。
コード
HTML
<div class="multiline-placeholder-wrapper">
<div class="placeholder" data-placeholder="例:\nhttps://www.example.com/page-01/\nhttps://www.example.com/page-02/"></div>
<textarea id="demo" rows="5"></textarea>
</div>
<div class="multiline-placeholder-wrapper">
<div class="placeholder" data-placeholder="例:りんご\nみかん"></div>
<textarea id="demo" rows="5"></textarea>
</div>
CSS
.multiline-placeholder-wrapper {
position: relative;
width: 100%;
}
.placeholder {
position: absolute;
top: 10px;
left: 10px;
color: #C0C0C0;
pointer-events: none;
white-space: pre-wrap;
font-family: inherit;
font-size: 16px;
}
.multiline-placeholder-wrapper.textarea-focused .placeholder,
.multiline-placeholder-wrapper.textarea-notempty .placeholder {
display: none;
}
JavaScript
document.addEventListener('DOMContentLoaded', function() {
const multiPlaceholderWrappers = document.querySelectorAll('.multiline-placeholder-wrapper');
if (multiPlaceholderWrappers) {
multiPlaceholderWrappers.forEach(wrapper => {
const textarea = wrapper.querySelector('textarea');
const placeholder = wrapper.querySelector('.placeholder');
const placeholderContent = placeholder.getAttribute('data-placeholder').replace(/\\n/g, '\n');
placeholder.textContent = placeholderContent;
// 初期状態の処理
if (textarea.value) {
wrapper.classList.add('textarea-notEmpty');
placeholder.style.display = 'none';
} else {
wrapper.classList.remove('textarea-notEmpty');
placeholder.style.display = 'block';
}
// フォーカス時の処理
textarea.addEventListener('focus', function() {
wrapper.classList.add('textarea-focused');
placeholder.style.display = 'none';
});
// フォーカスが外れた時の処理
textarea.addEventListener('blur', function() {
if (!textarea.value) {
wrapper.classList.remove('textarea-focused');
placeholder.style.display = 'block';
}
});
// 入力内容の変更時の処理
textarea.addEventListener('input', function() {
if (textarea.value) {
wrapper.classList.add('textarea-notEmpty');
placeholder.style.display = 'none';
} else {
wrapper.classList.remove('textarea-notEmpty');
placeholder.style.display = 'block';
}
});
});
}
});
コードの解説
multiline-placeholder-wrapper
でtextarea
を囲い、textarea
と同じ階層にplaceholder
を設置。そのplaceholder
の位置をmultiline-placeholder-wrapper
に対する絶対位置指定にします。- フォーカスありなしと、入力ありなしで
multiline-placeholder-wrapper
のクラス名を動的に変えることで、プレースホルダーの表示を制御します。 DOMContentLoaded
でDOM読み込み後に発火としないと、デフォルトで入力がある状態の場合に、プレースホルダーが表示されてしまうケースがあります。document.querySelectorAll
でmultiline-placeholder-wrapper
のクラス名がついた要素を全て拾うので、画面内に複数あっても動きます。
アクセシビリティに関する注意点
placeholderを使えばテキストエリアにフォーカスが当たった時点でスクリーンリーダーで読み上げが可能なので、アクセシビリティについては、placeholder属性を使った方が標準で担保されます。
この方法を用いる場合、placeholderだけに説明を任せないようにするか、aria-labelを用いるなどの考慮が必要です。
まとめ
この実装内容についてみたい方はBringRitera(リテラ)のフリープランに登録してお試しください。