AD JB Toolbox 01

CSS 강좌 / 관계 선택자와 가상 클래스로 요소 고르기

CSS 관계 선택자는 요소 사이의 부모·자식·형제 관계로 대상을 고르고, 가상 클래스는 상태나 문서 내 위치 같은 조건으로 대상을 고릅니다. .garden p와 .garden > p는 중첩된 문단의 포함 여부가 다르며, h2 + p와 h2 ~ p는 바로 다음 형제만 고르는지 뒤쪽 형제를 함께 고르는지가 다릅니다.

부모·자식·자손·형제 관계 읽기

다음 구조에서 section은 h2, A 문단, div, C 문단의 부모입니다. B 문단은 div의 자식이며 section의 자손입니다. A와 C는 같은 부모를 가지므로 형제이지만, A와 B는 부모가 달라 형제가 아닙니다. 화면에서 가까워 보이는지보다 HTML 구조가 기준입니다.

<section class="garden">
  <h2>방문 안내</h2>
  <p>A: 운영 시간</p>
  <div>
    <p>B: 온실 안내</p>
  </div>
  <p>C: 준비물</p>
</section>
section.garden
├─ h2
├─ p  ← A
├─ div
│  └─ p  ← B
└─ p  ← C
관계 표기 선택자 선택되는 문단 선택되지 않는 문단
공백: 자손 .garden p A, B, C 이 section 밖의 p
>: 직접 자식 .garden > p A, C div를 한 단계 더 거치는 B
+: 바로 다음 형제 h2 + p A B는 부모가 다르고 C 앞에는 div가 있습니다.
~: 뒤쪽 형제 h2 ~ p A, C B는 h2와 부모가 다릅니다.

관계 선택자는 일반적으로 오른쪽 조건에 해당하는 요소를 고릅니다. h2 + p는 h2를 꾸미는 규칙이 아니라 h2 바로 뒤의 p를 꾸미는 규칙입니다. 여기서 “바로 뒤”는 형제 요소를 기준으로 하므로 들여쓰기나 줄바꿈 텍스트가 있다고 인접 관계가 끊어지지는 않습니다.

자손과 자식 선택자의 범위 비교

.garden p { color: #087f5b; }
.garden > p { border-left: 4px solid #087f5b; padding-left: 12px; }

첫 규칙은 garden 안의 모든 p를 초록색으로 만듭니다. 중간에 div가 있어도 B를 포함합니다. 두 번째 규칙은 직접 자식인 A와 C에만 왼쪽 테두리와 여백을 넣습니다. color와 border-left는 다른 속성이므로 A와 C는 초록색과 테두리를 함께 가질 수 있습니다.

안내 영역 안의 모든 문단을 공통으로 꾸미려면 자손 선택자가 적합합니다. 안쪽 카드나 다른 작은 구역의 문단까지 바꾸지 않으려면 직접 자식 조건이 알맞을 수 있습니다. 구조가 바뀌면 선택 결과도 달라지므로, 이유 없이 >를 여러 번 연결해 HTML 깊이에 지나치게 의존하지 않는 것이 좋습니다. 각 관계 표기는 MDN의 결합자 설명을 참고할 수 있습니다.

바로 다음 형제와 뒤쪽 형제 비교

h2 + p { background-color: #fff4cc; }
h2 ~ p { font-style: italic; }

첫 규칙은 제목 바로 다음 안내문 A에 노란빛 배경을 넣습니다. 두 번째 규칙은 같은 section 안에서 h2 뒤에 있는 A와 C를 기울여 표시합니다. B는 화면상 h2 아래에 있어도 h2와 부모가 다르므로 해당하지 않습니다. 두 형제 선택자 모두 앞쪽 형제를 거꾸로 선택하지 않습니다.

h2와 A 사이에 <div>추가 안내</div>를 끼워 넣으면 A는 더 이상 바로 다음 형제가 아니므로 노란빛 배경이 사라집니다. 그러나 같은 부모 안에서 h2 뒤에 있다는 조건은 유지되어 기울임은 남습니다. 이 차이를 확인하면 +와 ~를 “비슷한 선택자”로 외우지 않아도 됩니다.

상태와 위치를 나타내는 가상 클래스

a:hover { background-color: #fff4cc; }
a:focus-visible { outline: 3px solid #1d4ed8; outline-offset: 3px; }
.plants li:first-child { font-weight: bold; }
.plants li:nth-child(odd) { background-color: #e9f7ef; }

:hover는 포인터를 올린 상태를 선택합니다. :focus-visible은 브라우저가 포커스 표시가 필요하다고 판단한 상태를 선택하며 키보드로 Tab 이동할 때 확인하기 좋습니다. :focus는 포커스를 가진 상태 자체를 고르므로 둘의 의미가 완전히 같지는 않습니다. 이 예제는 기본 포커스 표시를 없애지 않고 추가 외곽선을 지정합니다.

링크에 마우스를 올리면 배경이 노란빛으로 바뀌고, Tab으로 링크에 도달하면 파란 외곽선이 나타납니다. 터치 환경에서는 hover를 사용자가 항상 경험한다고 보장할 수 없습니다. 운영 시간이나 링크 이름처럼 꼭 필요한 내용은 기본 상태에서도 읽을 수 있게 두세요.

:first-child는 부모의 첫 번째 자식 요소인 경우를 고릅니다. :nth-child(odd)는 자식 요소 순서가 1, 3, 5처럼 홀수인 경우를 고릅니다. 위 식물 목록에는 li만 있으므로 1번 민트가 굵어지고 1·3번 항목에 배경이 생깁니다. odd 대신 even을 쓰면 2·4번이 대상입니다.

p:first-child는 “첫 번째 p”가 아니라 “첫 자식이면서 p인 요소”입니다. 이 예제의 section은 h2가 첫 자식이므로 .garden > p:first-child는 아무 문단도 고르지 않습니다. nth-child도 같은 태그만 세지 않고 모든 형제 요소의 순서를 셉니다. 태그 종류별 순서가 필요하다면 nth-of-type처럼 별도 조건을 검토해야 합니다. 상태와 위치 조건의 개념은 MDN의 가상 클래스 설명에 정리되어 있습니다.

관계와 상태를 모두 포함한 전체 예제

<!doctype html>
<html lang="ko">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>작은 정원</title>
  <style>
body { margin: 24px; font-family: sans-serif; line-height: 1.7; }
    .garden p { color: #087f5b; }
    .garden > p { border-left: 4px solid #087f5b; padding-left: 12px; }
    h2 + p { background-color: #fff4cc; }
    h2 ~ p { font-style: italic; }
    .plants li:first-child { font-weight: bold; }
    .plants li:nth-child(odd) { background-color: #e9f7ef; }
    a:hover { background-color: #fff4cc; }
    a:focus-visible { outline: 3px solid #1d4ed8; outline-offset: 3px; }
  </style>
</head>
<body>
<h1>작은 정원</h1>
  <section class="garden">
    <h2>방문 안내</h2>
    <p>A: 매일 오전 9시에 문을 엽니다.</p>
    <div>
      <p>B: 온실에서는 조용히 관람하세요.</p>
    </div>
    <p>C: 물병과 편한 신발을 준비하세요.</p>
  </section>
  <ul class="plants">
    <li>1: 민트</li>
    <li>2: 바질</li>
    <li>3: 로즈메리</li>
    <li>4: 타임</li>
  </ul>
  <a href="#contact">문의 위치로 이동</a>
  <h2 id="contact">문의</h2>
  <p>안내 데스크에서 문의하세요.</p>
</body>
</html>

저장해 실행하면 A·B·C가 초록색이고 A·C에만 왼쪽 테두리가 있습니다. A는 노란빛 배경, A·C는 기울임이 추가됩니다. 식물 목록은 첫 항목이 굵고 홀수 항목에 연한 배경이 있습니다. 링크는 마우스와 키보드로 각각 확인하세요. 문단 앞의 A~C 표시는 선택 결과를 비교하기 위해 본문에 직접 적은 문자입니다.

HTML 구조와 조건을 바꾸는 실습

  1. h2와 A 사이에 div를 한 개 추가합니다. A의 배경만 사라지고 기울임과 테두리는 남는지 확인합니다. 실습 후 추가한 div를 지웁니다.
  2. B 문단을 감싸는 div 태그만 제거하여 B를 section의 직접 자식으로 만듭니다. B도 왼쪽 테두리와 기울임을 갖게 되는지 확인합니다. + 조건에는 여전히 A만 맞습니다. 확인 후 div를 복원합니다.
  3. :nth-child(odd)를 :nth-child(even)으로 바꿉니다. 목록 배경이 1·3번에서 2·4번으로 옮겨가고, first-child의 굵은 글자는 여전히 1번에 남는지 확인합니다.
  4. 마우스를 치운 뒤 페이지 안을 클릭하고 Tab을 눌러 링크로 이동합니다. 포커스 외곽선이 보이는지, Enter로 문의 구역에 이동할 수 있는지 확인합니다. 브라우저 주소창에 포커스가 있다면 먼저 페이지로 돌아옵니다.

각 조건은 따로 확인하세요. 선택 범위를 넓히려는 문제에 색상값만 바꾸거나, 키보드 포커스 문제에 hover만 추가하면 원인을 해결하지 못합니다. 개발자 도구에서는 상태를 강제로 켜는 기능으로 비교할 수도 있지만, 마지막에는 실제 Tab 이동과 마우스 동작으로 사용자에게 보이는 결과를 확인하는 편이 좋습니다.

같은 카테고리의 다른 글
CSS / Tutorial / 인용문(Blockquote) 꾸미는 방법

CSS / Tutorial / 인용문(Blockquote) 꾸미는 방법

blockquote 요소의 기본 모양은 양쪽에 여백이 있는 것입니다. 그대로 사용하기보다는 여러 가지 모양으로 꾸미는 것이 일반적입니다. 다음은 아래와 같은 인용문을 꾸미는 몇 가지 예제입니다.

CSS / Tutorial / 세로 가운데 정렬하는 방법

CSS / Tutorial / 세로 가운데 정렬하는 방법

CSS에서 텍스트의 가로 가운데 정렬은 text-align 속성을 이용합니다. 요소의 가로 가운데 정렬은 margin 속성을 이용합니다. 세로 정렬을 가운데로 하려면 어떻게 해야 할까요? 네 가지 방법을 소개합니다.

CSS / Tutorial / 표 꾸미기 / 테두리

CSS / Tutorial / 표 꾸미기 / 테두리

테두리는 border 속성으로 만듭니다. table, th, td 요소에 적용할 수 있습니다. tr 요소에는 적용되지 않습니다.

CSS / Tutorial / 변수 사용하는 방법

CSS / Tutorial / 변수 사용하는 방법

CSS 사용자 지정 속성을 :root와 특정 구성 요소에 선언하고 var()로 색과 간격을 재사용하는 방법을 설명합니다. 상속 범위, 값이 없을 때의 대체값, 유효하지 않은 값의 처리도 예제로 확인합니다.

CSS / Tutorial / 문자열 자르는 방법

CSS / Tutorial / 문자열 자르는 방법

웹페이지에 출력하는 문자열의 길이는 서버단에서 조절하는 게 보통입니다. 하지만, 어떤 경우에는 그게 불가능할 수 있습니다. 이미 전송 받은 문자열을 잘라야 하는 상황이 생길 수 있습니다. CSS를 이용하여 문자열의 일부만 보여주는 방법을 소개해드립니다.

CSS 강좌 / CSS란 무엇이고 HTML과 어떻게 다를까?

CSS 강좌 / CSS란 무엇이고 HTML과 어떻게 다를까?

HTML과 CSS의 역할을 구분하고, 같은 작은 정원 문서에 색상·배경·여백을 적용합니다. 실행 가능한 예제와 세 가지 변형 실습으로 스타일이 바뀌는 범위를 확인할 수 있습니다.

CSS / Tutorial / 마우스 호버 효과 /  이미지 확대하는 방법

CSS / Tutorial / 마우스 호버 효과 / 이미지 확대하는 방법

이미지에 마우스를 올렸을 때 이미지가 확대되는 효과를 만들어보겠습니다. 다음과 같이 이미지가 들어간 간단한 HTML 문서를 만듭니다.

CSS / Tutorial / 원 또는 타원 만드는 방법

CSS / Tutorial / 원 또는 타원 만드는 방법

CSS의 border-radius 속성으로 원 또는 타원을 만들 수 있습니다. HTML 문서에 다음과 같이 내용이 없는 요소를 하나 만듭니다. 적절히 크기를 정하여 정사각형을 만들고, 배경색을 넣습니다. border-radius 속성을 추가하고, 값에 50%를 넣으면 원이 만들어집니다.

CSS / Tutorial / 마우스 호버 효과 / 텍스트 나오게 하는 방법

CSS / Tutorial / 마우스 호버 효과 / 텍스트 나오게 하는 방법

CSS로 특정 요소에 마우스를 올렸을 때 보이지 않던 특정 요소가 보이게 할 수 있습니다. 아래는 문단에 마우스를 올렸을 때 div 요소가 나오게 하는 예제입니다. div 요소 안에 텍스트가 있지만, 텍스트가 아닌 이미지 등 다른 것도 가능합니다.

CSS / Tutorial / 마우스 호버 효과 / 서서히 길어지는 선 만드는 방법

CSS / Tutorial / 마우스 호버 효과 / 서서히 길어지는 선 만드는 방법

마우스를 올리면 선이 그려지는 효과를 만들어봅니다. 다음과 같이 사각형을 만듭니다. :before를 이용하여 선이 시작하는 위치를 정합니다. position 속성으로 선 위에 선을 그릴 수 있도록 설정합니다.