タイトルの通りです。
要素の表示非表示はJavaScriptで制御することが多いと思いますが、その際CSSでdisplay: none
を付けたり外したりする方法がよく使われると思います。
Tailwind CSSだとhidden
というクラス名を付け外しするだけでできるので便利ですね。
例: element.classList.toggle('hidden');
<div class="container">
<p>この要素のdisplay: noneを切り替える</p>
</div>
その際、親要素にスタイルを当てている場合、子要素が空のときはそのスタイルを消したい、もしくは親要素自体もdisplay: none
で消したい、という場面は結構あるかと思います。
そこで:empty
の出番です。
.container {
border: 3px double red;
}
.container:empty {
border: none;
}
この際、子要素をdisplay: none
で消したとします。
するとその要素はアクセシビリティツリー上からも消え、ブラウザからも、スクリーンリーダーからも「見えなく」なります。
しかしながら、その要素はDOM上では存在しているため、:empty
は適用されません。
それはそう、と言われればそれまでなんですが、意外と盲点だったので書き留めておきます。
:empty
は CSS の擬似クラスで、子を持たない要素を表します。子とは要素のノードまたは文字列 (ホワイトスペースを含む) です。コメント、処理指示、 CSS の content は要素が空であるかどうかの判断には影響しません。
また、:empty
は改行があっても反映されないので注意が必要です。
<div class="container">
</div>
:empty
を適用させるには
子要素自体を削除するしかないです。
const container = document.querySelector('.container');
container.innerHTML = '';
ただ、要素自体が削除されているので、display: none
の付け外しによる表示非表示のような動作をさせたい場合、どこかに情報を保持しておく必要があります。
const container = document.querySelector('.container');
const originalContent = container.innerHTML;
// 削除
container.innerHTML = '';
// 復元
container.innerHTML = originalContent;
ただ、子要素を削除した後にもう一度上記のJSを実行すると、「そもそも子要素がないよ」と怒られるので、情報の保持、削除、復元は別々の関数で処理する必要があります。
let originalContent = '';
const storeOriginalContent = () => {
const container = document.querySelector('.container');
if (container && !originalContent) {
originalContent = container.innerHTML;
}
};
const deleteContent = () => {
const container = document.querySelector('.container');
if (container) {
container.innerHTML = '';
}
};
const restoreContent = () => {
const container = document.querySelector('.container');
if (container && originalContent) {
container.innerHTML = originalContent;
}
};
// 初回に情報を保持
storeOriginalContent();
// 削除
deleteContent();
// 復元
restoreContent();
display: none
で消すパターンと要素ごと消すパターンの:empty
の挙動の違い
以下のサンプルには
.container {
border: 3px double red;
}
.container:empty {
border: none;
}
的な内容が含まれています。
See the Pen Qiita: Differences in `:empty` Behavior: `display: none` vs. Element Removal by Yoruaki (@yoruaki) on CodePen.
ユーザーの操作に応じて動的に要素の表示非表示を切り替える場合、:empty
は相性が悪そうですね。
どちらかというとサーバーサイドでページを生成する際に、不要な要素を除外する場合などで力を発揮しそうです。
まとめ
ちょっとしたサンプルコードを書いているときに今回の状況に直面したので、別途まとめてみました。
同じような状況に遭遇した方の参考になれば幸いです。
今後も新しい発見を楽しみながら、皆さんと一緒に学びを深めていければと思います。