선택자와 캐스케이드
두 규칙이 같은 요소에 다른 색을 주면 CSS는 짐작하지 않습니다. 선택자를 비교하고, id 하나는 클래스가 몇 개든 이깁니다.
요소 고르기
선택자는 페이지의 요소에 맞춰 보는 패턴입니다. 가장 간단한 것은 요소 이름, 클래스, id로 고릅니다. p는 유형 선택자로 모든 문단에 맞습니다. .note는 클래스 선택자로 class="note"인 모든 요소에 맞습니다. 한 요소에 클래스를 빈칸으로 나눠 여러 개 줄 수 있고, 한 클래스를 여러 요소에 쓸 수도 있습니다. #intro는 id 선택자로 id="intro"인 요소 하나에 맞습니다. 전체 선택자 *는 모든 요소에 맞습니다.
p { line-height: 1.5; } /* every p */
.note { background: #fff4d6; } /* class="note" */
#intro { font-size: 20px; } /* id="intro" */
h1, h2 { font-weight: 600; } /* group: h1 and h2 */
nav a { text-decoration: none; } /* a anywhere inside nav */
ul > li { margin: 4px 0; } /* li that is a direct child of ul */
a:hover { text-decoration: underline; }
input[type="email"] { width: 20em; }선택자 조합하기
쉼표는 같은 선언을 쓰는 선택자를 묶어서 h1, h2는 둘 다에 적용됩니다. 빈칸은 자손 결합자로, nav a는 nav 안에 있는 링크라면 얼마나 깊이 있든 맞습니다. >는 더 까다로워서 바로 아래 자식에만 맞습니다. a.active처럼 단순 선택자 두 개를 빈칸 없이 붙여 쓰면 한 요소가 둘 다에 맞아야 합니다. active 클래스가 있는 링크라는 뜻입니다. 대괄호 안에 쓰는 속성 선택자는 input[type="email"]처럼 속성으로 고릅니다.
쌍점 하나로 쓰는 가상 클래스는 어떤 상태나 위치에 있는 요소를 고릅니다. :hover는 마우스 포인터가 올라가 있을 때, :focus-visible은 키보드 초점이 있을 때, :first-child는 부모의 첫 자식일 때입니다. 쌍점 두 개로 쓰는 가상 요소는 ::first-line, ::placeholder처럼 요소의 일부분에 모양을 줍니다.
규칙이 서로 다를 때
같은 요소의 같은 속성을 여러 규칙이 정하는 일은 흔합니다. 어느 규칙이 이길지는 CSS의 C인 캐스케이드(cascade)가 정합니다. 브라우저 자체 스타일과 !important를 빼면 거의 모든 경우는 질문 두 개로 결론이 납니다. 첫째, 어느 선택자가 더 구체적인가? 명시도(specificity)는 숫자 세 개로 셈니다. id 개수, 클래스 개수(속성 선택자와 가상 클래스 포함), 요소 이름 개수입니다. #menu a는 1-0-1, .active는 0-1-0, nav a는 0-0-2입니다. 왼쪽 숫자부터 비교하므로 id 하나가 클래스 몇 개든 이깁니다. 둘째, 명시도가 같다면 스타일시트에서 나중에 나오는 규칙이 이깁니다.
인라인 style 속성은 어떤 선택자보다도 강하고, !important를 붙인 선언은 보통 선언을 이깁니다. 둘 다 급할 때 손이 가지만, 이것을 덮어쓰려면 같은 것을 더 쓰는 수밖에 없어서 다음 수정이 어려워집니다. 대부분의 팀은 주로 클래스로 스타일을 주어 명시도를 낮고 고르게 유지합니다. 그러면 파일 안의 순서만 봐도 결과를 예상할 수 있습니다.
상속
어떤 속성은 부모에서 자식으로 저절로 전해집니다. body에 color나 font-family를 정하면, 안에 있는 문단, 목록, 표 칸이 자기 규칙이 없는 한 모두 그 값을 받습니다. 글자에 관한 속성은 대체로 상속되고, width, padding, border, margin처럼 상자에 관한 속성은 상속되지 않습니다. 그래서 section에 테두리를 줘도 안의 문단마다 테두리가 생기지는 않습니다. inherit 키워드를 쓰면 부모의 값을 그대로 받게 할 수 있습니다.
클래스 이름은 생김새가 아니라 그것이 무엇인지로 짓습니다. 디자이너가 색을 빨강에서 주황으로 바꿔도 .warning은 여전히 맞는 이름이지만 .red-text는 그렇지 않습니다. id는 하나뿐이라 스타일보다는 링크 대상이나 입력 칸 이름표에 쓰는 편이 좋고, 그러면 명시도도 낮게 유지됩니다.
| 유형 선택자 | p, h1, a. 그 이름의 모든 요소 |
| 클래스 선택자 | .이름. 그 클래스가 있는 모든 요소 |
| id 선택자 | #이름. 그 id가 있는 요소 하나 |
| 자손 결합자 | 빈칸. nav a = nav 안 어디든 있는 a |
| 가상 클래스 | :hover, :focus-visible. 상태나 위치 |
| 명시도 | id-클래스-요소, 왼쪽부터 비교 |
| 캐스케이드 | 어느 선언이 이길지 정하는 규칙 |
| 상속 | 글자 속성이 부모에서 자식으로 전해짐 |
<p class="note">에 맞는 선택자는?- .note
- #note
- note
nav a는 무엇에 맞을까요?- nav 안 어디든 있는 링크
- nav와 모든 링크
- nav 바로 아래 링크만
h1, h2는 무엇을 할까요?- h1과 h2 모두에 적용
- h1 안의 h2에 적용
- 아무것에도 맞지 않음
#menu .item a의 명시도는?- 1-1-1
- 0-2-1
- 1-0-2
.a.b.c(0-3-0)와#x(1-0-0)가 한 요소에 다른 색을 줍니다. 누가 이길까요?- #x
- .a.b.c
- The one written later
- 두 규칙의 명시도가 같다면 누가 이길까요?
- 스타일시트에서 나중에 나오는 것
- 먼저 나오는 것
- 둘 다 적용 안 됨
- 기본으로 상속되는 속성은?
- color
- border
- padding
- 키보드 초점이 있는 요소에 모양을 주는 가상 클래스는?
- :focus-visible
- :hover
- :first-child
a.active는 무엇에 맞을까요?- active 클래스가 있는 링크
- 링크 안의 active 요소
- 모든 링크와 모든 .active
- 평소 수정에 !important를 피하는 이유는?
- 더 많은 !important로만 덮어쓸 수 있어 다음 수정이 어려워져서
- 올바른 CSS가 아니어서
- 브라우저가 느려져서
- p, .클래스, #id. 쉼표는 묶음, 빈칸은 자손, >는 자식.
- 명시도(id-클래스-요소)로 결정하고, 같으면 나중 규칙이 이깁니다.
- 글자 속성은 상속되고, 상자 속성은 상속되지 않습니다.