CSS 가상 클래스와 가상 요소 차이
CSS의 :hover와 ::before는 이름과 문법이 비슷하다.
하지만 하나는 요소의 상태를 고르고, 다른 하나는 요소의 특정 부분이나 생성된 박스를 고른다.
가상 클래스와 가상 요소를 구분하면 선택자를 읽는 순서도 분명해진다.
선택 대상의 차이
가상 클래스는 문서 트리만으로 표현하기 어렵거나 외부 상태에 따라 달라지는 요소를 선택한다.
마우스 포인터가 올라간 요소를 고르는 :hover, 키보드 포커스가 드러나야 하는 요소를 고르는 :focus-visible, 첫 번째 자식을 고르는 :first-child가 여기에 속한다.
가상 요소는 선택한 요소의 특정 부분이나 문서 트리에 없는 별도의 대상을 선택한다.
첫 줄을 고르는 ::first-line, 목록 표시를 고르는 ::marker, 내용 앞뒤에 박스를 만드는 ::before와 ::after가 대표적이다.
둘 다 HTML에 class를 추가하지 않고 대상을 고를 수 있다.
일반 class와 id의 역할은 HTML id와 class 차이에서 따로 정리했다.
콜론 문법
가상 클래스는 콜론 하나로 시작한다.
가상 요소는 콜론 두 개로 시작한다.
a:hover {
text-decoration-thickness: 2px;
}
p::first-line {
font-weight: 700;
}과거 CSS 문법과의 호환 때문에 브라우저는 :before, :after, :first-line, :first-letter의 단일 콜론 표기도 받아들인다.
새 코드에서는 역할을 바로 구분할 수 있도록 ::before처럼 이중 콜론을 쓰는 편이 좋다.
상태 선택
가상 클래스는 사용자의 입력 상태를 스타일에 반영할 때 자주 사용한다.
.button:hover {
background: #e7f0ff;
}
.button:focus-visible {
outline: 3px solid #0969da;
outline-offset: 2px;
}:hover만 사용하면 터치 기기나 키보드 사용자가 같은 변화를 확인하기 어렵다.
클릭 가능한 요소의 중요한 상태는 포커스 스타일도 함께 제공해야 한다.
구조 상태에도 같은 문법을 사용한다.
예를 들어 li:first-child는 목록의 첫 번째 li 요소 자체를 선택한다.
부분과 생성 콘텐츠
가상 요소는 HTML에 별도 요소를 추가하지 않고 시각적인 부분을 꾸밀 때 유용하다.
<p class="notice">저장되었습니다.</p>.notice::before {
display: inline-block;
width: 0.5em;
height: 0.5em;
margin-right: 0.5em;
border-radius: 50%;
background: #1a7f37;
content: '';
}이 예시의 ::before는 의미를 추가하지 않는 장식용 점이다.
스크린 리더에 전달되어야 하는 성공 메시지는 HTML 텍스트에 남아 있다.
content로 넣은 텍스트는 보조 기술에서 일관되게 읽힌다고 보장할 수 없다.
가격, 상태, 버튼 이름처럼 이해에 필요한 정보는 가상 요소에만 두면 안 된다.
결합과 주의점
가상 클래스와 가상 요소는 한 선택자에서 함께 사용할 수 있다.
.link:hover::after,
.link:focus-visible::after {
content: ' →';
}이 선택자는 먼저 hover 또는 focus-visible 조건에 맞는 .link를 고른 다음 그 요소의 ::after를 꾸민다.
이처럼 가상 요소를 다른 단순 선택자 뒤에 두면 상태의 대상과 꾸밀 부분을 구분하기 쉽다.
::before와 ::after는 content의 계산값이 none이면 생성되지 않는다.
또한 <img>처럼 내용이 외부 리소스로 대체되는 요소에는 기대한 방식으로 적용되지 않는다.
명시도 계산에서도 둘은 다르다.:hover 같은 일반 가상 클래스는 class 선택자 항목으로 계산되고, 가상 요소는 type 선택자 항목으로 계산된다.
다만 :where()의 명시도는 0이고 :is(), :not(), :has()는 인자 목록에서 가장 높은 명시도를 사용하므로 함수형 가상 클래스의 예외 규칙을 따로 확인해야 한다.
전역 box-sizing에서 일반 요소와 가상 요소를 함께 선택하는 이유는 CSS box-sizing content-box와 border-box 차이에서 이어서 볼 수 있다.
참고 자료









