2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

子要素を display: none しても :empty は効かない

Last updated at Posted at 2025-04-07

タイトルの通りです。

要素の表示非表示はJavaScriptで制御することが多いと思いますが、その際CSSでdisplay: noneを付けたり外したりする方法がよく使われると思います。

Tailwind CSSだとhiddenというクラス名を付け外しするだけでできるので便利ですね。
例: element.classList.toggle('hidden');

HTML
<div class="container">
    <p>この要素のdisplay: noneを切り替える</p>
</div>

その際、親要素にスタイルを当てている場合、子要素が空のときはそのスタイルを消したい、もしくは親要素自体もdisplay: noneで消したい、という場面は結構あるかと思います。

そこで:emptyの出番です。

CSS
.container {
    border: 3px double red;
}

.container:empty {
    border: none;
}

この際、子要素をdisplay: noneで消したとします。
するとその要素はアクセシビリティツリー上からも消え、ブラウザからも、スクリーンリーダーからも「見えなく」なります。

しかしながら、その要素はDOM上では存在しているため、:emptyは適用されません。

それはそう、と言われればそれまでなんですが、意外と盲点だったので書き留めておきます。

:empty は CSS の擬似クラスで、子を持たない要素を表します。子とは要素のノードまたは文字列 (ホワイトスペースを含む) です。コメント、処理指示、 CSS の content は要素が空であるかどうかの判断には影響しません。

また、:emptyは改行があっても反映されないので注意が必要です。

これだと :empty は反映されない
<div class="container">
</div>

:emptyを適用させるには

子要素自体を削除するしかないです。

JavaScript
const container = document.querySelector('.container');

container.innerHTML = '';

ただ、要素自体が削除されているので、display: noneの付け外しによる表示非表示のような動作をさせたい場合、どこかに情報を保持しておく必要があります。

JavaScript
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は相性が悪そうですね。
どちらかというとサーバーサイドでページを生成する際に、不要な要素を除外する場合などで力を発揮しそうです。

まとめ

ちょっとしたサンプルコードを書いているときに今回の状況に直面したので、別途まとめてみました。
同じような状況に遭遇した方の参考になれば幸いです。

今後も新しい発見を楽しみながら、皆さんと一緒に学びを深めていければと思います。

2
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?