[CSS] CSS 가상 요소와 가상 클래스

jjee·2025년 8월 14일
0

CSS

목록 보기
9/24

썸네일

CSS 가상요소와 가상클래스

CSS에서는 기본 선택자 외에도 특별한 상태나 위치를 지정할 수 있는 가상 요소가상 클래스를 제공한다.
가상 요소와 가상 클래스에 대해 알아보자.

가상 요소(Pseudo-elements)

가상 요소는 말 그대로 가상의 요소를 만드는 것이다.
선택한 요소의 특정 부분에 스타일을 적용할 수 있게 해주며, 이중 콜론(::)을 사용하여 표현한다.

::before와 ::after

::before::after는 선택한 요소의 앞,뒤에 새로운 요소를 만들어 콘탠츠를 추가할 수 있도록 도와준다.
content 속성을 필수로 작성해야 한다.

p::before {
  content: '『';
  color: #3498db;
  font-size: 1.2em;
  margin-right: 5px;
}
 
p::after {
  content: '』';
  color: #3498db;
  font-size: 1.2em;
  margin-left: 5px;
}

주로 장식적인 요소를 추가하거나 기능적인 목적으로 사용되며, img, br, input에는 사용할 수 없다.

만약 이미지를 추가하고 싶다면 display값과 background, width, height 등의 속성을 함께 작성하여 원하는 위치에 배치할 수 있다.

::marker

::marker는 리스트 아이템의 마커를 스타일링 할 수 있게 해주는 가상요소이다.
박스 모델의 속성인 background, border, padding은 적용되지 않는다.

ul li::marker {
  content: '✦';
  color: #e74c3c;
  font-size: 1.2em;
}

::placeholder

::placeholder는 input 태그나 textarea의 placeholder 텍스트에 스타일을 적용할 수 있게 해준다.

input::placeholder {
  font-size: 14px;
}
 
textarea::placeholder {
  font-size: 16px;
  font-style: italic;
}
 

가상 클래스(Pseudo-class selectors)

가상 클래스 선택자는 요소의 특정 상태를 선택할 수 있게 해주며 콜론(:)을 사용하여 표현한다.

동적 가상 클래스 선택자

사용자의 동작에 따라 변화하는 상태를 선택할 수 있다.

:link는 아직 방문하지 않은 링크를 선택한다.

a:link {
  color: blue;
  text-decoration: none;
}

:visited

:visited는 이미 방문한 링크를 선택한다.

a:visited {
  color: red;
  text-decoration: none;
}

:hover

:hover는 마우스 포인터가 올라간 요소를 선택한다.

a:hover {
  background-color: yellow;
}

:active

:active는 마우스로 클릭하고 있는 요소를 선택한다.

a:active {
  background-color: green;
  color: white;
}

:focus

:focus는 현재 초점을 가진 요소를 선택한다.

a:focus {
  border: 1px solid blue;
}

구조적 가상 클래스 선택자

문서 구조 내에서 요소의 위치에 따라 선택할 수 있다.

:first-child와 :last-child

:first-child는 형제 요소 그룹 중 첫 번째 요소, :last-child는 마지막 요소를 선택한다.

li:first-child {
  color: red;
}
li:last-child {
  color: blue;
}

body의 직계 자손의 경우 :first-child 선택자는 사용가능하지만, :last-child 선택자는 적용되지 않는다.

<!-- index.html -->
<body>
  <p>first-child</p>
  <p>last-child</p>
</body>
/* style.css */
/* 적용 o */
body > :first-child {
	color: red;
}	 
/* 적용 x */
body > :last-child {
	color: red;
}

:nth-child

부모 요소 내의 모든 자식 요소 중에서 지정된 순서에 있는 요소를 선택한다.
이 선택자는 요소의 타입과 관계없이 순서만 고려한다.

/* 두 번째 자식 요소 선택 */
div :nth-child(2) {
  color: red;
}

:nth-child() 선택자는 괄호 안에 다양한 형태의 값을 사용할 수 있다.

  • 정수값: 특정 순서의 요소를 선택
  • 키워드
    odd: 홀수 번째 요소 선택
    even: 짝수 번째 요소 선택
  • 수식: an+b 형태의 수식 사용 가능 (여기서 n은 0부터 시작하는 정수, a와 b는 정수값)
  • 음수값: 요소의 뒷부분이나 특정 범위의 요소들을 선택할 때 유용
    예: :nth-child(-n+3) 처음 3개 요소 선택

:nth-of-type

부모 요소 내에서 같은 타입의 형제 요소 중 지정된 순서에 있는 요소를 선택한다.
:nth-child와는 다르게 요소의 타입을 고려하여 순서를 계산한다.

<!-- index.html -->
<div>
  <h2>첫 번째 제목</h2>
  <p>첫 번째 문단</p>
  <h2>두 번째 제목</h2>
  <p>두 번째 문단</p>
</div>
/* style.css */
p:nth-of-type(2) {
  color: green;
}

:only-of-type

동일한 유형의 형제가 없는, 형제 요소 중 유일하게 사용된 태그를 선택한다.

<!-- index.html -->
<div>
  <p>유일한 문단</p>
  <h2>첫 번째 제목</h2>
  <h2>두 번째 제목</h2>
</div>
/* style.css */
p:only-of-type {
  color: blue;
}
 
/* h2는 유일하지 않아서 적용되지 않음. */
h2:only-of-type {
  color: blue;
}

:not

부정 선택자로, 특정 선택자를 제외한 요소를 선택한다.

<!-- index.html -->
<div>
  <p>유일한 문단</p>
  <h2>첫 번째 제목</h2>
  <h2>두 번째 제목</h2>
</div>
/* style.css */
/* li 중 첫번째가 아닌 li */
li:not(:first-child) {
  list-style-type: decimal;
}

:is()

여러 개의 선택자를 한꺼번에 지정할 수 있다.
:is()는 여러 개의 선택자를 지정할 때 사용한다.

<!-- index.html -->
<h1><a>hello</a></h1>
<h2><a>hello</a></h2>
<h3><a>hello</a></h3>
<h4><a>hello</a></h4>
/* style.css */
:is(h1, h2, h3) a {
  color: blue;
}

과거에는 위의 코드와 같이 선택하려면 그룹 선택자를 사용해야 했다.

/* 과거 코드 */
h1 a,
h2 a,
h3 a {
  color: blue;
}

:where()

:where():is()와 유사하지만, 우선순위가 낮다.

<!-- index.html -->
<h1><a>hello</a></h1>
<h2><a>hello</a></h2>
<h3><a>hello</a></h3>
<h4><a>hello</a></h4>
/* style.css */
:is(h1, h2) a {
  color: blue;
}
:where(h1, h2, h3) a {
  color: red;
}

이 우선순위가 낮다는 점은 장점이 되기도 한다.
스타일 재정의가 필요한 상황에서 매우 유용하게 사용할 수 있다.
예를 들어, 기본 스타일을 정의하면서도 필요한 경우 쉽게 재정의할 수 있도록 도와준다.

/* 기본 스타일 - 낮은 우선순위 */
:where(button, .btn, [type='submit']) {
  padding: 0.5em 1em;
  background-color: #e0e0e0;
  border: 1px solid #ccc;
}
 
/* 특정 컨테이너의 버튼에 다른 스타일 적용 - 쉽게 재정의 가능 */
.form-container button {
  background-color: #0066cc;
  color: white;
}

위의 코드에서 만약 :is()를 사용했다면, 두 번째 선택자를 더 구체적으로 만들어야 재정의가 가능하다.

:has()

:has()는 2022년에 도입된 의사 클래스로, 특정 요소가 자식 요소를 포함하고 있는지를 검사할 수 있게 해준다.
다른 요소 안에 특정 요소가 포함되어 있는지 여부에 따라 스타일을 적용할 수 있어 매우 유용하다.

<!-- index.html -->
<div>
  <p>lorem ipsum</p>
</div>
<div>
  <a href="#">click me</a>
</div>
/* style.css */
div:has(a) {
  background-color: lightblue;
}

위와 같이 특정 요소가 자식으로 링크를 포함하고 있는 경우에만 스타일을 적용하고 싶을 때 사용할 수 있다.

그 외에도 img 태그가 포함된 값만 다르게 설정한다거나(:has(img)), 필수 키워드가 있는 라벨만 강조 하거나(:has(.required)), :not() 가상 클래스를 함께 사용하여 빈 목록을 표시 방법을 설정하는 등(:not(:has(li)))의 다양한 스타일링이 가능해졌다.

고급 포커스 선택자

:focus-visible

:focus와 유사하다.
:focus는 포커스된 요소에 항상 적용되고, :focus-visible은 주로 키보드를 사용하여 페이지를 탐색할 때나 스크립트를 통해 포커스가 관리될 때 활성화된다.
일반적으로 마우스나 터치 인터페이스를 사용하여 요소에 물리적으로 포커스를 설정할 때는 사용자가 이미 자신이 어떤 요소를 선택했는지 알고 있기 때문에 :focus-visible이 활성화되지 않는다.

/* Focus 스타일 */
.btn:focus {
  outline: none;
  box-shadow: 0 0 0 3px rgba(66, 153, 225, 0.5);
}
 
/* Focus-visible 스타일 */
.btn:focus-visible {
  outline: none;
  border-color: dodgerblue;
  box-shadow: 0 0 0 3px rgba(66, 153, 225, 0.5);
}

일부 브라우저에서는 마우스 클릭으로도 :focus-visible이 트리거될 수 있다.

:focus-within

요소 또는 그 자식 요소가 포커스를 받았을 때 적용된다.

div:focus-within {
  background-color: lightblue;
  border-color: cornflowerblue;
}
 
label {
  display: block;
  margin-bottom: 5px;
}
 
input {
  padding: 5px;
  border: 1px solid #ccc;
  width: 100%;
}

상태 관련 선택자

:enabled

활성화된 상태의 폼 요소를 선택한다.

input:enabled {
  background-color: #fff;
}

:disabled

비활성화된 상태의 폼 요소를 선택한다.

input:disabled {
  background-color: lightgray;
  cursor: not-allowed;
}

:checked

체크된 상태의 라디오 버튼이나 체크박스를 선택한다.

input[type='checkbox']:checked + label {
  color: royalblue;
  font-weight: bold;
}

input[type='radio']:checked + label {
  color: royalblue;
  font-weight: bold;
}
profile
내가 나에게 알려주는 개발 공부

0개의 댓글