edubun English

선택자와 캐스케이드

두 규칙이 같은 요소에 다른 색을 주면 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-클래스-요소, 왼쪽부터 비교
캐스케이드어느 선언이 이길지 정하는 규칙
상속글자 속성이 부모에서 자식으로 전해짐
  1. <p class="note">에 맞는 선택자는?
    • .note
    • #note
    • note
  2. nav a는 무엇에 맞을까요?
    • nav 안 어디든 있는 링크
    • nav와 모든 링크
    • nav 바로 아래 링크만
  3. h1, h2는 무엇을 할까요?
    • h1과 h2 모두에 적용
    • h1 안의 h2에 적용
    • 아무것에도 맞지 않음
  4. #menu .item a의 명시도는?
    • 1-1-1
    • 0-2-1
    • 1-0-2
  5. .a.b.c(0-3-0)와 #x(1-0-0)가 한 요소에 다른 색을 줍니다. 누가 이길까요?
    • #x
    • .a.b.c
    • The one written later
  6. 두 규칙의 명시도가 같다면 누가 이길까요?
    • 스타일시트에서 나중에 나오는 것
    • 먼저 나오는 것
    • 둘 다 적용 안 됨
  7. 기본으로 상속되는 속성은?
    • color
    • border
    • padding
  8. 키보드 초점이 있는 요소에 모양을 주는 가상 클래스는?
    • :focus-visible
    • :hover
    • :first-child
  9. a.active는 무엇에 맞을까요?
    • active 클래스가 있는 링크
    • 링크 안의 active 요소
    • 모든 링크와 모든 .active
  10. 평소 수정에 !important를 피하는 이유는?
    • 더 많은 !important로만 덮어쓸 수 있어 다음 수정이 어려워져서
    • 올바른 CSS가 아니어서
    • 브라우저가 느려져서
핵심 정리
  • p, .클래스, #id. 쉼표는 묶음, 빈칸은 자손, >는 자식.
  • 명시도(id-클래스-요소)로 결정하고, 같으면 나중 규칙이 이깁니다.
  • 글자 속성은 상속되고, 상자 속성은 상속되지 않습니다.