:empty {
    /* ... */
}
p {
    background-color: yellow;
    height: 1em;
}

p:empty {
    border: 3px solid red; /* 요소에 3px 두께의 빨간색 테두리 지정 */
}
<p></p>
<p><!-- comment --></p>
실제 적용된 모습
<!-- 모든 띄어쓰기는 공백임 -->
<p> </p>
<p>     </p>

<!-- 공백을 나타내는 특수 문자도 공백임 -->
<p>&nbsp;</p> <!-- &nbsp;는 줄바꿈되지 않는 공백을 나타내는 특수 문자-->

<!-- 소스 코드 서식에서 줄바꿈도 공백임 -->
<p>
</p>

<!-- 텍스트나 자식 요소가 없어야 함 -->
<p>텍스트</p>
<p><span></span></p>
실제 적용된 모습 p:empty로 지정한 border: 3px solid red(요소에 3px 두께의 빨간색 테두리)가 모두 적용되지 않습니다.
p {
    background-color: yellow;
}

p::before { /* CSS로 생성된 콘텐츠 */
    content: "Hello";
}

p:empty {
    border: 3px solid red; /* 요소에 3px 두께의 빨간색 테두리 지정 */
}
p {
    background-color: yellow;
}

p::before { /* CSS로 생성된 콘텐츠 */
    content: "Hello";
}

p:empty {
    border: 3px solid red; /* 요소에 3px 두께의 빨간색 테두리 지정 */
}
<!-- 내용이 빈 <p> 요소 -->
<p></p>

<!-- 내용이 비지 않은 <p> 요소 -->
<p>환영합니다.</p>
실제 적용된 모습 CSS로 생성된 콘텐츠는 :empty의 선택 조건에는 아무런 영향을 주지 않습니다.
hr:empty {
    border: 3px solid red; /* 요소에 3px 두께의 빨간색 테두리 지정 */
}
input:empty {
    background-color: yellow;
}
<hr>
<input>
실제 적용된 모습 자식 콘텐츠가 없으므로 :empty 가상 클래스 선택자에 선택됩니다.