CSS 선택자 총정리: 원하는 요소를 정확히 타겟팅하는 방법

2025. 5. 14. 10:16·TypeScript/CSS
반응형

CSS를 사용하다 보면 가장 먼저 마주치는 도전 과제는 스타일을 적용할 특정 요소를 정확하게 선택하는 것입니다. 복잡한 웹 페이지에서 원하는 요소만 골라내는 것은 마치 모래사장에서 특정 모양의 조개껍데기를 찾는 것처럼 느껴질 수 있습니다. 하지만 CSS 선택자(Selectors)를 제대로 이해하고 활용한다면, 아무리 복잡한 HTML 구조에서도 필요한 요소를 정확히 타겟팅할 수 있습니다. 이 글에서는 CSS 선택자의 기본부터 고급 기법까지 완벽하게 정리해 보겠습니다.

기본 선택자

CSS 선택자의 기본 중의 기본부터 시작해봅시다. 이 선택자들은 CSS를 막 시작한 분들도 쉽게 이해할 수 있는 것들입니다.

전체 선택자(Universal Selector)

별표(*)를 사용하여 모든 요소를 선택합니다.

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

모든 요소에 기본 스타일을 적용할 때 유용하지만, 성능에 영향을 줄 수 있으므로 신중하게 사용해야 합니다.

타입 선택자(Type Selector)

HTML 태그 이름을 사용하여 특정 유형의 모든 요소를 선택합니다.

p {
  line-height: 1.6;
}

h1 {
  font-size: 2rem;
}

클래스 선택자(Class Selector)

점(.)을 사용하여 특정 클래스를 가진 요소를 선택합니다. 가장 널리 사용되는 선택자입니다.

.button {
  display: inline-block;
  padding: 10px 20px;
}

.primary {
  background-color: #3498db;
}

여러 클래스를 가진 요소를 선택할 수도 있습니다:

.button.primary {
  border: none;
}

위 코드는 class="button primary"와 같이 두 클래스를 모두 가진 요소만 선택합니다.

ID 선택자(ID Selector)

해시 기호(#)를 사용하여 특정 ID를 가진 요소를 선택합니다. ID는 페이지에서 고유해야 합니다.

#header {
  position: sticky;
  top: 0;
}

#main-content {
  margin-top: 20px;
}

속성 선택자(Attribute Selector)

대괄호([])를 사용하여 특정 속성을 가진 요소를 선택합니다.

[type] {
  /* type 속성을 가진 모든 요소 */
}

[type="text"] {
  /* type="text" 속성을 가진 요소 */
  padding: 5px 10px;
}

[data-theme="dark"] {
  /* 사용자 정의 데이터 속성 선택 */
  background-color: #333;
  color: white;
}

속성 값의 일부를 기준으로 선택할 수도 있습니다:

/* class 속성에 "btn"이 포함된 요소 */
[class*="btn"] {
  cursor: pointer;
}

/* href 속성이 ".pdf"로 끝나는 링크 */
[href$=".pdf"] {
  background-image: url('pdf-icon.png');
  padding-left: 20px;
}

/* href 속성이 "https"로 시작하는 링크 */
[href^="https"] {
  color: green;
}

결합자(Combinators)

결합자는 선택자 간의 관계를 정의하여 더 구체적인 요소를 선택할 수 있게 해줍니다.

자손 결합자(Descendant Combinator)

공백( )을 사용하여 특정 요소의 모든 자손(자식, 손자 등)을 선택합니다.

article p {
  /* article 내부의 모든 p 요소 */
  text-indent: 1em;
}

.container .item {
  /* .container 클래스 요소 내부의 모든 .item 클래스 요소 */
  margin: 10px;
}

자식 결합자(Child Combinator)

더 큰 기호(>)를 사용하여 특정 요소의 직접적인 자식만 선택합니다.

ul > li {
  /* ul의 직접적인 자식인 li만 선택 (중첩된 li는 선택되지 않음) */
  list-style-type: square;
}

.dropdown > .dropdown-menu {
  display: none;
}

인접 형제 결합자(Adjacent Sibling Combinator)

더하기 기호(+)를 사용하여 특정 요소 바로 다음에 오는 형제 요소를 선택합니다.

h2 + p {
  /* h2 바로 다음에 오는 p 요소 */
  font-weight: bold;
}

.field + .field {
  /* 연속된 .field 클래스 중 두 번째부터 선택 (간격 추가에 유용) */
  margin-top: 10px;
}

일반 형제 결합자(General Sibling Combinator)

물결 기호(~)를 사용하여 특정 요소 다음에 오는 모든 형제 요소를 선택합니다.

h2 ~ p {
  /* h2 다음에 오는 모든 p 요소 */
  color: #666;
}

.active ~ li {
  /* .active 클래스를 가진 요소 다음의 모든 li 요소 */
  color: #999;
}

의사 클래스(Pseudo-classes)

의사 클래스는 요소의 특정 상태나 위치를 기반으로 요소를 선택할 수 있게 해줍니다.

사용자 액션 의사 클래스

/* 마우스 호버 시 */
a:hover {
  text-decoration: underline;
}

/* 마우스 클릭 중(누르고 있는 상태) */
button:active {
  transform: translateY(1px);
}

/* 포커스 상태일 때 (탭 이동 등) */
input:focus {
  border-color: #3498db;
  outline: none;
}

/* 방문한 링크 */
a:visited {
  color: purple;
}

폼 요소 상태 의사 클래스

/* 체크된 상태의 체크박스/라디오 버튼 */
input:checked + label {
  color: #3498db;
}

/* 비활성화된 입력 필드 */
input:disabled {
  background-color: #f5f5f5;
  cursor: not-allowed;
}

/* 유효한/유효하지 않은 입력 값 */
input:valid {
  border-color: green;
}

input:invalid {
  border-color: red;
}

/* 선택적 입력 필드 */
input:optional {
  background-color: #f9f9f9;
}

/* 필수 입력 필드 */
input:required {
  border-left: 3px solid red;
}

구조적 의사 클래스

/* 첫 번째 자식 요소 */
li:first-child {
  font-weight: bold;
}

/* 마지막 자식 요소 */
li:last-child {
  border-bottom: none;
}

/* n번째 자식 요소 */
li:nth-child(3) {
  background-color: #f5f5f5;
}

/* 홀수번째 자식 요소 */
li:nth-child(odd) {
  background-color: #f9f9f9;
}

/* 짝수번째 자식 요소 */
li:nth-child(even) {
  background-color: #eee;
}

/* 특정 패턴의 자식 요소: 3n은 3, 6, 9, ... */
li:nth-child(3n) {
  color: red;
}

/* 특정 유형의 n번째 요소 */
p:nth-of-type(2) {
  font-style: italic;
}

/* 부모의 유일한 자식 */
li:only-child {
  list-style-type: none;
}

/* 해당 타입의 유일한 요소 */
p:only-of-type {
  font-weight: bold;
}

/* 빈 요소 */
div:empty {
  display: none;
}

기타 유용한 의사 클래스

/* 부정 선택자: 특정 선택자와 일치하지 않는 요소 */
:not(.special) {
  opacity: 0.8;
}

/* 현재 타겟된 요소 (URL의 #fragment와 일치) */
:target {
  animation: highlight 2s;
}

/* 루트 요소 (보통 html) */
:root {
  --primary-color: #3498db;
}

/* 현재 클릭/탭 가능한 요소 */
:focus-visible {
  outline: 2px dashed #3498db;
}

의사 요소(Pseudo-elements)

의사 요소는 실제 HTML에 존재하지 않는 "가상" 요소를 선택할 수 있게 해줍니다. 이중 콜론(::)으로 표시하지만, 하위 호환성을 위해 단일 콜론(:)도 허용됩니다.

기본 의사 요소

/* 요소의 첫 글자 */
p::first-letter {
  font-size: 2em;
  font-weight: bold;
}

/* 요소의 첫 줄 */
p::first-line {
  font-variant: small-caps;
}

/* 요소의 선택된 텍스트 */
::selection {
  background-color: #ffeb3b;
  color: black;
}

/* 요소 내용 앞/뒤에 콘텐츠 추가 */
.quote::before {
  content: '"';
  font-size: 2em;
  color: #ccc;
}

.quote::after {
  content: '"';
  font-size: 2em;
  color: #ccc;
}

고급 의사 요소 활용

/* 아이콘 추가 */
.external-link::after {
  content: ' ↗';
  font-size: 0.8em;
}

/* 툴팁 생성 */
[data-tooltip]::after {
  content: attr(data-tooltip);
  display: none;
  position: absolute;
  background: black;
  color: white;
  padding: 5px;
  border-radius: 3px;
}

[data-tooltip]:hover::after {
  display: block;
}

/* 장식선 만들기 */
h2::before {
  content: '';
  display: block;
  width: 50px;
  height: 3px;
  background-color: #3498db;
  margin-bottom: 10px;
}

/* 플레이스홀더 스타일링 */
input::placeholder {
  color: #999;
  font-style: italic;
}

선택자 결합 및 고급 패턴

이제 앞서 배운 선택자들을 결합하여 더 강력하고 정확한 선택을 해봅시다.

여러 선택자 그룹화

쉼표(,)를 사용하여 여러 선택자에 동일한 스타일을 적용할 수 있습니다.

h1, h2, h3, h4, h5, h6 {
  font-family: 'Montserrat', sans-serif;
}

.btn-primary, .btn-secondary, .btn-tertiary {
  border-radius: 4px;
  padding: 10px 20px;
}

복합 선택자

여러 선택자 유형을 결합하여 매우 구체적인 요소를 타겟팅할 수 있습니다.

/* nav 내부의 .active 클래스를 가진 a 태그 */
nav a.active {
  font-weight: bold;
}

/* article 내부의 첫 번째 p 요소의 첫 글자 */
article p:first-child::first-letter {
  font-size: 2em;
}

/* form 내부의 disabled 상태가 아닌 모든 input */
form input:not([disabled]) {
  background-color: white;
}

/* 레이블이 있는 체크박스를 선택했을 때 레이블 스타일 변경 */
input[type="checkbox"]:checked + label {
  color: #3498db;
}

/* 특정 섹션 내의 홀수번째 목록 아이템만 선택 */
.features-list li:nth-child(odd) {
  background-color: #f9f9f9;
}

실용적인 선택자 패턴

실제 개발에서 유용하게 사용할 수 있는 선택자 패턴을 살펴봅시다.

/* 형제 요소 간 간격 추가 (마진 충돌 방지) */
.card + .card {
  margin-top: 20px;
}

/* 제목 다음에 오는 첫 단락만 특별 스타일링 */
h2 + p {
  font-size: 1.1em;
  font-weight: 500;
}

/* 특정 깊이의 요소만 선택 */
.menu > li > ul > li {
  /* 메뉴의 2단계 깊이 항목만 */
  font-size: 0.9em;
}

/* 부모 기준 선택자 */
.parent:hover > .child {
  /* 부모에 호버했을 때 자식 요소 스타일 변경 */
  visibility: visible;
}

선택자 우선순위 이해하기

CSS에서 여러 규칙이 동일한 요소에 적용될 때, 어떤 규칙이 우선하는지는 "명시도(Specificity)"에 따라 결정됩니다.

명시도 계산 방법

명시도는 다음과 같은 순서로 계산됩니다 (높은 것이 우선):

  1. 인라인 스타일 (style 속성)
  2. ID 선택자 (#id)
  3. 클래스 선택자 (.class), 속성 선택자 ([attr]), 의사 클래스 (:hover)
  4. 요소 선택자 (div), 의사 요소 (::before)

예를 들어:

#nav .list li:hover {
  /* 명시도: 1-2-1 (ID 1개, 클래스+의사클래스 2개, 요소 1개) */
}

body .wrapper .button {
  /* 명시도: 0-2-1 (ID 0개, 클래스 2개, 요소 1개) */
}

첫 번째 선택자가 ID를 포함하기 때문에 두 번째 선택자보다 우선합니다.

!important

모든 명시도 규칙을 무시하고 최우선 적용하는 방법입니다. 남용하면 유지보수가 어려워지므로 꼭 필요한 경우에만 사용해야 합니다.

.button {
  background-color: blue !important; /* 다른 모든 배경색 규칙 무시 */
}

최신 CSS 선택자

CSS의 최신 사양에서 도입된 몇 가지 강력한 선택자를 살펴봅시다.

:is() 및 :where() 의사 클래스

이 선택자들은 선택자 목록을 그룹화하여 코드를 간결하게 만들어 줍니다.

/* 기존 방식 */
header a:hover, 
main a:hover, 
footer a:hover {
  text-decoration: underline;
}

/* :is() 사용 */
:is(header, main, footer) a:hover {
  text-decoration: underline;
}

차이점은 :is()는 내부 선택자의 가장 높은 명시도를 가져오는 반면, :where()는 명시도가 0입니다.

:has() 관계 선택자

부모 선택자를 가능하게 하는 혁신적인 선택자입니다. "특정 요소를 포함하는 요소"를 선택할 수 있습니다.

/* 이미지를 포함하는 단락 */
p:has(img) {
  display: flex;
  align-items: center;
}

/* 체크된 라디오 버튼을 포함하는 라벨 */
label:has(input[type="radio"]:checked) {
  font-weight: bold;
}

/* 자식 요소가 없는 div (빈 컨테이너) */
div:not(:has(*)) {
  display: none;
}

:focus-visible 및 :focus-within

/* 키보드 포커스일 때만 스타일 적용 (마우스 클릭은 제외) */
button:focus-visible {
  outline: 2px dashed blue;
}

/* 내부 요소 중 하나가 포커스를 받으면 컨테이너 스타일 변경 */
form:focus-within {
  background-color: #f5f5f5;
}

실무 CSS 선택자 활용 팁

유지보수성 향상을 위한 팁

  1. 과도하게 구체적인 선택자 피하기
/* 지양할 것 */
body header nav ul li a.nav-link {}

/* 지향할 것 */
.nav-link {}
  1. BEM 방법론과 같은 명명 규칙 사용
.block {}
.block__element {}
.block--modifier {}
  1. 선택자 깊이 제한하기 최대 3단계 이하로 선택자 깊이를 유지하면 유지보수성이 향상됩니다.

성능 최적화 팁

  1. 선택자는 오른쪽에서 왼쪽으로 해석됨을 이해하기
/* 비효율적: 모든 div를 확인한 후 .container 클래스 확인 */
div.container {}

/* 효율적: .container 클래스를 먼저 찾고 div인지 확인 */
.container {}
  1. 전체 선택자(*) 사용 제한하기 특히 복잡한 선택자의 일부로 사용할 때 성능에 영향을 줄 수 있습니다.
  2. ID 선택자 활용하기 ID 선택자는 페이지에서 고유하므로 브라우저가 빠르게 요소를 찾을 수 있습니다.

마무리

CSS 선택자는 단순한 기술 이상의 예술입니다. 기본 선택자부터 시작하여 복잡한 선택자 조합까지 마스터하면, HTML 구조를 변경하지 않고도 원하는 요소에 정확하게 스타일을 적용할 수 있습니다. 이는 유지보수성이 높고 효율적인 CSS 코드를 작성하는 데 필수적입니다.

가장 중요한 것은 실전 경험입니다. 다양한 선택자를 실험해보고, 개발자 도구를 활용하여 선택자가 어떤 요소를 타겟팅하는지 확인해보세요. 점차 더 복잡한 레이아웃과 인터랙션을 구현할 수 있게 될 것입니다.

최신 CSS 선택자는 계속해서 발전하고 있으므로, 새로운 스펙과 브라우저 지원 상황을 주기적으로 확인하는 것도 잊지 마세요. 이제 여러분은 CSS 선택자의 강력함을 활용하여 웹 개발의 새로운 가능성을 탐색할 준비가 되었습니다!

저작자표시 비영리 변경금지 (새창열림)

'TypeScript > CSS' 카테고리의 다른 글

CSS 초보자가 흔히 저지르는 10가지 실수와 해결책  (0) 2025.05.16
CSS 단위 완벽 이해하기: px vs. em vs. rem vs. vh/vw  (1) 2025.05.15
CSS 애니메이션 마스터하기: 자바스크립트 없이 인터랙티브한 웹 만들기  (0) 2025.05.13
반응형 웹 디자인: 모바일부터 데스크톱까지 완벽하게 대응하는 CSS 기법  (1) 2025.05.12
CSS 변수(Custom Properties)로 코드 유지보수 시간 절반으로 줄이기  (2) 2025.05.11
'TypeScript/CSS' 카테고리의 다른 글
  • CSS 초보자가 흔히 저지르는 10가지 실수와 해결책
  • CSS 단위 완벽 이해하기: px vs. em vs. rem vs. vh/vw
  • CSS 애니메이션 마스터하기: 자바스크립트 없이 인터랙티브한 웹 만들기
  • 반응형 웹 디자인: 모바일부터 데스크톱까지 완벽하게 대응하는 CSS 기법
코샵
코샵
나의 코딩 일기장
    반응형
  • 코샵
    끄적끄적 코딩 공방
    코샵
    • 분류 전체보기 (727) N
      • 스마트팜 (1) N
      • 상품 추천 (223)
      • DataBase (0)
        • MongoDB (4)
        • PostgreSQL (0)
      • 하드웨어 (18) N
      • 일기장 (4)
      • 파이썬 (130)
        • Basic (41)
        • OpenCV (8)
        • Pandas (15)
        • PyQT (3)
        • SBC(Single Board Computer) (1)
        • 크롤링 (14)
        • Fast API (29)
        • Package (6)
      • Unity (138)
        • Tip (41)
        • Project (1)
        • Design Pattern (8)
        • Firebase (6)
        • Asset (2)
      • Linux (4)
      • C# (97)
        • Algorithm (11)
        • Window (7)
      • TypeScript (51)
        • CSS (10)
      • Git (11)
      • SQL (5)
      • Flutter (10)
        • Tip (1)
      • System (1)
      • BaekJoon (6)
      • Portfolio (2)
      • MacOS (1)
      • 유틸리티 (1)
      • 서비스 (6)
      • 자동화 (3)
      • Hobby (10)
        • 물생활 (10)
        • 식집사 (0)
  • 인기 글

  • 태그

    C#
    파이썬
    상품 리뷰 크롤링
    스크립트 실행 순서
    쇼핑몰리뷰
    유니티
    rtsp
    긴유통기한우유
    unity
    programming101
    카페24리뷰이관
    ipcamera
    programmerlife
    learntocode
    스마트스토어리뷰
    리스트
    appdevelopment
    codingcommunity
    devlife
    셀레니움
    Python
    스크립트 실행
    리뷰관리
    리뷰이관
    믈레코비타멸균우유
    list
    codingtips
    라떼우유
    cv2
    카페24리뷰
  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
코샵
CSS 선택자 총정리: 원하는 요소를 정확히 타겟팅하는 방법
상단으로

티스토리툴바