CSS 기본 문법과 선택자
선택자와 선언 블록의 문법을 익히고 인라인·내부·외부 스타일 시트의 적용 범위와 우선순위를 구분합니다.
2장에서 우리는 HTML을 사용하여 웹 페이지의 뼈대와 콘텐츠를 구성하는 방법을 학습했습니다.
이제는 텍스트를 정리하고, 이미지를 삽입하며, 링크를 만들고, 폼을 통해 사용자 입력을 받는 기본적인 웹 페이지를 만들 수 있게 되었습니다.
하지만 HTML만으로는 웹 페이지가 다소 투박하고 정보가 나열된 문서처럼 보일 수 있습니다.
여기서 등장하는 것이 바로 CSS(Cascading Style Sheets)입니다.
CSS는 HTML 문서의 스타일(Style)과 레이아웃(Layout)을 정의하는 언어입니다.
웹 페이지의 색상, 글꼴, 크기, 배치, 여백 등 시각적인 모든 요소를 제어하여 사용자에게 매력적이고 직관적인 웹 경험을 제공하는 것이 CSS의 역할입니다.
이 장에서는 CSS 기본 문법 규칙과, 특정 요소에 스타일을 적용하는 핵심 개념인 선택자(Selector)를 중심으로 다룹니다.
CSS 기본기를 익히면 원하는 디자인을 더 일관되게 구현할 수 있습니다.
선택된 CSS 선언이 cascade를 거쳐 적용되는 과정 — 상태 추적
앞 우선순위가 동률일 때만 specificity/scope/소스 순서로 진행한다. 같은 두 선언의 살아남은 후보와 다음 검사 도달 여부를 상태로 나타낼 가치가 있다.
CSS CASCADE
CSS는 앞 조건이 동률일 때 다음 조건을 비교합니다
같은 요소·같은 속성의 후보를 cascade로 선택한 뒤, 지정값 → 계산값 → 사용값으로 처리합니다.
- 1 · 후보 확인
선택자와 현재 @media·@supports 조건이 맞는 유효 선언
- 2 · 출처·중요도·layer
UA·user·author, normal/!important, layer와 inline style. 애니메이션·전환도 이 우선순위에 관여
- 3 · specificity
같은 앞선 계층 안에서 ID → class·attribute·pseudo-class → type·pseudo-element
- 4 · scope 거리
specificity도 같고 @scope를 쓴 경우, scope root까지 더 가까운 선언
- 5 · 소스 순서
앞 조건이 모두 같을 때 마지막 선언
Specified · 지정값
선택된 선언 또는 상속·초깃값 등 기본 처리로 지정값을 정합니다.
Computed · 계산값
속성 규칙에 따라 상속과 상대값 등을 계산합니다. 모든 %가 여기서 px이 되는 것은 아닙니다.
Used · 사용값
레이아웃에서 필요한 containing block 크기 등으로 실제 사용할 값을 정합니다.
외부 CSS와 내부 CSS는 위치만으로 우선순위가 갈리지 않습니다
둘 다 작성자 스타일입니다. 위 순서를 확인한 뒤 소스 순서를 비교합니다. 기본 상속은 자식 요소에 직접 적용한 선언끼리의 specificity 경쟁과 별개입니다.
이 예의 조건
- 원도표의 전체 구조와 설명은 위 관계도와 표에서 유지합니다. 아래 인쇄 표에도 원도표의 관계·조건·라벨·설명·주석을 보존합니다.
- 두 관찰 칸의 위치는 고정입니다. 관찰 상태는 해당 순간의 값이며, 동작·이유는 그 조건에서의 판정과 변화 원인입니다. 독립 비교와 실패 분기는 별도 조건으로 읽고 모든 분기를 한 요청의 필수 실행 순서로 이어 읽지 않습니다.
관계도의 보충 설명
| 구분 | 내용 |
|---|---|
| 원도표 조건·주석 | 1 · 후보 확인: 선택자와 현재 @media·@supports 조건이 맞는 유효 선언 |
| 원도표 조건·주석 | 2 · 출처·중요도·layer: UA·user·author, normal/!important, layer와 inline style. 애니메이션·전환도 이 우선순위에 관여 |
| 원도표 조건·주석 | 3 · specificity: 같은 앞선 계층 안에서 ID → class·attribute·pseudo-class → type·pseudo-element |
| 원도표 조건·주석 | 4 · scope 거리: specificity도 같고 @scope를 쓴 경우, scope root까지 더 가까운 선언 |
| 원도표 조건·주석 | 5 · 소스 순서: 앞 조건이 모두 같을 때 마지막 선언 |
| 장면 | 현재 관찰값 | 설명 | 변화 이유 |
|---|---|---|---|
| 적용 후보 | 후보: 적용 가능한 선언 / 제외: 조건/선택자 불일치 | 조건과 매칭을 만족한 선언만 남긴다 | 매칭되지 않는 선언은 specificity로 되살리지 않는다 |
| cascade 위치 | 판정: 상위 cascade 기준 / specificity: 같은 위치에서 비교 | origin/important/layer 등 상위 기준을 먼저 비교한다 | 특이성만으로 모든 선언의 우열을 정하지 않는다 |
| 동률 해소 | scope: 해당 조건 비교 / source order: 최종 동률만 | 같은 기준일 때 scope 거리와 최종 source order를 읽는다 | 파일 뒤쪽이라는 이유만으로 항상 이기는 것은 아니다 |
선택된 CSS 선언이 cascade를 거쳐 적용되는 과정 — 상태 추적
앞 우선순위가 동률일 때만 specificity/scope/소스 순서로 진행한다. 같은 두 선언의 살아남은 후보와 다음 검사 도달 여부를 상태로 나타낼 가치가 있다.
CSS CASCADE
CSS는 앞 조건이 동률일 때 다음 조건을 비교합니다
같은 요소·같은 속성의 후보를 cascade로 선택한 뒤, 지정값 → 계산값 → 사용값으로 처리합니다.
- 1 · 후보 확인
선택자와 현재 @media·@supports 조건이 맞는 유효 선언
- 2 · 출처·중요도·layer
UA·user·author, normal/!important, layer와 inline style. 애니메이션·전환도 이 우선순위에 관여
- 3 · specificity
같은 앞선 계층 안에서 ID → class·attribute·pseudo-class → type·pseudo-element
- 4 · scope 거리
specificity도 같고 @scope를 쓴 경우, scope root까지 더 가까운 선언
- 5 · 소스 순서
앞 조건이 모두 같을 때 마지막 선언
Specified · 지정값
선택된 선언 또는 상속·초깃값 등 기본 처리로 지정값을 정합니다.
Computed · 계산값
속성 규칙에 따라 상속과 상대값 등을 계산합니다. 모든 %가 여기서 px이 되는 것은 아닙니다.
Used · 사용값
레이아웃에서 필요한 containing block 크기 등으로 실제 사용할 값을 정합니다.
외부 CSS와 내부 CSS는 위치만으로 우선순위가 갈리지 않습니다
둘 다 작성자 스타일입니다. 위 순서를 확인한 뒤 소스 순서를 비교합니다. 기본 상속은 자식 요소에 직접 적용한 선언끼리의 specificity 경쟁과 별개입니다.
이 예의 조건
- 원도표의 전체 구조와 설명은 위 관계도와 표에서 유지합니다. 아래 인쇄 표에도 원도표의 관계·조건·라벨·설명·주석을 보존합니다.
- 두 관찰 칸의 위치는 고정입니다. 관찰 상태는 해당 순간의 값이며, 동작·이유는 그 조건에서의 판정과 변화 원인입니다. 독립 비교와 실패 분기는 별도 조건으로 읽고 모든 분기를 한 요청의 필수 실행 순서로 이어 읽지 않습니다.
관계도의 보충 설명
| 구분 | 내용 |
|---|---|
| 원도표 조건·주석 | 1 · 후보 확인: 선택자와 현재 @media·@supports 조건이 맞는 유효 선언 |
| 원도표 조건·주석 | 2 · 출처·중요도·layer: UA·user·author, normal/!important, layer와 inline style. 애니메이션·전환도 이 우선순위에 관여 |
| 원도표 조건·주석 | 3 · specificity: 같은 앞선 계층 안에서 ID → class·attribute·pseudo-class → type·pseudo-element |
| 원도표 조건·주석 | 4 · scope 거리: specificity도 같고 @scope를 쓴 경우, scope root까지 더 가까운 선언 |
| 원도표 조건·주석 | 5 · 소스 순서: 앞 조건이 모두 같을 때 마지막 선언 |
| 장면 | 현재 관찰값 | 설명 | 변화 이유 |
|---|---|---|---|
| 적용 후보 | 후보: 적용 가능한 선언 / 제외: 조건/선택자 불일치 | 조건과 매칭을 만족한 선언만 남긴다 | 매칭되지 않는 선언은 specificity로 되살리지 않는다 |
| cascade 위치 | 판정: 상위 cascade 기준 / specificity: 같은 위치에서 비교 | origin/important/layer 등 상위 기준을 먼저 비교한다 | 특이성만으로 모든 선언의 우열을 정하지 않는다 |
| 동률 해소 | scope: 해당 조건 비교 / source order: 최종 동률만 | 같은 기준일 때 scope 거리와 최종 source order를 읽는다 | 파일 뒤쪽이라는 이유만으로 항상 이기는 것은 아니다 |
CSS란 무엇인가? 웹 디자인의 핵심 언어
CSS는 HTML 요소들이 웹 브라우저에 어떻게 보일지를 설명하는 언어입니다.
HTML이 집의 뼈대와 방의 구조를 만드는 것이라면, CSS는 벽지 색깔, 가구 배치, 창문의 모양과 같은 내부 장식을 담당한다고 생각할 수 있습니다.
CSS의 필요성
- HTML과 스타일의 분리: HTML은 콘텐츠의 구조와 의미를 담당하고, CSS는 시각적인 표현을 담당합니다. 이렇게 역할을 분리함으로써 HTML 코드는 더 간결해지고, CSS 코드는 디자인 변경에 유연하게 대응할 수 있습니다.
- 일관된 디자인 적용: 하나의 CSS 파일을 통해 여러 웹 페이지에 동일한 스타일을 적용할 수 있습니다. 웹사이트 전체의 디자인을 변경할 때도 CSS 파일 하나만 수정하면 되므로 유지보수가 매우 효율적입니다.
- 반응형 웹 디자인: CSS 미디어 쿼리(Media Query)를 사용하여 다양한 화면 크기(PC, 태블릿, 모바일)에 맞춰 웹 페이지의 레이아웃과 스타일을 다르게 적용할 수 있습니다.
- 읽기와 조작을 위한 표현: 글자 대비, 줄 간격, 포커스 표시를 CSS로 조정할 수 있습니다. 구조와 스타일을 분리하는 것만으로 접근성이나 검색 노출이 보장되지는 않으므로 실제 내용과 키보드 조작도 확인합니다.
CSS 기본 문법: 선언 블록과 속성-값 쌍
CSS는 매우 간단하고 직관적인 문법을 가지고 있습니다.
CSS 규칙(rule)은 크게 선택자(Selector)와 선언 블록(Declaration Block)으로 구성됩니다.
선택자 {
속성(property): 값(value);
속성(property): 값(value);
/* ...더 많은 속성-값 쌍 */
}- 선택자 (Selector): 스타일을 적용할 HTML 요소를 지정합니다. (예:
h1,p,.box,#main-header등) - 선언 블록 (Declaration Block): 중괄호
{}안에 들어가는 부분으로, 선택된 요소에 적용할 스타일 규칙들을 포함합니다. - 속성 (Property): 변경하고 싶은 스타일의 종류를 나타냅니다. (예:
color,font-size,background-color,margin등) - 값 (Value): 해당 속성에 적용할 구체적인 값입니다. (예:
red,16px,#f0f0f0,10px등) - 세미콜론 (
;): 각 속성-값 쌍의 끝에는 반드시 세미콜론을 붙여야 합니다. 마지막 속성-값 쌍에는 생략해도 오류는 아니지만, 일관성을 위해 붙이는 것이 좋은 습관입니다.
h1 { /* h1 태그를 선택하여 스타일 적용 */
color: blue; /* 글자 색상을 파란색으로 */
font-size: 32px; /* 글자 크기를 32픽셀로 */
text-align: center; /* 텍스트를 가운데 정렬 */
}
p { /* p 태그를 선택하여 스타일 적용 */
line-height: 1.8; /* 줄 간격을 1.8배로 */
margin-bottom: 1em; /* 아래쪽 여백을 1em으로 */
}CSS 규칙은 선택자, 선언 블록, 속성-값 쌍으로 나누어 읽으면 구조를 빠르게 파악할 수 있습니다. 위 코드의 “선택자”, “속성”, “값”은 문법을 설명하는 자리 표시자입니다. 실제 파일에는 다음 예처럼 h1, color, blue를 씁니다. 잘못된 선언은 무시될 수 있으므로 화면이 일부만 바뀌었을 때에는 개발자 도구의 Styles에서 해당 선언을 확인합니다.
CSS 적용 방법: HTML과 CSS 연결하기
CSS 스타일을 HTML 문서에 적용하는 방법은 크게 세 가지가 있습니다.
인라인 스타일 (Inline Style)
HTML 태그의 style 속성에 직접 CSS 코드를 작성하는 방식입니다.
- 장점: 특정 요소에만 즉시 스타일을 적용할 때 편리합니다.
- 단점: 코드 가독성이 떨어지고, 재사용이 불가능하며, 유지보수가 어렵습니다. 권장되지 않는 방법입니다.
인라인 스타일은 일반 선택자 specificity 계산 밖에서 강하게 적용되므로, 나중에 외부 CSS에서 덮어쓰기 어렵습니다.
반복되는 스타일이나 컴포넌트 규칙은 class와 외부 스타일 시트로 옮기는 편이 안전합니다.
<p style="color: red; font-size: 18px;">이 문단은 인라인 스타일이 적용됩니다.</p>내부 스타일 시트 (Internal Style Sheet)
HTML 문서의 <head> 태그 안에 <style> 태그를 사용하여 CSS 코드를 작성하는 방식입니다.
- 장점: HTML 문서 하나에서 모든 스타일을 관리할 수 있어 간단한 페이지에 유용합니다.
- 단점: 여러 HTML 페이지에 동일한 스타일을 적용할 수 없으며, HTML 파일의 크기가 커집니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>내부 스타일 시트</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f0f0f0;
}
h1 {
color: purple;
text-decoration: underline;
}
</style>
</head>
<body>
<h1>내부 스타일 시트 예시</h1>
<p>이것은 내부 스타일 시트가 적용된 문단입니다.</p>
</body>
</html>외부 스타일 시트 (External Style Sheet)
별도의 .css 파일을 만들고, 이 파일을 HTML 문서에 연결하는 방식입니다.
대부분의 실제 웹 개발 프로젝트에서 사용되는 표준적인 방법입니다.
-
장점
- HTML과 CSS 코드를 완벽하게 분리하여 가독성과 유지보수성이 매우 뛰어납니다.
- 하나의
.css파일로 여러 HTML 페이지에 동일한 스타일을 적용할 수 있어 효율적입니다. - CSS 파일이 캐싱되어 웹 페이지 로딩 속도를 개선할 수 있습니다.
- 단점: HTML 파일과 CSS 파일 간의 링크가 깨지면 스타일이 적용되지 않습니다.
CSS 파일 생성: HTML 파일과 같은 폴더 또는 하위 폴더(css 폴더 등)에 style.css와 같은 이름으로 CSS 파일을 만듭니다.
style.css 파일 내용
body {
font-family: 'Malgun Gothic', sans-serif;
background-color: #e6e6fa;
}
h1 {
color: darkgreen;
text-align: left;
}
p {
font-size: 16px;
}HTML 파일에 연결: HTML 문서의 <head> 태그 안에 <link> 태그를 사용하여 CSS 파일을 연결합니다.
rel="stylesheet": 연결하는 문서가 스타일 시트임을 나타냅니다.href="경로/파일명.css": CSS 파일의 경로를 지정합니다.
index.html 파일 내용
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>외부 스타일 시트</title>
<link rel="stylesheet" href="style.css"> </head>
<body>
<h1>외부 스타일 시트 예시</h1>
<p>이것은 외부 스타일 시트가 적용된 문단입니다.</p>
<p>HTML과 CSS 파일이 분리되어 있어 깔끔합니다.</p>
</body>
</html>CSS 선택자: 원하는 요소만 골라내기
선택자(Selector)는 CSS의 핵심 중 하나입니다.
수많은 HTML 요소 중에서 정확히 어떤 요소에 스타일을 적용할지 지정하는 역할을 합니다.
올바른 선택자 사용법을 익히는 것은 CSS를 효과적으로 다루는 데 필수적입니다.
기본 선택자
*)- 문서의 모든 HTML 요소에 스타일을 적용합니다.
- 초기화처럼 모든 요소에 공통으로 적용할 규칙에 사용합니다. 범위가 넓으므로 의도하지 않은 요소까지 바꾸지 않는지 확인합니다. 선택자 기호 하나만으로 성능 문제를 판단하지는 않습니다.
* {
margin: 0; /* 모든 요소의 기본 마진 제거 */
padding: 0; /* 모든 요소의 기본 패딩 제거 */
}- 특정 HTML 태그 이름을 직접 사용하여 해당 태그의 모든 요소에 스타일을 적용합니다.
p { /* 모든 <p> 태그 */
color: #333;
font-family: sans-serif;
}
h2 { /* 모든 <h2> 태그 */
border-bottom: 1px solid #ccc;
}클래스 선택자 (.) - 가장 많이 사용!
- HTML 요소의
class속성 값으로 요소를 선택합니다. 한 HTML 문서 내에서 여러 요소에 동일한 클래스를 적용할 수 있으며, 하나의 요소가 여러 클래스를 가질 수도 있습니다. .클래스명형태로 사용합니다.
<h1 class="main-title">우리 회사</h1>
<p class="section-text">회사 소개입니다.</p>
<p class="section-text highlight">중요한 내용입니다.</p>.main-title { /* class가 "main-title"인 요소 */
font-size: 40px;
color: #2c3e50;
}
.section-text { /* class가 "section-text"인 요소들 */
line-height: 1.6;
color: #555;
}
.highlight { /* class가 "highlight"인 요소들 */
background-color: yellow;
}#)- HTML 요소의
id속성 값으로 요소를 선택합니다.id는 HTML 문서 내에서 유일해야 합니다. (하나의id는 오직 하나의 요소에만 사용되어야 함) #ID명형태로 사용합니다.- 특정 요소를 정확히 식별하여 스타일링할 때 유용합니다.
<div id="header">
<h1>환영합니다!</h1>
</div>
<div id="footer">
<p>저작권</p>
</div>#header { /* id가 "header"인 요소 */
background-color: #f8f8f8;
padding: 20px;
}
#footer { /* id가 "footer"인 요소 */
text-align: center;
font-size: 14px;
color: #888;
}id: 문서 내에서 고유한 하나의 요소에 적용 (주로 JavaScript에서 특정 요소에 접근할 때 사용)class: 여러 요소에 반복적으로 적용 가능 (주로 CSS 스타일링에 사용)
복합 선택자
여러 선택자를 조합하여 더 구체적인 요소를 선택할 수 있습니다.
- 부모 요소 안에 있는 모든 자손 요소(하위 요소)를 선택합니다.
부모선택자 자손선택자형태로 사용합니다.
<div class="menu">
<ul>
<li><a href="#">메뉴 1</a></li>
<li><a href="#">메뉴 2</a></li>
</ul>
</div>
<p>일반 문단</p>.menu ul li a { /* class가 "menu"인 요소 내부의 ul 내부의 li 내부의 a 태그 */
text-decoration: none; /* 밑줄 제거 */
color: #4CAF50; /* 초록색 */
}>)- 부모 요소의 바로 아래에 있는 자식 요소만 선택합니다.
부모선택자 > 자식선택자형태로 사용합니다.
<div class="container">
<p>자식 문단 1</p>
<div>
<p>손자 문단</p>
</div>
<p>자식 문단 2</p>
</div>.container > p { /* class가 "container"인 요소의 직계 자식인 <p> 태그만 */
border: 1px solid blue;
}
/* 위의 CSS는 "손자 문단"에는 적용되지 않습니다. */+)- 바로 다음에 오는 형제 요소(같은 부모를 가진 요소)를 선택합니다.
형제1선택자 + 형제2선택자형태로 사용합니다.
<h1>제목</h1>
<p>첫 번째 문단</p>
<p>두 번째 문단</p>
<div>다른 요소</div>
<p>세 번째 문단</p>h1 + p { /* <h1> 태그 바로 뒤에 오는 <p> 태그 */
font-weight: bold;
color: red;
}
/* 이 스타일은 "첫 번째 문단"에만 적용됩니다. */~)- 다음에 오는 모든 형제 요소들을 선택합니다.
형제1선택자 ~ 형제2선택자형태로 사용합니다.
h1 ~ p { /* <h1> 태그 다음에 오는 모든 <p> 태그들 */
font-style: italic;
}
/* 이 스타일은 "첫 번째 문단", "두 번째 문단", "세 번째 문단" 모두에 적용됩니다. */속성 선택자
- 특정 속성을 가지거나 특정 속성 값을 가진 요소를 선택합니다.
[속성명]: 해당 속성을 가진 모든 요소[속성명="값"]: 해당 속성이 특정 값을 가진 요소[속성명^="값"]: 해당 속성 값이 특정 문자열로 시작하는 요소[속성명$="값"]: 해당 속성 값이 특정 문자열로 끝나는 요소[속성명*="값"]: 해당 속성 값이 특정 문자열을 포함하는 요소
a[target="_blank"] { /* target="_blank" 속성을 가진 모든 <a> 태그 */ background-color: lightblue; } input[type="text"] { /* type="text" 속성을 가진 모든 <input> 태그 */ border: 1px solid gray; } img[alt*="로고"] { /* alt 속성 값에 "로고"가 포함된 모든 <img> 태그 */ border: 2px solid green; }
가상 클래스 선택자 (Pseudo-classes)
- 요소의 특정 상태나 위치에 따라 스타일을 적용할 때 사용합니다.
:(콜론)을 사용하여 정의합니다.:hover: 마우스 커서가 요소 위에 올라갔을 때:active: 요소를 클릭하는 동안:focus: 폼 입력 필드처럼 요소에 포커스가 있을 때:link: 방문하지 않은 링크:visited: 방문한 링크:first-child: 부모의 첫 번째 자식 요소:last-child: 부모의 마지막 자식 요소:nth-child(n): 부모의 n번째 자식 요소 (n은 숫자,odd,even사용 가능):not(selector): 지정된 선택자가 아닌 요소
a:hover { /* 링크에 마우스 올렸을 때 */ color: orange; text-decoration: underline; } input:focus { /* input 필드에 포커스 있을 때 */ border-color: blue; box-shadow: 0 0 5px rgba(0, 0, 255, 0.5); } li:first-child { /* 목록의 첫 번째 항목 */ font-weight: bold; } li:nth-child(even) { /* 목록의 짝수 번째 항목 */ background-color: #f2f2f2; } button:active { /* 버튼 클릭 시 */ transform: translateY(1px); /* 살짝 눌리는 효과 */ }
가상 요소 선택자 (Pseudo-elements)
- 요소의 특정 부분에 스타일을 적용할 때 사용합니다.
::(이중 콜론)을 사용하여 정의합니다. 호환을 위한 단일 콜론 표기는before,after,first-letter,first-line네 가지에만 허용되므로, 여기서는 이중 콜론으로 구분합니다.::before: 요소의 콘텐츠 앞에 가상 콘텐츠를 생성::after: 요소의 콘텐츠 뒤에 가상 콘텐츠를 생성::first-letter: 텍스트의 첫 글자::first-line: 텍스트의 첫 줄::selection: 사용자가 텍스트를 드래그하여 선택했을 때
p::first-letter { /* <p> 태그의 첫 글자 */ font-size: 2em; color: #ff5733; float: left; /* 드롭캡 효과 */ line-height: 1; margin-right: 5px; } a::after { /* <a> 태그 콘텐츠 뒤에 화살표 아이콘 추가 */ content: " →"; font-size: 0.8em; vertical-align: super; }
직접 선택해 보기
자식 선택자 예의 HTML을 그대로 두고, .container > p와 .container p가 각각 고르는 문단 이름을 먼저 적으세요. “손자 문단”만 파란 테두리 없이 남기는 선택자는 어느 쪽인가요? 그다음 CSS의 선택자만 바꾸어 결과를 비교하세요.
매칭 관계 확인
.container > p는 “자식 문단 1”, “자식 문단 2”를 고릅니다. 손자 문단의 직접 부모는 안쪽 div이므로 제외됩니다. .container p는 깊이와 관계없이 세 문단을 모두 고릅니다. 두 선택자는 우선순위를 비교하기 전에 선택되는 요소 집합부터 다릅니다.