프로그래밍/css 기초

CSS 기초 공부(7) - 가상 class

lamarcK 2025. 3. 10. 22:17

가상 클래스(Pseudo-class)와 가상 요소(Pseudo-element)라는 것이 있는데 별도로 이름을 지정하지 않아도 마치 클래스나 요소가 있는 것처럼 사용할 수 있는 스타일 규칙이라고 볼 수 있다.

 

가상 클래스(Pseudo-class)란?

CSS에서 요소의 특정 상태나 조건을 기반으로 스타일을 적용하는 선택자이다.

별도로 class를 지정하지 않고도 class를 지정한 것처럼 요소를 선택할 수 있다.

의사 클래스라고도 부른다.

 

주요 가상 클래스 종류 및 예시

:hover (마우스 오버)

마우스 포인터가 요소 위에 올라갔을 때 스타일을 적용한다.

button:hover {
    background-color: blue;
    cursor: pointer;
    }

위 코드는 button 요소에 마우스 포인터를 올리면 배경색이 파란색으로 변경되고, 커서가 포인터 모양으로 바뀐다.

(버튼의 기본 모양은 저번 글에서 설정한 CSS 디자인 형식을 따랐다)

:active (활성화)

요소가 활성화되었을 때(마우스 버튼을 누르고 있는 동안) 스타일을 적용한다.

button:active {
  background-color: orange;
}

 

위 코드는 button 요소를 클릭하고 있는 동안 배경색이 주황색으로 변경된다.

:focus (포커스):

요소가 포커스를 받았을 때(입력 양식에 커서가 위치했을 때) 스타일을 적용한다.

<body>
<input type="text">
</body>
input:focus {
    border: 10px solid red;
    }

 

위 코드는 input 요소에 포커스가 맞춰지면 빨간색 테두리가 표시된다.

:visited (방문한)

사용자가 방문한 링크에 스타일을 적용한다.

    <body>
        <a href="https://www.naver.com">네이버 홈페이지</a>
    </body>

 

a:visited {
    color: red;
    }

 

위 코드는 사용자가 방문한 a 요소(링크)의 글자색을 빨간색으로 변경한다.

:first-child (첫 번째 자식)

부모 요소의 첫 번째 자식 요소에 스타일을 적용한다.

    <body>
        <p>1번</p>
        <p>2번</p>
        <p>3번</p>
    </body>

 

p:first-child {
    color: red;
    font-weight: bold;
  }

 

위 코드는 부모 요소의 첫 번째 <p> 자식 요소의 글자를 굵게, 빨간색으로 표시한다.

별도로 부모 태그가 없는 것처럼 보이지만 실제로는 <body> 태그를 부모 태그로 취급해서 1번째 <p>태그만 적용이 된 모습이다.


여기서 잠깐 부모 태그와 자식 태그가 정확히 무엇인지 한번 더 짚고 넘어가겠다.

부모 태그와 자식 태그란?

  • 부모 태그 : 다른 태그를 포함하는 태그
  • 자식 태그 : 다른 태그에 의해 포함되는 태그

그렇다면 아래와 같은 코드가 있다면 어떨까?

    <body>
        <p>1번</p>
        <p>2번</p>
        <p>3번</p>
        <div>
        <p>1번</p>
        <p>2번</p>
        <p>3번</p>
        </div>
    </body>

 

그렇다면 이처럼 <body> 태그의 1번째 자식인 1번이 스타일 적용을 받는 것을 볼 수 있다.

또한 <div> 태그의 첫번째 자식인 4번 또한 스타일 적용을 받는 것을 볼 수 있다.

:last-child (마지막 자식)

부모 요소의 마지막 자식 요소에 스타일을 적용한다.

p:last-child {
  font-style: italic;
}

 

위 코드는 부모 요소의 마지막 <p> 자식 요소의 글자를 기울여 표시한다.

 

위의 설정을 그대로 유지한 채로 해당 스타일을 추가한다면 마지막 자식인 6번만이 스타일 적용을 받아서 기울임 효과를 받는 것을 알 수 있다.


위에서 나온 태그들은 모두 1번째 혹은 마지막 자식 태그만을 변경하기 때문에 사실상 제약이 너무 크다. 그렇기 때문에 원하는 자식 태그를 변경 시킬 수 있는 태그를 사용해야하는데 그것이 바로 :nth-child(n)이라는 가상 클래스다.

:nth-child(n) (n번째 자식)

부모 요소의 n번째 자식 요소에 스타일을 적용한다.

 

:nth-child(n)는 다양한 사용법이 있다.

1. 숫자 사용

<ul>
  <li>항목 1</li>
  <li>항목 2</li>
  <li>항목 3</li>
  <li>항목 4</li>
  <li>항목 5</li>
</ul>

 

li:nth-child(3) {
  color: red;
}

 

위 코드는 <ul> 요소의 3번째 <li> 자식 요소에 빨간색 글씨 스타일을 적용한다.


:nth-child(n)의 장점은 n에 다양한 수치를 넣을 수 있다는 점이다. 그 중 하나는 키워드를 사용하는 방법이다.

2. 키워드 사용

  • even : 짝수 번째 자식 요소를 선택한다.
  • odd : 홀수 번째 자식 요소를 선택한다.

HTML

<table>
  <tr>
    <td>1행 1열</td>
    <td>1행 2열</td>
  </tr>
  <tr>
    <td>2행 1열</td>
    <td>2행 2열</td>
  </tr>
  <tr>
    <td>3행 1열</td>
    <td>3행 2열</td>
  </tr>
  <tr>
    <td>4행 1열</td>
    <td>4행 2열</td>
  </tr>
</table>

 

tr:nth-child(even) {
    background-color: lightgray;
  }

 

이처럼 짝수 요소만 선택해서 스타일을 적용하게 할 수도 있고 반대로 홀수 요소만 선택할 수도 있을 것이다.

만약에 css에서 스타일을 적용할 대상을 <tr>에서 <td>로 바꾼다면 행이 아닌 열에 스타일을 적용할 수 있다.

td:nth-child(even) {
    background-color: lightgray;
  }

table 태그에 대해서

더보기

<table>: 표 전체를 정의한다.

<tr>: 표의 행(가로줄)을 정의한다.

<td>: 표의 일반 셀(열)을 정의하고 데이터를 입력한다.


또한 수식을 사용해서 특정한 순서의 태그에만 스타일을 적용하는 것도 가능하다.

3. 수식 사용

  • an + b 형태의 수식을 사용하여 특정 패턴의 자식 요소를 선택한다.
  • a : 반복되는 패턴의 간격
  • b : 시작 위치
<ul>
  <li>항목 1</li>
  <li>항목 2</li>
  <li>항목 3</li>
  <li>항목 4</li>
  <li>항목 5</li>
  <li>항목 6</li>
  <li>항목 7</li>
  <li>항목 8</li>
  <li>항목 9</li>
</ul>

 

li:nth-child(3n + 1) {
    font-weight: bold; color: red;
  }

 

위 코드는 <ul> 요소의 3n+1 번째 <li> 자식 요소(1, 4, 7번째 항목)에 굵은 글씨와 붉은색 색상 스타일을 적용한다.

그렇다면 다음과 같은 경우 어떻게 적용 될까?

<body>
    <ol>
      <li>목록 1 - 항목 1</li>
      <li>목록 1 - 항목 2</li>
    </ol>
    <p>일반 문단</p>
    <ol>
      <li>목록 2 - 항목 1</li>
      <li>목록 2 - 항목 2</li>
    </ol>
    <ol>
      <li>목록 3 - 항목 1</li>
      <li>목록 3 - 항목 2</li>
    </ol>
  </body>

 

  ol:nth-child(2n) {
    background-color: lightblue;
}

 

<ol> 태그를 사용해서 순서가 있는 목록을 작성했고 중간에 <p> 태그를 사용해서 1개의 단락을 추가했다.

css에서는 nth-child(2n) 가상 클래스를 사용해서 2n 즉 짝수 단위에만 스타일이 적용되도록 설정했다.

결과는 다음과 같다.

목록 3에만 스타일이 적용된 것을 볼 수 있다.

짝수 단위인데 왜 목록 3에 스타일이 적용되는지 궁금할 수 있을 것이다.

그것은 바로 :nth-child(n) 가상 클래스가 오직 순서만을 기준으로 적용되기 때문이다.

 

실제로 해당 코드의 태그는 총 4가지이다.

  1. 목록1
  2. 일반 문단
  3. 목록2
  4. 목록3

(X) 보다시피 목록1은 홀수이기 때문에 적용이 안되기 때문에 그대로이고

(X) 일반 문단은 짝수이지만 <p>태그이기 때문에 <ol> 스타일의 적용이 안되기 때문에 다음으로 넘어간다.

(X) 목록2는 <ol> 태그이지만 홀수이기 때문에 적용이 안되기 때문에 그대로이다.

(O) 마지막 목록3은 <ol> 태그인 동시에 짝수 이기 떄문에 홀로 스타일이 적용되는 것이다.

 

이처럼 :nth-child(n)라는 가상 클래스는 오직 순서만을 기준으로 적용되기 때문에 실제로 <ol> 태그를 가진 목록은 3개임에도 불구하고 목록2가 아닌 4번째(짝수) 순서에 있는 목록3에만 스타일이 적용되게 되는 것이다.

 

만약에 코드의 순서를 바꾸어 다음과 같이 코드를 수정한다면

<body>
    <ol>
      <li>목록 1 - 항목 1</li>
      <li>목록 1 - 항목 2</li>
    </ol>
    <ol>
      <li>목록 2 - 항목 1</li>
      <li>목록 2 - 항목 2</li>
    </ol>

    <p>일반 문단</p>
    
    <ol>
      <li>목록 3 - 항목 1</li>
      <li>목록 3 - 항목 2</li>
    </ol>
  </body>

목록 2와 3이 모두 짝수이며 <ol>태그이기 때문에 스타일의 적용을 받게 된다.

 

그렇다면 :nth-child(n) 처럼 순서만을 기준으로 스타일을 적용하는 것이 아니라 <특정 태그>를 기준으로만 순서를 따져서 스타일을 적용하는 방법은 없을까?

 

그럴 경우 사용하는 것이 바로 :nth-of-type(n)라는 가상 클래스이다.

:nth-child(n)와의 차이점

:nth-child(n)

  • 부모 요소의 모든 자식 요소를 대상으로 순서를 계산한다.
  • 따라서 특정 태그뿐만 아니라 다른 태그들도 순서 계산에 포함된다.

:nth-of-type(n)

  • 부모 요소의 자식 요소 중에서 특정 태그만을 대상으로 순서를 계산한다.
  • 따라서 특정 태그만을 선택하여 스타일을 적용할 수 있다.
 
 
예를 들어 다음과 같은 코드가 있다고 한다면
<div>
  <p>문단 1</p>
  <span>스팬 1</span>
  <p>문단 2</p>
  <span>스팬 2</span>
  <p>문단 3</p>
</div>
p:nth-of-type(2) {
  color: blue;
}

 

이처럼 <p> 태그를 가진 내용 중 2번째에 있는 문단2만이 스타일의 적용을 받는 것을 알 수 있다.


스타일을 2가 아니라 3n을 적용 시킨다면

p:nth-of-type(3n){
    color: blue;
  }

 

이처럼 3번째마다 스타일이 적용되어 문단3만 스타일의 적용을 받는 것을 알 수 있다.

 

그렇다면 좀 더 복잡하게 복합적으로 스타일을 적용하면 어떻게 될까?

p:nth-of-type(n){
    font-size: 30px;
  }

p:nth-of-type(3n){
    color: blue;
  }

span:nth-of-type(2n){
    background-color: aquamarine;
}

이런식으로 원하는 순서의 태그에 각각 스타일을 적용할 수 있게 된다.


위에서 언급한 child 가상 클래스 외에도 다양한 child 계통의 가상 클래스가 존재한다. 아래는 주요 목록이다.

더보기

1. :first-child

  • 부모 요소의 첫 번째 자식 요소를 선택합니다.
  • 자식 요소의 타입(태그 이름)에 관계없이 첫 번째 위치에 있는 요소에 스타일을 적용합니다.
  • 예시: p:first-child { color: red; } (부모 요소의 첫 번째 <p> 요소에 빨간색 글씨 스타일 적용)

2. :last-child

  • 부모 요소의 마지막 자식 요소를 선택합니다.
  • 자식 요소의 타입(태그 이름)에 관계없이 마지막 위치에 있는 요소에 스타일을 적용합니다.
  • 예시: li:last-child { border-bottom: none; } (부모 요소의 마지막 <li> 요소에 아래쪽 테두리 제거)

3. :nth-child(n)

  • 부모 요소의 자식 요소 중 n번째 요소에 스타일을 적용합니다.
  • n은 숫자, 키워드(even, odd), 수식을 사용하여 다양한 패턴으로 자식 요소를 선택할 수 있습니다.
  • 예시:
    • li:nth-child(3): 세 번째 <li> 요소에 스타일 적용
    • tr:nth-child(even): 짝수 번째 <tr> 요소에 스타일 적용
    • li:nth-child(3n + 1): 3n+1 번째 <li> 요소에 스타일 적용

4. :nth-last-child(n)

  • 부모 요소의 자식 요소 중 뒤에서부터 n번째 요소에 스타일을 적용합니다.
  • :nth-child(n)와 반대로 뒤에서부터 순서를 계산합니다.
  • 예시:
    • li:nth-last-child(1): 마지막 <li> 요소에 스타일 적용
    • tr:nth-last-child(even): 뒤에서부터 짝수 번째 <tr> 요소에 스타일 적용

5. :only-child

  • 부모 요소의 유일한 자식 요소에 스타일을 적용합니다.
  • 부모 요소 안에 자식 요소가 단 하나만 존재할 때 스타일이 적용됩니다.
  • 예시: p:only-child { font-style: italic; } (부모 요소 안에 <p> 요소가 하나만 있을 때 기울임꼴 스타일 적용)

6. :first-of-type

  • 부모 요소의 자식 요소 중 특정 타입(태그 이름)의 첫 번째 요소에 스타일을 적용합니다.
  • 특정 타입의 요소들 중에서 첫 번째 요소에 스타일을 적용합니다.
  • 예시: p:first-of-type { font-weight: bold; } (부모 요소의 첫 번째 <p> 요소에 굵은 글씨 스타일 적용)

7. :last-of-type

  • 부모 요소의 자식 요소 중 특정 타입(태그 이름)의 마지막 요소에 스타일을 적용합니다.
  • 특정 타입의 요소들 중에서 마지막 요소에 스타일을 적용합니다.
  • 예시: p:last-of-type { color: blue; } (부모 요소의 마지막 <p> 요소에 파란색 글씨 스타일 적용)

8. :nth-of-type(n)

  • 부모 요소의 자식 요소 중 특정 타입(태그 이름)의 n번째 요소에 스타일을 적용합니다.
  • :nth-child(n)와 달리 특정 타입의 요소만을 대상으로 순서를 계산합니다.
  • 예시:
    • p:nth-of-type(2): 두 번째 <p> 요소에 스타일 적용
    • li:nth-of-type(odd): 홀수 번째 <li> 요소에 스타일 적용

9. :nth-last-of-type(n)

  • 부모 요소의 자식 요소 중 특정 타입의 뒤에서부터 n번째 요소에 스타일을 적용합니다.
  • :nth-of-type(n)와 마찬가지로 특정 타입의 요소만을 대상으로 순서를 계산합니다.
  • 예시:
    • p:nth-last-of-type(1): 마지막 <p> 요소에 스타일 적용
    • li:nth-last-of-type(odd): 뒤에서부터 홀수 번째 <li> 요소에 스타일 적용