1. 소개
이 절은 표준이 아닙니다.
테스트
이 절은 표준이 아니므로 테스트가 필요하지 않습니다.
선택자는 트리 구조의 요소를 받아 해당 요소가 선택자와 일치하는지 여부를 판정하는 불리언 값 판별식입니다.
이런 표현식은 여러 상황에서 활용될 수 있습니다:
- 요소에 직접 적용해 주어진 조건과 일치하는지 확인(예: [DOM]에서 정의된
element.matches()함수) - 전체 요소 트리에 적용하여 주어진 조건에 맞는 요소 집합으로 걸러내기(예: [DOM]에서 정의된
document.querySelectorAll()함수 또는 CSS 스타일 규칙의 선택자) - "역방향"으로 사용하여 특정 선택자에 맞는 마크업 생성(예: HAML, Emmet 등)
선택자 레벨 1, 2, 3은 각각 CSS1, CSS2.1, Selectors Level 3 명세에서 정의된 선택자 기능의 하위 집합입니다. 이 모듈은 Selectors Level 4를 정의합니다.
1.1. 모듈 상호작용
테스트
이 절에는 테스트가 필요 없습니다.
이 모듈은 CSS에서 [SELECT] 및 [CSS21]에 정의된 선택자의 정의를 대체하고 범위를 확장합니다.
렌더링 트리에서 추상 요소를 정의하는 의사요소 선택자는 이 명세 범위에 포함되지 않습니다: 그들의 일반 문법은 여기에서 다루지만, 렌더링 모델 밀접 통합 및 DOM 쿼리 등 다른 용도와 무관한 이유로 별도의 모듈에서 정의될 예정입니다.
2. 선택자 개요
이 절은 표준이 아니며, 이후 절들을 간략히 요약합니다.
테스트
이 절은 표준이 아니므로 테스트가 필요하지 않습니다.
선택자는 구조를 표현합니다. 이 구조는 문서 트리에서 선택자가 어떤 요소들과 매칭될지 결정하는 조건(예: CSS 규칙)으로 사용되거나, 그 구조에 해당하는 HTML 또는 XML 조각에 대한 평면적 설명으로 쓰일 수 있습니다.
선택자는 간단한 요소 이름부터 복합적 문맥 표현까지 다양합니다.
아래 표는 선택자 문법을 요약한 것입니다:
| 패턴 | 의미 | 섹션 | 레벨 |
|---|---|---|---|
*
| 모든 요소 | § 5.2 범용 선택자 | 2 |
E
| E 타입의 요소 | § 5.1 타입(태그 이름) 선택자 | 1 |
E:not(s1, s2, …)
| 아래 복합 선택자 s1 또는 복합 선택자 s2와 모두 일치하지 않는 E 요소 | § 4.3 부정(일치하지 않음) 가상 클래스: :not() | 3/4 |
E:is(s1, s2, …)
| 복합 선택자 s1 및/또는 복합 선택자 s2와 일치하는 E 요소 | § 4.2 일치-임의 가상 클래스: :is() | 4 |
E:where(s1, s2, …)
| 복합 선택자 s1 및/또는 복합 선택자 s2와 일치하나 특이성을 더하지 않는 E 요소 | § 4.4 특이성 조정 가상 클래스: :where() | 4 |
E:has(rs1, rs2, …)
| 만일 상대 선택자 rs1 또는 rs2를 만족하는 요소가 존재하고(평가 시 E가 기준 요소가 될 때), 그럴 때의 E 요소 | § 4.5 관계형 가상 클래스: :has() | 4 |
E.warning
| warning 클래스를 가진 E 요소 (문서 언어별로 class 판정 방법 명세)
| § 6.6 클래스 선택자 | 1 |
E#myid
| myid와 같은 ID 값을 가진 E 요소
| § 6.7 ID 선택자 | 1 |
E[foo]
| foo 속성이 있는 E 요소
| § 6.1 속성 존재 및 값 선택자 | 2 |
E[foo="bar"]
| foo 속성 값이 정확히 bar인 E 요소
| § 6.1 속성 존재 및 값 선택자 | 2 |
E[foo="bar" i]
| foo 속성 값이 (ASCII 범위 내) 대소문자 무시하며 bar와 동일한 E 요소
| § 6.3 대소문자 구분 | 4 |
E[foo="bar" s]
| 동일한 bar 값인 foo 속성의 E 요소
| § 6.3 대소문자 구분 | 4 |
E[foo~="bar"]
| foo 속성 값이 공백으로 구분된 값 목록이고, 그 중 하나가 정확히 bar인 E 요소
| § 6.1 속성 존재 및 값 선택자 | 2 |
E[foo^="bar"]
| foo 속성 값이 bar 문자열로 시작하는 E 요소
| § 6.2 부분문자열 일치 속성 선택자 | 3 |
E[foo$="bar"]
| foo 속성 값이 bar 문자열로 끝나는 E 요소
| § 6.2 부분문자열 일치 속성 선택자 | 3 |
E[foo*="bar"]
| foo 속성 값이 bar 문자열을 포함하는 E 요소
| § 6.2 부분문자열 일치 속성 선택자 | 3 |
E[foo|="en"]
| foo 속성 값이 en으로 시작하는 하이픈 연결 목록인 E 요소
| § 6.1 속성 존재 및 값 선택자 | 2 |
E:dir(ltr)
| 좌→우(ltr) 방향성을 가지는 E 타입 요소(문서 언어별 방향성 판정 방법 명세) | § 7.1 방향성 가상 클래스: :dir() | 4 |
E:lang(zh, "*-hant")
| E 타입 요소로, 중국어(방언/문자 종류 무관) 또는 전통 한자 사용으로 태그된 것 | § 7.2 언어 가상 클래스: :lang() | 2/4 |
E:any-link
| 하이퍼링크의 소스 앵커인 E 요소 | § 8.1 하이퍼링크 가상 클래스: :any-link | 4 |
E:link
| 아직 방문되지 않은 하이퍼링크의 소스 앵커인 E 요소 | § 8.2 링크 기록 가상 클래스: :link, :visited | 1 |
E:visited
| 이미 방문된 하이퍼링크의 소스 앵커인 E 요소 | § 8.2 링크 기록 가상 클래스: :link, :visited | 1 |
E:target
| 현재 URL의 타겟이 되는 E 요소 | § 8.3 타겟 가상 클래스: :target | 3 |
E:scope
| 스코프 루트인 E 요소 | § 8.4 참조 요소 가상 클래스: :scope | 4 |
E:active
| 활성화 상태인 E 요소 | § 9.2 활성화 가상 클래스: :active | 1 |
E:hover
| 커서가 올라가 있거나, 자식 중 누구에게 커서가 올라가 있는 E 요소 | § 9.1 포인터 hover 가상 클래스: :hover | 2 |
E:focus
| 사용자 입력 포커스를 가진 E 요소 | § 9.3 입력 포커스 가상 클래스: :focus | 2 |
E:focus-within
| 사용자 입력 포커스를 가졌거나, 그 자식 중 포커스가 있는 E 요소 | § 9.5 포커스 컨테이너 가상 클래스: :focus-within | 4 |
E:focus-visible
| 사용자 입력 포커스를 가지며, UA가 포커스 링 또는 표시자를 그려야 한다고 판단한 E 요소 | § 9.4 포커스 표시 가상 클래스: :focus-visible | 4 |
E:enabled
| 활성화 또는 비활성화된 사용자 인터페이스 요소 E | § 12.1.1 :enabled, :disabled 가상 클래스 | 3 |
E:read-writeE:read-only
| 사용자가 변경 가능한/불가능한 UI 요소 E | § 12.1.2 변경 가능성 가상 클래스: :read-only, :read-write | 3-UI/4 |
E:placeholder-shown
| 현재 플레이스홀더 텍스트를 표시하는 입력 컨트롤 | § 12.1.3 플레이스홀더 표시 가상 클래스: :placeholder-shown | 3-UI/4 |
E:default
| 관련 선택들 그룹에서 기본 항목인 UI 요소 E | § 12.1.5 기본 옵션 가상 클래스: :default | 3-UI/4 |
E:checkedE:uncheckedE:indeterminate
| 체크(선택)됨/해제됨/불확정 상태(체크됨도 해제됨도 아닌)인 UI 요소 E(예: 라디오버튼, 체크박스) | § 12.2 입력 값 상태 | 3 |
E:validE:invalid
| 최소한의 데이터 유효성 의미를 만족 혹은 불만족하는 사용자 입력 요소 E | § 12.3.1 유효성 가상 클래스: :valid, :invalid | 3-UI/4 |
E:in-rangeE:out-of-range
| 값이 허용 범위 내/밖인 사용자 입력 요소 E | § 12.3.2 범위 가상 클래스: :in-range, :out-of-range | 3-UI/4 |
E:requiredE:optional
| 입력이 "필수"/"선택"인 사용자 입력 요소 E | § 12.3.3 필수/선택적 가상 클래스: :required, :optional | 3-UI/4 |
E:user-invalid
| 잘못된 입력으로 사용자가 수정한 사용자 입력 요소 E(유효성 위반, 범위 초과, 필수임에도 누락 등) | § 12.3.4 사용자 상호작용 가상 클래스: :user-valid, :user-invalid | 4 |
E:root
| 문서의 루트인 E 요소 | § 13.1 :root 가상 클래스 | 3 |
E:empty
| 자식(요소, 텍스트 모두)이 없거나 공백만 있는 E 요소 | § 13.2 :empty 가상 클래스 | 3 |
E:nth-child(n [of S]?)
| 부모에서 S와 일치하는 n번째 자식인 E 요소 | § 13.3.1 :nth-child() 가상 클래스 | 3/4 |
E:nth-last-child(n [of S]?)
| 마지막부터 셌을 때 부모에서 S와 일치하는 n번째 자식인 E 요소 | § 13.3.2 :nth-last-child() 가상 클래스 | 3/4 |
E:first-child
| 부모의 첫번째 자식인 E 요소 | § 13.3.3 :first-child 가상 클래스 | 2 |
E:last-child
| 부모의 마지막 자식인 E 요소 | § 13.3.4 :last-child 가상 클래스 | 3 |
E:only-child
| 부모의 유일한 자식인 E 요소 | § 13.3.5 :only-child 가상 클래스 | 3 |
E:nth-of-type(n)
| 동일 타입 내에서 n번째 형제인 E 요소 | § 13.4.1 :nth-of-type() 가상 클래스 | 3 |
E:nth-last-of-type(n)
| 동일 타입 내에서 마지막부터 셌을 때 n번째 형제인 E 요소 | § 13.4.2 :nth-last-of-type() 가상 클래스 | 3 |
E:first-of-type
| 동일 타입의 첫번째 형제인 E 요소 | § 13.4.3 :first-of-type 가상 클래스 | 3 |
E:last-of-type
| 동일 타입의 마지막 형제인 E 요소 | § 13.4.4 :last-of-type 가상 클래스 | 3 |
E:only-of-type
| 동일 타입 내에 유일한 형제인 E 요소 | § 13.4.5 :only-of-type 가상 클래스 | 3 |
E F
| E 요소 후손인 F 요소 | § 14.1 하위 결합자( ) | 1 |
E > F
| E 요소의 직계 자식인 F 요소 | § 14.2 자식 결합자(>) | 2 |
E + F
| E 요소 바로 뒤에 나오는 F 형제 요소 | § 14.3 인접 형제 결합자(+) | 2 |
E ~ F
| E 요소 앞에 등장한 F 형제 요소 | § 14.4 일반 형제 결합자(~) | 3 |
참고: 일부 레벨 4 선택자(위에서 "3-UI"로 표시된 것)는 [CSS3UI]에서 도입되었습니다.
테스트
- css3-modsel-1.xml (시각적 테스트) (source)
- css3-modsel-10.xml (시각적 테스트) (source)
- css3-modsel-100.xml (시각적 테스트) (source)
- css3-modsel-100b.xml (시각적 테스트) (source)
- css3-modsel-101.xml (live test) (source)
- css3-modsel-101b.xml (live test) (source)
- css3-modsel-102.xml (live test) (source)
- css3-modsel-102b.xml (시각적 테스트) (source)
- css3-modsel-103.xml (live test) (source)
- css3-modsel-103b.xml (live test) (source)
- css3-modsel-104.xml (시각적 테스트) (source)
- css3-modsel-104b.xml (시각적 테스트) (source)
- css3-modsel-105.xml (live test) (source)
- css3-modsel-105b.xml (live test) (source)
- css3-modsel-106.xml (live test) (source)
- css3-modsel-106b.xml (live test) (source)
- css3-modsel-107.xml (시각적 테스트) (source)
- css3-modsel-107b.xml (시각적 테스트) (source)
- css3-modsel-108.xml (live test) (source)
- css3-modsel-108b.xml (live test) (source)
- css3-modsel-109.xml (live test) (source)
- css3-modsel-109b.xml (live test) (source)
- css3-modsel-11.xml (시각적 테스트) (source)
- css3-modsel-110.xml (live test) (source)
- css3-modsel-110b.xml (live test) (source)
- css3-modsel-111.xml (시각적 테스트) (source)
- css3-modsel-111b.xml (시각적 테스트) (source)
- css3-modsel-112.xml (live test) (source)
- css3-modsel-112b.xml (live test) (source)
- css3-modsel-113.xml (시각적 테스트) (source)
- css3-modsel-113b.xml (시각적 테스트) (source)
- css3-modsel-114.xml (시각적 테스트) (source)
- css3-modsel-114b.xml (시각적 테스트) (source)
- css3-modsel-115.xml (live test) (source)
- css3-modsel-115b.xml (live test) (source)
- css3-modsel-116.xml (live test) (source)
- css3-modsel-116b.xml (live test) (source)
- css3-modsel-117.xml (live test) (source)
- css3-modsel-117b.xml (live test) (source)
- css3-modsel-118.xml (시각적 테스트) (source)
- css3-modsel-119.xml (시각적 테스트) (source)
- css3-modsel-120.xml (시각적 테스트) (source)
- css3-modsel-121.xml (시각적 테스트) (source)
- css3-modsel-122.xml (live test) (source)
- css3-modsel-123.xml (시각적 테스트) (source)
- css3-modsel-123b.xml (시각적 테스트) (source)
- css3-modsel-124.xml (시각적 테스트) (source)
- css3-modsel-124b.xml (시각적 테스트) (source)
- css3-modsel-125.xml (live test) (source)
- css3-modsel-125b.xml (live test) (source)
- css3-modsel-126.xml (live test) (source)
- css3-modsel-126b.xml (live test) (source)
- css3-modsel-127.xml (live test) (source)
- css3-modsel-127b.xml (live test) (source)
- css3-modsel-128.xml (live test) (source)
- css3-modsel-128b.xml (live test) (source)
- css3-modsel-129.xml (live test) (source)
- css3-modsel-129b.xml (live test) (source)
- css3-modsel-13.xml (시각적 테스트) (source)
- css3-modsel-130.xml (시각적 테스트) (source)
- css3-modsel-130b.xml (시각적 테스트) (source)
- css3-modsel-131.xml (시각적 테스트) (source)
- css3-modsel-131b.xml (시각적 테스트) (source)
- css3-modsel-132.xml (시각적 테스트) (source)
- css3-modsel-132b.xml (시각적 테스트) (source)
- css3-modsel-133.xml (시각적 테스트) (source)
- css3-modsel-133b.xml (시각적 테스트) (source)
- css3-modsel-134.xml (live test) (source)
- css3-modsel-134b.xml (live test) (source)
- css3-modsel-135.xml (live test) (source)
- css3-modsel-135b.xml (live test) (source)
- css3-modsel-136.xml (live test) (source)
- css3-modsel-136b.xml (live test) (source)
- css3-modsel-137.xml (시각적 테스트) (source)
- css3-modsel-137b.xml (시각적 테스트) (source)
- css3-modsel-138.xml (시각적 테스트) (source)
- css3-modsel-138b.xml (시각적 테스트) (source)
- css3-modsel-139.xml (시각적 테스트) (source)
- css3-modsel-139b.xml (시각적 테스트) (source)
- css3-modsel-14.xml (시각적 테스트) (source)
- css3-modsel-140.xml (시각적 테스트) (source)
- css3-modsel-140b.xml (시각적 테스트) (source)
- css3-modsel-141.xml (live test) (source)
- css3-modsel-141b.xml (live test) (source)
- css3-modsel-142.xml (live test) (source)
- css3-modsel-142b.xml (live test) (source)
- css3-modsel-143.xml (live test) (source)
- css3-modsel-143b.xml (live test) (source)
- css3-modsel-144.xml (시각적 테스트) (source)
- css3-modsel-145a.xml (시각적 테스트) (source)
- css3-modsel-145b.xml (시각적 테스트) (source)
- css3-modsel-146a.xml (시각적 테스트) (source)
- css3-modsel-146b.xml (시각적 테스트) (source)
- css3-modsel-147a.xml (시각적 테스트) (source)
- css3-modsel-147b.xml (시각적 테스트) (source)
- css3-modsel-148.xml (live test) (source)
- css3-modsel-149.xml (live test) (source)
- css3-modsel-149b.xml (live test) (source)
- css3-modsel-14b.xml (live test) (source)
- css3-modsel-14c.xml (시각적 테스트) (source)
- css3-modsel-14d.xml (시각적 테스트) (source)
- css3-modsel-14e.xml (시각적 테스트) (source)
- css3-modsel-15.xml (시각적 테스트) (source)
- css3-modsel-150.xml (시각적 테스트) (source)
- css3-modsel-151.xml (live test) (source)
- css3-modsel-152.xml (live test) (source)
- css3-modsel-153.xml (시각적 테스트) (source)
- css3-modsel-154.xml (live test) (source)
- css3-modsel-155.xml (live test) (source)
- css3-modsel-155a.xml (live test) (source)
- css3-modsel-155b.xml (live test) (source)
- css3-modsel-155c.xml (live test) (source)
- css3-modsel-155d.xml (live test) (source)
- css3-modsel-156.xml (live test) (source)
- css3-modsel-156b.xml (live test) (source)
- css3-modsel-156c.xml (live test) (source)
- css3-modsel-157.xml (live test) (source)
- css3-modsel-158.xml (live test) (source)
- css3-modsel-159.xml (manual test) (source)
- css3-modsel-15b.xml (live test) (source)
- css3-modsel-16.xml (manual test) (source)
- css3-modsel-160.xml (live test) (source)
- css3-modsel-161.xml (manual test) (source)
- css3-modsel-166.xml (시각적 테스트) (source)
- css3-modsel-166a.xml (시각적 테스트) (source)
- css3-modsel-167.xml (시각적 테스트) (source)
- css3-modsel-167a.xml (시각적 테스트) (source)
- css3-modsel-168.xml (live test) (source)
- css3-modsel-168a.xml (live test) (source)
- css3-modsel-169.xml (live test) (source)
- css3-modsel-169a.xml (live test) (source)
- css3-modsel-17.xml (manual test) (source)
- css3-modsel-170.xml (live test) (source)
- css3-modsel-170a.xml (live test) (source)
- css3-modsel-170b.xml (live test) (source)
- css3-modsel-170c.xml (live test) (source)
- css3-modsel-170d.xml (live test) (source)
- css3-modsel-171.xml (시각적 테스트) (source)
- css3-modsel-172a.xml (live test) (source)
- css3-modsel-172b.xml (live test) (source)
- css3-modsel-173a.xml (live test) (source)
- css3-modsel-173b.xml (live test) (source)
- css3-modsel-174a.xml (시각적 테스트) (source)
- css3-modsel-174b.xml (시각적 테스트) (source)
- css3-modsel-175a.xml (live test) (source)
- css3-modsel-175b.xml (live test) (source)
- css3-modsel-175c.xml (live test) (source)
- css3-modsel-176.xml (live test) (source)
- css3-modsel-177a.xml (manual test) (source)
- css3-modsel-177b.xml (live test) (source)
- css3-modsel-178.xml (live test) (source)
- css3-modsel-179.xml (live test) (source)
- css3-modsel-179a.xml (시각적 테스트) (source)
- css3-modsel-18.xml (manual test) (source)
- css3-modsel-180a.xml (시각적 테스트) (source)
- css3-modsel-181.xml (시각적 테스트) (source)
- css3-modsel-182.xml (시각적 테스트) (source)
- css3-modsel-183.xml (시각적 테스트) (source)
- css3-modsel-184a.xml (live test) (source)
- css3-modsel-184b.xml (live test) (source)
- css3-modsel-184c.xml (live test) (source)
- css3-modsel-184d.xml (live test) (source)
- css3-modsel-184e.xml (live test) (source)
- css3-modsel-184f.xml (live test) (source)
- css3-modsel-18a.xml (manual test) (source)
- css3-modsel-18b.xml (manual test) (source)
- css3-modsel-18c.xml (manual test) (source)
- css3-modsel-19.xml (manual test) (source)
- css3-modsel-19b.xml (manual test) (source)
- css3-modsel-2.xml (시각적 테스트) (source)
- css3-modsel-20.xml (manual test) (source)
- css3-modsel-21.xml (manual test) (source)
- css3-modsel-21b.xml (시각적 테스트) (source)
- css3-modsel-21c.xml (시각적 테스트) (source)
- css3-modsel-22.xml (시각적 테스트) (source)
- css3-modsel-25.xml (시각적 테스트) (source)
- css3-modsel-27.xml (시각적 테스트) (source)
- css3-modsel-27a.xml (시각적 테스트) (source)
- css3-modsel-27b.xml (시각적 테스트) (source)
- css3-modsel-28.xml (시각적 테스트) (source)
- css3-modsel-28b.xml (시각적 테스트) (source)
- css3-modsel-29.xml (시각적 테스트) (source)
- css3-modsel-29b.xml (시각적 테스트) (source)
- css3-modsel-3.xml (시각적 테스트) (source)
- css3-modsel-30.xml (시각적 테스트) (source)
- css3-modsel-31.xml (시각적 테스트) (source)
- css3-modsel-32.xml (시각적 테스트) (source)
- css3-modsel-33.xml (시각적 테스트) (source)
- css3-modsel-34.xml (시각적 테스트) (source)
- css3-modsel-35.xml (시각적 테스트) (source)
- css3-modsel-36.xml (시각적 테스트) (source)
- css3-modsel-37.xml (시각적 테스트) (source)
- css3-modsel-38.xml (시각적 테스트) (source)
- css3-modsel-39.xml (시각적 테스트) (source)
- css3-modsel-39a.xml (시각적 테스트) (source)
- css3-modsel-39b.xml (시각적 테스트) (source)
- css3-modsel-39c.xml (시각적 테스트) (source)
- css3-modsel-3a.xml (시각적 테스트) (source)
- css3-modsel-4.xml (시각적 테스트) (source)
- css3-modsel-41.xml (시각적 테스트) (source)
- css3-modsel-41a.xml (시각적 테스트) (source)
- css3-modsel-42.xml (시각적 테스트) (source)
- css3-modsel-42a.xml (시각적 테스트) (source)
- css3-modsel-43.xml (시각적 테스트) (source)
- css3-modsel-43b.xml (시각적 테스트) (source)
- css3-modsel-44.xml (시각적 테스트) (source)
- css3-modsel-44b.xml (시각적 테스트) (source)
- css3-modsel-44c.xml (시각적 테스트) (source)
- css3-modsel-44d.xml (시각적 테스트) (source)
- css3-modsel-45.xml (시각적 테스트) (source)
- css3-modsel-45b.xml (시각적 테스트) (source)
- css3-modsel-45c.xml (시각적 테스트) (source)
- css3-modsel-46.xml (시각적 테스트) (source)
- css3-modsel-46b.xml (시각적 테스트) (source)
- css3-modsel-47.xml (시각적 테스트) (source)
- css3-modsel-48.xml (live test) (source)
- css3-modsel-49.xml (live test) (source)
- css3-modsel-5.xml (시각적 테스트) (source)
- css3-modsel-50.xml (시각적 테스트) (source)
- css3-modsel-51.xml (시각적 테스트) (source)
- css3-modsel-52.xml (시각적 테스트) (source)
- css3-modsel-53.xml (시각적 테스트) (source)
- css3-modsel-54.xml (live test) (source)
- css3-modsel-55.xml (live test) (source)
- css3-modsel-56.xml (live test) (source)
- css3-modsel-57.xml (시각적 테스트) (source)
- css3-modsel-57b.xml (시각적 테스트) (source)
- css3-modsel-59.xml (live test) (source)
- css3-modsel-6.xml (시각적 테스트) (source)
- css3-modsel-60.xml (live test) (source)
- css3-modsel-61.xml (manual test) (source)
- css3-modsel-62.xml (manual test) (source)
- css3-modsel-63.xml (manual test) (source)
- css3-modsel-64.xml (manual test) (source)
- css3-modsel-65.xml (manual test) (source)
- css3-modsel-66.xml (manual test) (source)
- css3-modsel-66b.xml (시각적 테스트) (source)
- css3-modsel-67.xml (시각적 테스트) (source)
- css3-modsel-7.xml (시각적 테스트) (source)
- css3-modsel-70.xml (시각적 테스트) (source)
- css3-modsel-72.xml (시각적 테스트) (source)
- css3-modsel-72b.xml (시각적 테스트) (source)
- css3-modsel-73.xml (시각적 테스트) (source)
- css3-modsel-73b.xml (시각적 테스트) (source)
- css3-modsel-74.xml (시각적 테스트) (source)
- css3-modsel-74b.xml (시각적 테스트) (source)
- css3-modsel-75.xml (시각적 테스트) (source)
- css3-modsel-75b.xml (시각적 테스트) (source)
- css3-modsel-76.xml (시각적 테스트) (source)
- css3-modsel-76b.xml (시각적 테스트) (source)
- css3-modsel-77.xml (시각적 테스트) (source)
- css3-modsel-77b.xml (시각적 테스트) (source)
- css3-modsel-78.xml (시각적 테스트) (source)
- css3-modsel-78b.xml (시각적 테스트) (source)
- css3-modsel-79.xml (시각적 테스트) (source)
- css3-modsel-7b.xml (live test) (source)
- css3-modsel-8.xml (시각적 테스트) (source)
- css3-modsel-80.xml (시각적 테스트) (source)
- css3-modsel-81.xml (시각적 테스트) (source)
- css3-modsel-81b.xml (시각적 테스트) (source)
- css3-modsel-82.xml (시각적 테스트) (source)
- css3-modsel-82b.xml (시각적 테스트) (source)
- css3-modsel-83.xml (live test) (source)
- css3-modsel-86.xml (시각적 테스트) (source)
- css3-modsel-87.xml (live test) (source)
- css3-modsel-87b.xml (live test) (source)
- css3-modsel-88.xml (시각적 테스트) (source)
- css3-modsel-88b.xml (시각적 테스트) (source)
- css3-modsel-89.xml (시각적 테스트) (source)
- css3-modsel-9.xml (시각적 테스트) (source)
- css3-modsel-90.xml (live test) (source)
- css3-modsel-90b.xml (live test) (source)
- css3-modsel-91.xml (시각적 테스트) (source)
- css3-modsel-92.xml (시각적 테스트) (source)
- css3-modsel-93.xml (시각적 테스트) (source)
- css3-modsel-94.xml (시각적 테스트) (source)
- css3-modsel-94b.xml (시각적 테스트) (source)
- css3-modsel-95.xml (시각적 테스트) (source)
- css3-modsel-96.xml (시각적 테스트) (source)
- css3-modsel-96b.xml (시각적 테스트) (source)
- css3-modsel-97.xml (시각적 테스트) (source)
- css3-modsel-97b.xml (시각적 테스트) (source)
- css3-modsel-98.xml (시각적 테스트) (source)
- css3-modsel-98b.xml (시각적 테스트) (source)
- css3-modsel-99.xml (live test) (source)
- css3-modsel-99b.xml (live test) (source)
- css3-modsel-d1.xml (시각적 테스트) (source)
- css3-modsel-d1b.xml (시각적 테스트) (source)
- css3-modsel-d2.xml (시각적 테스트) (source)
- css3-modsel-d3.xml (시각적 테스트) (source)
- css3-modsel-d4.xml (시각적 테스트) (source)
Tests that do not relate to any section
- eof-right-after-selector-crash.html (live test) (source)
- eof-some-after-selector-crash.html (live test) (source)
- hash-collision.html (live test) (source)
- invalid-pseudos.html (live test) (source)
- selector-after-font-family.html (live test) (source)
3. 선택자 문법 및 구조
3.1. 구조와 용어
선택자는 트리 구조 내에서 특정한 요소(들)의 패턴을 표현합니다. 선택자라는 용어는 단순 선택자, 복합 선택자, 복합적 선택자, 또는 선택자 목록을 모두 지칭할 수 있습니다. 선택자의 주체란, 해당 선택자가 정의상 대상으로 삼는 모든 요소를 의미합니다; 즉, 그 선택자와 일치하는 선택자인 모든 요소를 말합니다.
단순 선택자는 하나의 요소에 대한 단일 조건입니다. 타입 선택자, 범용 선택자, 속성 선택자, 클래스 선택자, ID 선택자, 또는 가상 클래스는 단순 선택자입니다. (이는 선택자 <simple-selector>로 문법에서 표현됩니다.) 주어진 요소는 이 명세와 문서 언어의 규정에 따라 단순 선택자가 요소를 정확히 설명할 때 그 단순 선택자와 일치한다고 합니다.
복합 선택자는 단순 선택자 여러 개가 결합자 없이 연속적으로 나열될 때를 말하며, 단일 요소에 대한 여러 조건을 동시에 표현합니다. 타입 선택자 또는 범용 선택자가 포함된다면, 반드시 앞에 와야 합니다. 타입 선택자 또는 범용 선택자는 시퀀스에 한 개만 허용됩니다. (복합 선택자는 문법에서 <compound-selector>로 표현됩니다.) 주어진 요소가 복합 선택자 내 모든 단순 선택자를 동시에 만족하면 그 복합 선택자와 일치한다고 합니다.
참고: 공백은 자손 결합자를 의미하므로, 복합 선택자 내 단순 선택자 사이에는 공백이 허용되지 않습니다.
의사-복합 선택자란, 의사요소 선택자에 선택적으로 추가 가상 클래스 선택자를 뒤따라 붙이거나, 앞에 복합 선택자나 또 다른 의사-복합 선택자를 붙일 수 있고, 결합자는 사용하지 않은 경우를 의미합니다. (문법에서는 <pseudo-compound-selector>로 표기됩니다.) 의사요소가 의사-복합 선택자와 일치한다고 하는 경우: 지정된 의사요소 이름을 가지며, 추가된 가상 클래스 조건도 만족하고, 인접한 바로 앞 선택자가 나타내는 기원 요소도 존재해야 합니다. 앞에 아무 선택자도 없다면, 범용 선택자가 암묵적으로 적용된 것과 같습니다. (예시: .foo ::before는 .foo *::before와 같으며, .foo::before와는 다릅니다.)
참고: 의사-복합 선택자는 복합 선택자가 아니며, 오로지 복합 선택자를 기대하는 부분에 쓸 수 없습니다. 의사-복합 선택자는 마치 자신만의 결합자를 가진 것처럼 동작하며, 자신과 기원 요소 사이의 관계를 나타냅니다. 이는 > 결합자가 상위 요소와의 관계를 표현하는 것과 유사합니다.
결합자란,
양쪽에 오는 복합 선택자 간의 관계 조건을 나타냅니다.
Selectors Level 4에서의 결합자는:
자손 결합자 (공백),
자식 결합자
(U+003E, >),
바로 다음 형제
결합자 (U+002B, +),
이후
형제 결합자 (U+007E, ~) 등이 있습니다.
두 요소가 그 사이의 관계 조건을 만족하면 그 결합자와 일치한다고 합니다.
복합적 선택자란, 하나 이상의 복합 선택자 또는 의사-복합 선택자가, 복합 선택자들 사이에 결합자를 두고 연속된 시퀀스입니다. 이것은 일련의 요소에서 결합자가 정의하는 특정 관계에 따라 각 요소에 동시적으로 적용되는 조건 모음을 나타냅니다. (문법에서 <complex-selector>로 표시됩니다.) 주어진 요소 또는 의사요소가 그 시퀀스 최종 복합/의사-복합 선택자에 일치하고, 앞선 모든 단위도 연이어 각 요소 또는 의사요소에 맞게 일치하며, 각 유닛은 결합자 또는 의사-복합 선택자의 적절한 기원 요소 관계에 맞는 경우 복합적 선택자와 일치한다고 합니다.
.ancestor > .foo.bar는 이러한 요소 중 부모 요소 (여기서 > 결합자로 표시됨) 가 "ancestor" 클래스를 가진 경우에만 일치한다.
.foo.bar::before는 ::before 의사-요소와 일치하며, 그 출발 요소가 .foo.bar와 일치해야 한다.
단순/복합/복합 선택자들의 목록은 콤마로 구분된 단순, 복합, 또는 복잡 선택자들의 목록이다. 타입이 주변 서술에서 중요하지 않거나 명시된 경우에는 보통 선택자 목록이라고만 부른다; 타입이 중요하지만 명시되지 않았을 때는, 기본적으로 복잡 선택자 목록을 의미한다. (§ 4.1 선택자 목록에서 선택자 목록과 문법의 다양한 <*-selector-list> 생성들에 대해 추가 정보를 볼 수 있다.) 지정된 요소가 선택자 목록의 선택자들 중 아무 하나(최소 한 개)와 일치할 때, 그 요소가 해당 선택자 목록과 일치한다고 한다.
3.2. 데이터 모델
선택자는 DOM과 같은 요소 트리에 대해 평가됩니다. [DOM] 이 명세서 내에서는 이를 "문서 트리" 또는 "소스 문서"라고 부를 수 있습니다.
각 요소는 아래 다섯 가지 특성을 가질 수 있으며, 이 모든 특성은 문자열 형태로 선택자로 매칭이 가능합니다:
- 요소의 타입(태그 이름).
- 요소의 네임스페이스.
- ID.
- 소속된 클래스들(명명된 그룹들).
- 속성(이름-값 쌍).
많은 선택자는 문서 언어(즉, 문서 트리의 언어 및 의미) 또는 호스트 언어(즉, 선택자 문법을 사용하는 상위 언어)의 의미에 의존합니다. 예를 들어, :lang() 선택자는 문서 언어(예: HTML)에서 요소가 어떤 언어와 연관되는지 정의하는 방식에 따라 동작합니다. 또 다른 예로, ::first-line 의사요소는 호스트 언어(예: CSS)에서 ::first-line 의사요소가 무엇을 나타내며 어떤 역할을 하는지 정의합니다.
3.2.1. 특성 없는 요소
테스트
개별 요소는 위의 어떤 기능도 없을 수 있지만, 일부 요소는 특징 없음(featureless)입니다. 특징 없음(featureless)인 요소는 어떤 선택자와도 절대 일치하지 않습니다, 단, 아래의 경우는 예외입니다:
-
단순 선택자(simple selector) 중 명시적으로 일치하도록 정의된 것
-
복합 선택자(compound selector)의 경우, 포함된 모든 단순 선택자가 일치하도록 허용된 경우
-
복잡 선택자(complex selector)의 경우, 복합 선택자가 주체(subject)를 대상으로 하여 일치하도록 허용된 경우
-
선택자 목록(selector lists)의 경우, 목록 중 적어도 하나의 선택자가 일치하도록 허용된 경우
-
논리 결합 가상 클래스의 경우, 해당 인자 선택자가 일치하도록 허용된 경우
-
:has() 가상 클래스의 경우, 해당 복합 선택자 안에 다른 단순 선택자가 최소 하나 포함되어 있고, 그것이 일치하도록 허용된 경우에만 해당합니다.
만약 선택자가 특징 없음 요소와 일치할 수 있을 경우, 단지 기본 네임스페이스 [CSS-NAMESPACES-3](특징 없음 요소는 다르게 정의되지 않는 한 네임스페이스가 없으므로) 때문이라면, 기본 네임스페이스는 일치를 막지 않습니다.
:not(.foo:host)와 같은 논리 조합도 호스트 요소와는 절대 일치하지 않습니다 ("foo" 클래스를 가지지 않더라도), 그 이유는 .foo:host 내부의 모든 단순 선택자가 섀도우 호스트와 일치하도록 허용되지 않기 때문입니다.
비슷하게, :not(:host > .foo) 도 섀도우 호스트와 절대 일치하지 않습니다. 비록 섀도우 호스트가 실제로 자기 자신의 후손이 아니고 "foo" 클래스를 가지지 않더라도, 복잡 선택자 인자(.foo)의 주체는 섀도우 호스트와 일치하도록 허용되지 않기 때문입니다.
위의 :has() 규칙 또한 유사하게 동작합니다. 섀도우 호스트 내부에 .foo 자손이 있더라도, :has(.foo)는 일치하지 않으며, 이는 나머지 복합 선택자 (비어 있음)가 호스트와 일치할 수 있는 단순 선택자를 포함하지 않기 때문입니다. 호스트 요소와 일치시키려면 :host:has(.foo)를 사용해야 합니다.
3.3. 범위 지정 선택자(Scoped Selectors)
일부 호스트 애플리케이션은 선택자를 특정 문서의 하위 트리나 조각에 범위 제한(scope)할 수 있습니다. 범위 트리의 루트는 범위 루트(scoping root)라고 부릅니다.
선택자가 범위 제한 된 경우, 해당 선택자가 일치하는 요소는 반드시 범위 루트의 후손이어야 합니다. (나머지 선택자는 제한받지 않고 일치할 수 있으며, 단지 마지막으로 일치하는 요소만 범위 안에 있어야 합니다.)
querySelector() 메서드는 [DOM]에서 정의되어 있고,
작성자가 범위 제한 선택자를
기준 요소에 따라 평가할 수 있게 해줍니다.
widget와 같은
호출은
a
요소를 widget 요소 내부에서만 찾고,
문서 전체에 흩어져 있을 수 있는
a
요소를 무시하게 됩니다.
3.4. 상대 선택자(Relative Selectors)
특정 컨텍스트에서는 상대 선택자(relative selectors)를 허용하는데, 이는 하나 이상의 상대 선택자 기준 요소(anchor elements)에 상대적인 요소를 나타내는 선택자의 축약형입니다. 상대 선택자는 결합자(combinator)로 시작되며, 선택자의 시작 부분에 기준(anchor) 요소가 암시적으로 생략되어 있습니다. (결합자가 없으면, 하위 결합자(descendant combinator)가 암시적으로 적용됩니다.)
상대 선택자는 선택자 문법에서 <relative-selector>로 표기하며, 여러 개의 목록은 <relative-selector-list>로 표기합니다.
3.5. 가상 클래스(Pseudo-classes)
가상 클래스(pseudo-classes)는 단순 선택자의 일종이며 문서 트리 밖의 정보에 기반해 선택이 가능하게 하거나, 다른 단순 선택자로는 표현하기 어렵거나 불가능한 경우를 허용합니다. 또한 동적으로 작동할 수 있으며, 사용자가 문서와 상호작용하는 동안 요소가 가상 클래스를 획득하거나 잃을 수 있지만, 문서 자체는 변경되지 않습니다. 가상 클래스는 문서 소스나 문서 트리에 나타나지도 않고, 이를 수정하지도 않습니다.
가상 클래스의 문법은 ":" (U+003A COLON) 뒤에 가상 클래스의 이름을 CSS 식별자(identifier)로 적고, 함수형 가상 클래스(functional pseudo-class)의 경우, 괄호( ) 안에 인자를 넣습니다.
예를 들어, :valid는 일반 가상 클래스이고, :lang()은 함수형 가상 클래스(functional pseudo-class)입니다.
모든 CSS 키워드와 마찬가지로, 가상 클래스 이름은 ASCII 대소문자 구분 없음입니다. 공백은 콜론과 가상 클래스 이름 사이에 허용되지 않으며, (CSS 문법에서 통상적으로) 함수형 가상 클래스 이름과 그 괄호 사이 역시 공백이 없으며, (따라서 CSS 함수 토큰을 형성합니다.) 마찬가지로 괄호 안 인자 주위에는 별도 명시 없으면 공백이 허용됩니다.
다른 단순 선택자와 마찬가지로, 가상 클래스는 선택자 내 모든 복합 선택자에 들어갈 수 있으며, 반드시 타입 선택자 혹은 범용 선택자(universal selector) 뒤에 위치해야 합니다 (존재하는 경우).
참고: 일부 가상 클래스는 서로 동시에 쓸 수 없고 (복합 선택자에 포함되더라도 유효하나 어떤 것과도 일치하지 않음), 다른 것들은 동일 요소에 동시에 적용될 수 있습니다.
3.6. 가상 요소(Pseudo-elements)
특정 의사-클래스가 문서 트리에 직접 존재하지 않는 추가 상태 정보를 나타내는 것과 비슷하게, 의사-요소는 문서 트리에 직접 존재하지 않는 요소를 나타낸다. 이들은 문서 트리가 제공하는 것 그 이상으로 문서 트리에 대한 추상화를 생성하는 데 사용된다. 예를 들어, 의사-요소는 문서 언어의 요소에 해당하지 않는 문서의 부분(요소 경계에 맞지 않거나 트리 구조 내에 포함되지 않는 범위 등)을 선택하는 데 사용할 수 있다; 문서 트리에 존재하지 않거나 문서 트리의 대체 투영에 존재하는 콘텐츠를 나타내는 데 사용할 수 있다; 또는 문서 트리에 반영되지 않는 스타일링, 레이아웃, 사용자 상호작용, 기타 처리 과정에 의해 제공되는 정보에 의존할 수도 있다.
가상 요소는 또한 소스 문서에 전혀 존재하지 않는 내용도 나타낼 수 있습니다. 예를 들어 ::before 및 ::after 가상 요소는 어떤 요소의 콘텐츠 앞이나 뒤에 추가 콘텐츠를 삽입할 수 있게 해줍니다.
가상 클래스와 마찬가지로, 가상 요소는 문서 소스나 문서 트리에서 등장하지 않으며, 이를 변경하지 않습니다. 그러므로 구조적 가상 클래스(structural pseudo-classes)나 해당 기원 요소(originating element) 혹은 그 트리와 관련된 다른 선택자 해석에 영향을 주지 않습니다.
호스트 언어에서 어떤 가상 요소가 존재하는지, 그 타입과 능력을 정의합니다. CSS에 존재하는 가상 요소들은 [CSS21] (2단계), [SELECT] (3단계), [CSS-PSEUDO-4] (4단계) 등에서 정의되어 있습니다.
3.6.1. 문법
가상 요소의 문법은 "::" (콜론 U+003A 문자 2개) 뒤에 가상 요소의 이름을 식별자(identifier)로 작성합니다. 함수형 가상 요소(functional pseudo-element)의 경우, 괄호 ( ) 안에 인자를 포함합니다. 가상 요소의 이름은 ASCII 대소문자 구분 없음입니다. 두 콜론 사이, 콜론과 이름 사이에는 공백이 허용되지 않습니다.
CSS Level 1 와 CSS Level 2에서는 단일 콜론 문법으로 가상 클래스와 가상 요소가 혼합되었으므로, 사용자 에이전트는 1·2단계 가상 요소(::before, ::after, ::first-line, ::first-letter)에 대해 예전의 1콜론 표기법도 허용해야 합니다. 이 호환성 표기법은 다른 가상 요소에는 허용되지 않습니다. 단, 이 문법은 더 이상 권장되지 않으므로, 작성자는 Level 3 이상에서는 2중 콜론 문법을 사용해야 합니다.
가상 요소는 특징 없음(featureless)이므로, 다른 어떤 선택자로도 선택할 수 없습니다.
3.6.2. 문서 트리와의 결합
가상 요소는 트리에서 독립적으로 존재하지 않습니다: 항상 페이지의 다른 요소에 결합되어 있는데, 이것을 기원 요소(originating element)라 부릅니다. 문법적으로, 가상 요소는 바로 앞의 복합 선택자가 해당 기원 요소를 나타냅니다. 복합 선택자가 생략된 경우에는 범용 선택자(universal selector) *가 기본값으로 간주됩니다.
선택자 ::first-line은 *::first-line과 같으며, 문서 내 모든 요소의 ::first-line 가상 요소를 선택합니다.
선택자에 의사-요소가 등장하면, 해당 의사-요소 앞에 있는 선택자 부분은 출발 요소를 선택하며, 의사-요소 뒤에 선택자 부분이 있다면, 그 부분은 의사-요소 자체에 적용된다. (아래 참조.)
3.6.3. 가상 요소에 가상 클래스 적용
특정 가상 요소는 특정 가상 클래스를 조합하여 바로 뒤에 붙일 수 있습니다. 이때 가상 요소는 해당 상태에서만 표현됩니다. 이 명세에서는 모든 가상 요소에 대해 논리 결합 가상 클래스와 사용자 동작 가상 클래스(user action pseudo-classes)의 조합을 허용합니다. 기타 명세에서 특정 가상 클래스의 조합이 가능한 가상 요소를 추가로 정의할 수도 있습니다. 명시적으로 허용되지 않은 조합은 잘못된 선택자(invalid selector)입니다.
참고: 논리 결합 가상 클래스는 위치상 제한에 대한 유효성 검사를 인자 쪽으로 위임합니다.
::first-line:hover와 :hover::first-line의 차이에 유의하십시오. :hover::first-line은 hover된 기원 요소의 첫 줄만과 일치하는데, 예를 들어, :hover::first-line은 p 요소의 두 번째 줄이 hover되어 있을 때도 첫 줄에 일치하지만, ::first-line:hover는 오직 첫 줄이 실제로 hover된 경우에만 일치합니다.
3.6.4. 하위 가상 요소(Sub-pseudo-elements)
일부 가상 요소는 다른 가상 요소의 기원 요소가 될 수도 있습니다. 이를 하위 가상 요소(sub-pseudo-element)라고 하고, 이때의 상위 가상 요소는 기원 가상 요소(originating pseudo-element)입니다. 예를 들어, ::before에 list-item display 타입을 주면, 그 기원 가상 요소의 하위 가상 요소로 ::before::marker sub-pseudo-element가 생깁니다.
명확히 해야 할 때는 최종 기원 요소(ultimate originating element)라는 용어를 사용하며, 이는 어떤 가상 요소가 실제로 유래한 진짜(비가상) 요소를 의미합니다.
해당 하위 가상 요소가 다른 명세에서 명확히 존재한다고 정의된 경우가 아니면, 가상 요소 선택자 끼리 조합하는 것은 유효하지 않습니다. 예를 들어 ::before::before는 잘못된 선택자이지만, ::before::marker는 (해당 ::before::marker 하위 가상 요소를 지원하는 구현에서는) 올바른 선택자입니다.
3.6.5. 내부 구조
일부 가상 요소는 내부 구조를 가지고 있다고 정의되어 있습니다. 이런 가상 요소는 자식/후손 결합자(child/descendant combinator)로 관계를 표현할 수 있습니다. 가상 요소 뒤에 결합자(combinator)가 오는 선택자는 그 외에는 올바르지 않습니다.
참고: 미래의 명세에서 기존 가상 요소의 기능이 확장되어, 지금은 잘못된 선택자인 (::first-line :any-link 등) 것도 향후 유효해질 수 있습니다.
이런 가상 요소의 자식은 다른 요소의 자식이기도 할 수 있습니다. 다만, 적어도 CSS에서는 box 트리의 트리 구조성을 유지하도록 렌더링이 정의되어야 합니다.
3.7. 문자 및 대소문자 구분
테스트
모든 Selector 문법은 ASCII 대소문자 구분 없음(즉, [a-z]와 [A-Z]는 동일)입니다. 단, Selector가 제어하지 않는 부분은 예외입니다: 즉, 문서 언어에서 요소 이름, 속성 이름, 속성 값의 대소문자 구분 여부는 문서 언어에 따라 다릅니다.
네임스페이스 접두사의 대소문자 구분은 [CSS3NAMESPACE]에서 정의합니다. 언어 범위(language ranges)의 대소문자 구분은 :lang() 항목에서 설명합니다.
Selector에서의 공백(white space)은 다음 문자를 포함합니다: SPACE(U+0020), TAB(U+0009), LINE FEED(U+000A), CARRIAGE RETURN(U+000D), FORM FEED(U+000C). EM SPACE(U+2003), IDEOGRAPHIC SPACE(U+3000)와 같은 다른 공백 유사 문자는 구문상 공백으로 간주하지 않습니다.
Selector에서의 코드 포인트는 CSS와 동일한 이스케이프 규칙에 따라
백슬래시로 이스케이프할 수 있습니다. [CSS21] 코드 포인트를 이스케이프하면,
Selector 내에서 그 문자가
가진 특별한 의미가 "무효화"됩니다.
예를 들어, 선택자 #foo>a는 결합자를 포함하지만,
#foo\>a는 id가 foo>a인 요소를 선택합니다.
3.8. 네임스페이스 접두사 선언
특정 선택자는 네임스페이스 접두사를 지원합니다. 네임스페이스 접두사를 선언하는 방법은 Selector를 사용하는 언어에서 명시해야 합니다. 언어가 접두사 선언 방법을 따로 지정하지 않은 경우, 접두사는 선언되지 않은 것으로 간주합니다. CSS에서는 네임스페이스 접두사를 @namespace 규칙으로 선언할 수 있습니다. [CSS3NAMESPACE]
3.9. 잘못된 선택자와 오류 처리
테스트
사용자 에이전트는 잘못된 선택자(invalid selector) 처리 규칙을 따라야 합니다:
- 선택자에 구문 분석 오류가 있을 경우, 예를 들어 인식되지 않는 토큰이 있거나 해당 위치에서 허용되지 않는 토큰이 있는 경우 (전체 § 16 문법과 개별 선택자 문법 정의 참고), 해당 선택자는 잘못된 것으로 간주합니다.
- 선언되지 않은 네임스페이스 접두사가 포함된 단순 선택자는 잘못된 것으로 간주합니다.
- 잘못된 단순 선택자, 잘못된 결합자, 잘못된 토큰이 포함된 선택자는 잘못된 것으로 간주합니다.
- 잘못된 선택자가 포함된 선택자 목록도 잘못된 것으로 간주합니다.
- 빈 선택자, 즉 복합 선택자가 포함되지 않은 선택자도 잘못된 것으로 간주합니다.
참고: CSS의 하위 호환 구문 분석 원칙에 따라, UA는 반드시 지원이 불충분한 가상 클래스, 가상 요소, 결합자, 그 외 문법 요소는 잘못된 것으로 처리해야 합니다. 부분 구현 항목 참조.
잘못된 선택자는 아무것도 나타내지 않으며, 따라서 어떤 요소와도 일치하지 않습니다.
3.10. 레거시 별칭(Legacy Aliases)
일부 선택자는 레거시 선택자 별칭(legacy selector alias)을 갖습니다. 이는 파싱 시 표준 이름으로 변환되는 이름으로, (따라서 선택자를 나타내는 어떤 객체 모델에도 별칭이 나타나지 않습니다.)
4. 논리 조합(Logical Combinations)
테스트
선택자 논리는 복합(논리 AND), 선택자 목록(논리 OR), 그리고 논리 조합 가상 클래스(logical combination pseudo-classes)인 :is()·:where()·:not()로 조작할 수 있습니다. 논리 조합 가상 클래스는 다른 가상 클래스가 허용되는 모든 곳에 허용됩니다. 단, 제한 조건은 인자 쪽에 그대로 전달됩니다. (예를 들어, 복합 선택자만 허용되는 위치라면, 복합 선택자만 :is() 안에서 허용됩니다.)
참고: :is()와 :where() 안에서 잘못된 인자는 가상 클래스 전체를 무효화하지 않고 삭제되므로, 맥락적으로 무효화된 인자도 :is() 전체를 무효화하지 않습니다.
4.1. 선택자 목록(Selector Lists)
쉼표로 구분한 선택자 목록은 그 선택자 목록 내 모든 개별 선택자로 선택되는 요소들의 합집합을 나타냅니다. (쉼표는 U+002C.) 예를 들어, CSS에서 여러 선택자가 동일 선언을 가진다면 쉼표 목록으로 묶을 수 있습니다. 쉼표 앞뒤에는 공백을 둘 수 있습니다.
h1 { font-family: sans-serif }
h2 { font-family: sans-serif }
h3 { font-family: sans-serif }
은 다음과 같습니다:
h1, h2, h3 { font-family: sans-serif }
경고: 이 예에서의 동등성은 모든 선택자가 유효한 선택자이기 때문에 성립합니다. 세 개 중 하나라도 잘못된 선택자라면 전체 선택자 목록이 무효가 됩니다. 이렇게 되면 세 개의 heading 요소에 대한 규칙 전체가 무효가 되지만, 각자 따로 썼을 경우엔 그중 하나 규칙만 무효가 됩니다.
h1 { font-family: sans-serif }
h2..foo { font-family: sans-serif }
h3 { font-family: sans-serif }
은 다음과 다릅니다:
h1, h2..foo, h3 { font-family: sans-serif }
왜냐하면 위 선택자(h1, h2..foo, h3)는 전체가 무효라 스타일 규칙도 통째로 버려지기 때문입니다. (선택자가 따로일 경우 h2..foo에 해당하는 규칙만 버려집니다.)
4.2. 여러 항목과 일치하는 가상 클래스: :is()
테스트
- is.html (live test) (source)
- is-default-ns-001.html (live test) (source)
- is-default-ns-002.html (live test) (source)
- is-default-ns-003.html (live test) (source)
- is-default-ns-002.html (live test) (source)
- is-default-ns-003.html (live test) (source)
- is-nested.html (live test) (source)
- is-specificity-shadow.html (live test) (source)
- is-specificity.html (live test) (source)
- is-where-basic.html (live test) (source)
- is-where-error-crash.html (live test) (source)
- is-where-error-recovery.html (live test) (source)
- is-where-not.html (live test) (source)
- is-where-pseudo-classes.html (live test) (source)
- is-where-pseudo-elements.html (live test) (source)
- is-where-shadow.html (live test) (source)
- is-where-visited.html (live test) (source)
- parse-is-where.html (live test) (source)
- parse-is.html (live test) (source)
- query-is.html (live test) (source)
매치-애니 가상 클래스(:is())는 <forgiving-selector-list>를 유일한 인자로 받는 함수형 가상 클래스입니다.
인자를 파싱한 뒤, 빈 목록이면 해당 가상 클래스는 유효하지만 어떤 것도 일치하지 않습니다. 그렇지 않으면, 해당 가상 클래스는 목록 내 선택자 중 하나라도 일치하는 요소 모두와 일치합니다.
참고:
:is() 가상 클래스의
특이성은
인자 중 가장 특이성이 큰 값으로 대체됩니다.
따라서 :is()로 작성한 선택자가
:is() 없이 쓴 것과 특이성이 반드시 같지는 않습니다.
예를 들어 :is(ul, ol, .list) > [hidden]과
ul > [hidden], ol > [hidden], .list > [hidden]이 있을 때,
ol의
[hidden] 자식은 앞 선택자에는 특이성 (0,2,0)으로, 뒤 선택자에는 (0,1,1)로 일치합니다.
§ 15 선택자 특이성 계산 참고.
의사-요소는 matches-any 의사-클래스로 표현할 수 없다; 이들은 :is() 내부에서 유효하지 않다.
기본 네임스페이스 선언은, 어떤 선택자의 주체(subject)를 나타내는 복합 선택자에 영향을 주지 않습니다. 단, 해당 복합 선택자에 명시적 범용 선택자 또는 타입 선택자가 있을 때는 예외입니다.
*|*:is(:hover, :focus)
아래 선택자는 명시적으로 :is() 안에 범용 선택자를 사용했으므로, 기본 네임스페이스 내에서 hover 또는 focus된 요소에만 일치합니다:
*|*:is(*:hover, *:focus)
이 명세의 이전 초안에서는 이 가상 클래스 명칭을 :matches()로 사용하기도 하였으므로,
UA는 필요하다면 레거시 선택자
별칭으로서
:is() 대신
:matches()도 구현할 수 있습니다(하위 호환성 목적).
4.3. 부정(매치-없음) 가상 클래스: :not()
테스트
- not-001.html (live test) (source)
- not-002.html (live test) (source)
- not-complex.html (live test) (source)
- not-default-ns-001.html (live test) (source)
- not-default-ns-002.html (live test) (source)
- not-default-ns-003.html (live test) (source)
- not-links.html (live test) (source)
- not-specificity.html (live test) (source)
- parse-not.html (live test) (source)
- query-where.html (live test) (source)
부정 가상 클래스(:not())는 <complex-real-selector-list>를 인자로 받는 함수형 가상 클래스입니다. 인자로 받은 선택자에 의해 표현되지 않는 요소를 나타냅니다.
참고: Selector Level 3에서는 단순 선택자 한 개만 :not()의 인자로 허용되었습니다.
참고: :not() 가상 클래스의 특이성은 인자 중 가장 특이성이 높은 선택자의 특이성으로 대체되며, 따라서 :not(:is(argument))와 정확히 동일하게 동작합니다. § 15 선택자 특이성 계산 참고.
가상 요소는 부정 가상 클래스에서 표현될 수 있으며, :not() 내에서는 유효하지 않습니다.
button:not([DISABLED])
다음 선택자는 FOO 요소를 제외한 모든 요소와 일치합니다.
*:not(FOO)
다음 복합 선택자는 링크를 제외한 모든 HTML 요소와 일치합니다.
html|*:not(:link):not(:visited)
:is()와 마찬가지로, 기본 네임스페이스 선언은 주체(subject)를 나타내는 복합 선택자에 영향을 주지 않습니다. 단, 해당 복합 선택자에 명시적으로 범용 선택자 또는 타입 선택자가 포함되어 있을 때는 예외입니다. (예시는 :is() 참고.)
참고: :not() 가상 클래스를 사용해 쓸모없는 선택자를 만들 수 있습니다. 예를 들어, :not(*|*)는 어떤 요소와도 일치하지 않고, div:not(span)은 div와 같지만 특이성은 더 높습니다.
4.4. 특이성 조정 가상 클래스: :where()
테스트
특이성 조정 의사-클래스인 :where()는 :is()와 동일한 문법과 기능을 가지는 함수형 의사-클래스이다. :is()와 달리, :where() 의사-클래스와 그 인자들은 선택자의 특이성에 어떤 기여도 하지 않는다—즉, 특이성은 항상 0이다.
이것은 선택자에서 필터를 도입하면서도 관련 스타일 선언의 우선순위를 쉽게 재정의할 수 있게 해주어 유용합니다.
a:not(:hover) {
text-decoration: none;
}
nav a {
/* 효과 없음 */
text-decoration: underline;
}
하지만 :where()를 사용하면 작성자가 자신의 의도를 명확히 선언할 수 있습니다:
a:where(:not(:hover)) {
text-decoration: none;
}
nav a {
/* 이제 동작함! */
text-decoration: underline;
}
참고: Selector의 향후 단계에서는 해당 가상 클래스 인스턴스의 특이성을 명시적으로 지정하는 추가 인자를 도입할 수 있습니다.
4.5. 관계형 가상 클래스: :has()
테스트
- has-argument-with-explicit-scope.html (live test) (source)
- has-basic.html (live test) (source)
- has-display-none-checked.html (live test) (source)
- has-focus-display-change.html (live test) (source)
- has-matches-to-uninserted-elements.html (live test) (source)
- has-nth-of-crash.html (live test) (source)
- has-relative-argument.html (live test) (source)
- has-sibling-chrome-crash.html (live test) (source)
- has-specificity.html (live test) (source)
- has-style-sharing-001.html (live test) (source)
- has-style-sharing-002.html (live test) (source)
- has-style-sharing-003.html (live test) (source)
- has-style-sharing-004.html (live test) (source)
- has-style-sharing-005.html (live test) (source)
- has-style-sharing-006.html (live test) (source)
- has-style-sharing-007.html (live test) (source)
- has-style-sharing-pseudo-001.html (live test) (source)
- has-style-sharing-pseudo-002.html (live test) (source)
- has-style-sharing-pseudo-003.html (live test) (source)
- has-style-sharing-pseudo-004.html (live test) (source)
- has-style-sharing-pseudo-005.html (live test) (source)
- has-style-sharing-pseudo-006.html (live test) (source)
- has-style-sharing-pseudo-007.html (live test) (source)
- has-style-sharing-pseudo-008.html (live test) (source)
- has-visited.html (live test) (source)
- attribute-or-elemental-selectors-in-has.html (live test) (source)
- child-indexed-pseudo-classes-in-has.html (live test) (source)
- has-pseudoclass-only-crash.html (live test) (source)
- defined-in-has.html (live test) (source)
- dir-pseudo-class-in-has.html (live test) (source)
- empty-pseudo-in-has.html (live test) (source)
- fullscreen-pseudo-class-in-has.html (live test) (source)
- has-append-first-node.html (live test) (source)
- has-complexity.html (live test) (source)
- has-css-nesting-shared.html (live test) (source)
- has-in-adjacent-position.html (live test) (source)
- has-in-ancestor-position.html (live test) (source)
- has-in-parent-position.html (live test) (source)
- has-in-sibling-position.html (live test) (source)
- has-invalidation-after-removing-non-first-element.html (live test) (source)
- has-invalidation-first-in-sibling-chain.html (live test) (source)
- has-invalidation-for-wiping-an-element.html (live test) (source)
- has-nested-pseudo-001-crash.html (live test) (source)
- has-nested-pseudo-002-crash.html (live test) (source)
- has-nested-pseudo-003-crash.html (live test) (source)
- has-pseudo-element.html (live test) (source)
- has-pseudoclass-only.html (live test) (source)
- has-sibling-insertion-removal.html (live test) (source)
- has-sibling.html (live test) (source)
- has-side-effect.html (live test) (source)
- has-unstyled.html (live test) (source)
- has-with-is-child-combinator.html (live test) (source)
- has-with-nesting-parent-containing-complex.html (live test) (source)
- has-with-nesting-parent-containing-hover.html (live test) (source)
- has-with-not.html (live test) (source)
- has-with-nth-child-sibling-remove.html (live test) (source)
- has-with-nth-child.html (live test) (source)
- has-with-pseudo-class.html (live test) (source)
- host-context-pseudo-class-in-has.html (live test) (source)
- host-has-shadow-tree-element-at-nonsubject-position.html (live test) (source)
- host-has-shadow-tree-element-at-subject-position.html (live test) (source)
- host-pseudo-class-in-has.html (live test) (source)
- input-pseudo-classes-in-has.html (live test) (source)
- is-pseudo-containing-complex-in-has.html (live test) (source)
- is-pseudo-containing-sibling-relationship-in-has.html (live test) (source)
- lang-pseudo-class-in-has-document-element.html (live test) (source)
- lang-pseudo-class-in-has-multiple-document-elements.html (live test) (source)
- lang-pseudo-class-in-has-xhtml.xhtml (live test) (source)
- lang-pseudo-class-in-has.html (live test) (source)
- link-pseudo-class-in-has.html (live test) (source)
- link-pseudo-in-has.html (live test) (source)
- location-pseudo-classes-in-has.html (live test) (source)
- media-loading-pseudo-classes-in-has.html (live test) (source)
- media-pseudo-classes-in-has.html (live test) (source)
- modal-pseudo-class-in-has.html (live test) (source)
- negated-has-in-nonsubject-position.html (live test) (source)
- not-pseudo-containing-complex-in-has.html (live test) (source)
- not-pseudo-containing-sibling-relationship-in-has.html (live test) (source)
- state-in-has.html (live test) (source)
- subject-has-invalidation-with-display-none-anchor-element.html (live test) (source)
- target-pseudo-in-has.html (live test) (source)
- typed-child-indexed-pseudo-classes-in-has.html (live test) (source)
- user-action-pseudo-classes-in-has.html (live test) (source)
- parse-has-disallow-nesting-has-inside-has.html (live test) (source)
- parse-has-forgiving-selector.html (live test) (source)
- parse-has.html (live test) (source)
관계형 가상 클래스(:has())는 <relative-selector-list>를 인자로 받는 함수형 가상 클래스입니다. 이 가상 클래스는 상대 선택자 중 하나라도 이 요소를 기준(anchor)으로 맞닿았을 때 최소 한 요소와 일치하는 경우, 그 요소를 나타냅니다.
:has() 가상 클래스는 중첩될 수 없으며, :has() 내에 :has()가 있으면 무효입니다. 또한 명시적으로 :has-허용 가상 요소(:has-allowed pseudo-element)로 정의되지 않은 한, 가상 요소는 :has() 내에서 허용되지 않습니다. (이 명세에서는 어떤 :has-허용 가상 요소도 정의하지 않으나, 다른 명세에서 따로 정의할 수 있습니다.)
참고: 많은 가상 요소가 조상 요소의 스타일에 따라 조건적으로 존재하므로, :has()에서 이들을 쿼리할 수 있게 하면 순환(사이클)이 발생할 수 있습니다. 이 때문에 가상 요소는 일반적으로 :has()에서 제외됩니다.
참고: :has()는 <relative-selector-list>를 받으므로, 인자들은 본질적으로 복잡 선택자(complex selector)입니다 (결합자로 시작하거나 암시적으로 결합자가 있다고 가정). 즉 :has()는 복잡 선택자가 허용되지 않는 문맥에서는 사용할 수 없고, 그러한 경우 인자가 반드시 무효가 됩니다.
<img> 자식을 포함한
<a> 요소만과 일치합니다:
a:has(> img)
다음 선택자는 다른 <dt> 요소에 바로 이어진 <dt> 요소와 일치합니다:
dt:has(+ dt)
다음 선택자는 아무 heading 요소도 포함하지 않는 <section> 요소와 일치합니다:
section:not(:has(h1, h2, h3, h4, h5, h6))
위 선택자는 순서가 중요합니다. 두 가상 클래스의 중첩 순서를 바꾸면 아래처럼 됩니다:
section:has(:not(h1, h2, h3, h4, h5, h6))
...이런 경우, heading 요소가 아닌 무언가를 포함하는 모든 <section> 요소에
일치한다는 결과가 나옵니다.
5. 기본(원자) 선택자(Elemental selectors)
5.1. 타입(태그 이름) 선택자(Type (tag name) selector)
타입 선택자(type selector)는 문서 언어의 요소 타입 이름으로, 문서 트리에서 그 요소 타입의 인스턴스를 나타냅니다.
타입 선택자는 CSS 한정 이름(qualified name)으로 작성됩니다: 네임스페이스 접두사가 선택적으로 붙은 식별자(identifier)입니다. [CSS3NAMESPACE] (§ 5.3 원자 선택자의 네임스페이스 참고.)
5.2. 범용 선택자(Universal selector)
범용 선택자(universal selector)는 모든 요소 타입을 나타내는 특수한 타입 선택자입니다.
이는 지역 이름 부분에 별표(* U+002A)를 사용한
CSS 한정 이름(Qualified Name)으로 작성합니다.
타입 선택자와 마찬가지로,
범용 선택자에도 네임스페이스를
지정할 수 있어,
해당 네임스페이스에 속한 요소로만 제한할 수 있습니다.
§ 5.3 원자 선택자의 네임스페이스의 기본 네임스페이스 선언에도 영향을 받습니다.
요소가 특징 없음이 아닌 한, 범용 선택자가 존재해도 선택자 일치에 영향이 없습니다. (특징 없음 요소는 범용 선택자 등 어떤 선택자에도 일치하지 않습니다.)
범용 선택자는 다른 타입 선택자와 동일한 문법 규칙을 따릅니다: 하나의 복합 선택자 내에 오직 하나만 등장할 수 있으며, 복합 선택자의 첫 번째 단순 선택자여야 합니다.
참고: 일부 경우, 범용 선택자를 추가하면 일치 행위에는 영향이 없지만 선택자를 더 읽기 쉽게 만들 수 있습니다. 예를 들어 div :first-child와 div:first-child는 얼핏 봐서는 다르다고 느끼기 어렵지만, 앞의 예를 div *:first-child로 쓰면 차이가 명확해집니다.
5.3. 원자 선택자의 네임스페이스(Namespaces in Elemental Selectors)
타입 선택자 및 범용 선택자는 네임스페이스
컴포넌트(접두사)를 선택적으로 허용합니다:
선언된 네임스페이스 접두사를 요소 이름 앞에 네임스페이스 구분자 “vertical bar”(| U+007C)로 붙일 수 있습니다.
(XML에서 네임스페이스에 대한 예시는 [XML-NAMES] 참고.)
형태별 의미는 다음과 같습니다:
ns|E- 네임스페이스 ns 내 이름이 E인 요소
*|E- 어느 네임스페이스(네임스페이스가 없는 것도 포함)에서든 이름이 E인 요소
|E- 네임스페이스가 없는 이름이 E인 요소
E- 선택자에 대한 기본 네임스페이스가 선언되지 않은 경우 *|E와 같고, 선언되어 있다면 ns|E와 같으나, 이때 ns는 기본 네임스페이스입니다.
@namespace foo url(http://www.example.com);
foo|h1 { color: blue } /* 첫 번째 규칙 */
foo|* { color: yellow } /* 두 번째 규칙 */
|h1 { color: red } /* ...*/
*|h1 { color: green }
h1 { color: green }
첫 번째 규칙(@namespace 규칙 자체는 제외)은 "http://www.example.com" 네임스페이스의 h1 요소만과 일치합니다.
두 번째 규칙은 "http://www.example.com" 네임스페이스의 모든 요소와 일치합니다.
세 번째 규칙은 네임스페이스가 전혀 없는 h1 요소만과 일치합니다.
네 번째 규칙은 어느 네임스페이스(네임스페이스 없는 케이스 포함)든 h1 요소와 일치합니다.
마지막 규칙은 정의된 기본 네임스페이스가 없다면 네 번째 규칙과 동일합니다.
기본 네임스페이스가 선언된 경우, 타입 선택자 없이 복합 선택자만으로도 해당 네임스페이스의 요소에만 일치합니다.
@namespace url("http://example.com/foo");
.special { ... }
.special 선택자는 "http://example.com/foo" 네임스페이스 내 요소와만 일치하며, (DOM에서 네임스페이스와 쌍을 이루는) 타입 이름이 명시되지 않아도 효과가 있습니다.
이전에 선언되지 않은 네임스페이스 접두사가 포함된 타입 선택자 또는 범용 선택자는 잘못된 선택자입니다.
5.4. 정의됨 가상 클래스(The Defined Pseudo-class): :defined
일부 호스트 언어에서는 요소가 "정의됨/생성됨" 상태인지 아닌지 구분할 수 있습니다. :defined 가상 클래스(pseudo-class)는 호스트 언어에서 완전히 정의된 요소와 일치합니다.
해당 구분이 없는 호스트 언어의 경우, 모든 요소가 :defined와 일치하게 됩니다.
p : defined{ ...}
커스텀 요소는 처음엔 정의되지 않은 상태이며, 적절히 등록될 때에야 정의된 상태가 됩니다. 따라서 :defined 가상 클래스를 활용하면 커스텀 요소가 등록될 때까지 숨기고, 등록 후에만 노출할 수 있습니다:
custom-element { visibility: hidden }
custom-element:defined { visibility: visible }
6. 속성 선택자(Attribute selectors)
테스트
선택자는 요소의 속성을 표현할 수 있습니다. 선택자를 요소와 일치시키는 표현식으로 사용할 때, 속성 선택자(attribute selector)는, 해당 요소가 속성 선택자가 나타내는 속성과 일치하는 속성을 가지고 있다면 일치하는 것으로 간주해야 합니다.
여러 값 매칭을 위한 쉼표 구분 문법 추가? 예: [rel ~= next, prev, up, first, last]
6.1. 속성 존재 및 값 선택자(Attribute presence and value selectors)
CSS2에서는 네 가지 속성 선택자가 도입되었습니다:
- [att]
-
att속성이 있는 요소를 나타냅니다. 속성 값은 관계없습니다. - [att=val]
-
att속성의 값이 정확히 "val"인 요소를 나타냅니다. - [att~=val]
-
att속성이 공백으로 구분된 단어 목록이며, 그 중 하나가 정확히 "val"인 요소를 나타냅니다. "val"에 공백이 포함되어 있다면, 절대로 어떤 것도 나타낼 수 없습니다 (단어가 공백으로 구분되기 때문). 또한 "val"이 빈 문자열이면, 역시 아무것도 나타내지 않습니다. - [att|=val]
-
att속성이 있는 요소를 나타내며, 값이 정확히 "val"이거나, "val" 바로 뒤에 "-"(U+002D)가 오는 것으로 시작할 때만 일치합니다. 이는 주로 언어 하위 코드 매칭을 허용하기 위한 것으로 (예: HTML에서 a 요소의hreflang속성), BCP 47 ([BCP47]) 또는 그 후속과 같이 동작하도록 설계되었습니다.lang(또는xml:lang) 언어 하위 코드 매칭의 경우 :lang() 가상 클래스를 참고하세요.
속성 값은 <ident-token>이거나 <string-token>이어야 합니다. [CSS3SYN]
다음 속성 선택자는 h1 요소에
title 속성이 있으면 값에 관계없이 일치합니다:
h1[title]
다음 예에서 이 선택자는 span 요소의 class 속성 값이
정확히 "example"일 때만 일치합니다:
span[class="example"]
여러 개의 속성 선택자를 사용하면
한 요소의 여러 속성을 나타내거나,
같은 속성에 여러 조건을 걸 수 있습니다.
여기서는 span 요소가
hello 속성은 "Cleveland", goodbye 속성은 "Columbus"일 때만 일치합니다:
span[hello="Cleveland"][goodbye="Columbus"]
다음 CSS 규칙들은
"="과 "~="의 차이를 보여줍니다. 첫 번째 선택자는 예를 들어 a 요소가 rel 속성에 "copyright copyleft
copyeditor"라는 값을 가지면 일치합니다. 두 번째 선택자는 a 요소의 href
속성 값이 정확히 "http://www.w3.org/"일 때에만 일치합니다.
a[rel~="copyright"] { ... }
a[href="http://www.w3.org/"] { ... }
다음 선택자는 a 요소의
hreflang 속성이 정확히 "fr"일 때 일치합니다.
a[hreflang=fr]
다음 선택자는 a 요소의
hreflang 값이 "en"으로 시작하는 경우(= "en", "en-US", "en-scouse" 모두 포함)와 일치합니다:
a[hreflang|="en"]
다음 선택자는 속성 character가 "romeo" 또는 "juliet" 값일 때
DIALOGUE 요소와 일치합니다:
DIALOGUE[character=romeo] DIALOGUE[character=juliet]
6.2. 부분 문자열 매칭 속성 선택자(Substring matching attribute selectors)
속성 값 내의 부분 문자열 일치를 위한 추가 속성 선택자도 세 가지가 있습니다:
- [att^=val]
-
att속성 값이 "val"로 시작하는 요소를 나타냅니다. "val"이 빈 문자열일 경우, 선택자는 아무것도 나타내지 않습니다. - [att$=val]
-
att속성 값이 "val"로 끝나는 요소를 나타냅니다. "val"이 빈 문자열이면, 아무것도 나타내지 않습니다. - [att*=val]
-
att속성 값에 부분 문자열 "val"이 한 번이라도 포함된 요소를 나타냅니다. "val"이 빈 문자열이면, 아무것도 나타내지 않습니다.
속성 값은 <ident-token> 또는 <string-token>이어야 합니다.
object[type^="image/"]
다음 선택자는 a 요소의
href 속성 값이 ".html"로 끝날 경우와 일치합니다.
a[href$=".html"]
다음 선택자는 title 속성 값에 "hello"가 포함된 HTML 단락과 일치합니다
p[title*="hello"]
6.3. 대소문자 구분(Case-sensitivity)
테스트
기본적으로 선택자 내 속성 이름과 값의 대소문자 구분 여부는 문서 언어에 따라 달라집니다.
속성 값 일치를 문서 언어 규칙과 상관없이
ASCII
대소문자 구분 없이 처리하려면,
속성 선택자의 닫는 대괄호(]) 앞에 식별자 i를 쓸 수 있습니다.
이 플래그가 있으면,
UA는 반드시 속성 값을 ASCII
대소문자 구분 없이([a-z]와 [A-Z]가 동일) 일치시켜야 합니다.
반대로, 속성 선택자 닫는 대괄호(]) 앞에 식별자 s를 쓸 수도 있습니다;
이 경우 UA는 값이 완전히 동일해야만 일치로 판단해야 하며,
문서 언어 규칙에 관계없이 대소문자를 반드시 구분해야 합니다. [INFRA]
다른 Selector 문법과 마찬가지로,
i와 s 식별자 자체도
ASCII 대소문자 구분 없음입니다.
frame 속성 값이
hsides, HSIDES, hSides 등 다양한 대소문자로 쓰였어도,
심지어 XML 환경처럼 속성 값이 대소문자 구분될 때도 모두 스타일 적용됩니다.
[frame=hsides i] { border-style: solid none; }
type="a"인 리스트와 type="A"인 리스트를
각각 다르게 스타일링하며,
이는 HTML에서는 type 속성이 대소문자 구분이 없다고 정의되어 있음에도 가능합니다.
[type="a" s] { list-style: lower-alpha; }
[type="A" s] { list-style: upper-alpha; }
참고:
일부 문서 모델은 대소문자 구분이 없는 속성 값을 파싱 시점에서 정규화 하므로,
문자열 대소문자 구분 매칭을 확인하는 것이 불가능합니다.
s 플래그로 대소문자 구분 매칭을 하려면 원본 대소문자를 보존하는 시스템이어야만 가능합니다.
6.4. 속성 선택자와 네임스페이스(Attribute selectors and namespaces)
속성 선택자에서의 속성 이름은
CSS 한정 이름(qualified name)으로
표기됩니다: 미리 선언된 네임스페이스 접두사를 속성 이름 앞에 네임스페이스
구분자(vertical bar, |)로 붙일 수 있습니다.
XML Namespaces 권고안에 따라, 기본 네임스페이스는 속성에 적용되지 않으므로,
네임스페이스 컴포넌트가 없는 속성 선택자는 네임스페이스가 없는 속성(즉, |attr과 동일)만 대상으로 합니다.
접두사에 별표(*)를 쓰면 속성의 네임스페이스에 관계없이 모든 속성 이름을 대상으로 일치시킵니다.
이전에 선언되지 않은 네임스페이스 접두사가 포함된 속성 이름을 가진 속성 선택자는 잘못된 선택자입니다.
@namespace foo "http://www.example.com";
[foo|att=val] { color: blue }
[*|att] { color: yellow }
[|att] { color: green }
[att] { color: green }
첫 번째 규칙은 "http://www.example.com" 네임스페이스에서 att 속성이 "val" 값을 가진 경우만 일치합니다.
두 번째 규칙은 속성 att가 네임스페이스가 있든 없든
(네임스페이스 없음 포함) 모두 일치합니다.
마지막 두 규칙은 동일하며,
네임스페이스가 없는 att 속성을 가진 경우만 일치합니다.
6.5. DTD의 기본 속성 값(Default attribute values in DTDs)
속성 선택자는 문서 트리 내의 속성 값을 나타냅니다. 이 문서 트리를 어떻게 구성하는지에 대해서는 Selector의 범위를 벗어납니다. 일부 문서 포맷에서는 DTD나 다른 곳에 기본 속성 값을 정의할 수 있지만, 이 값이 문서 트리에 실제로 나타난 경우에만 속성 선택자로 선택할 수 있습니다. Selector는 기본값이 트리에 존재하는지 여부와 관계없이 동작하도록 작성되어야 합니다.
예를 들어 XML UA는 "외부 서브셋" DTD를 읽어도 되지만(반드시 읽어야 하는 것은 아님), "내부 서브셋"에서는 기본 속성 값을 반드시 확인해야 합니다. (각 서브셋에 대한 정의는 [XML10] 참고.) UA에 따라 DTD 외부 서브셋에 정의된 기본 속성 값이 문서 트리에 나타나기도 하고 나타나지 않을 수도 있습니다.
XML 네임스페이스를 인식하는 UA는, 해당 네임스페이스에 대한 정보를 활용해 기본 속성 값을 문서에 실제로 있는 것처럼 취급할 수도 있고, 반드시 그래야 하는 것은 아닙니다. (예를 들어 XHTML UA는 XHTML DTD를 내장 정보로 반드시 사용하지 않아도 됩니다. 자세한 내용은 [XML-NAMES] 참고.)
참고: 일반적으로, 구현체들은 외부 서브셋을 무시하는 쪽을 택합니다. 이는 XML 명세에서 정의한 비(非)유효성 검사 프로세서 동작과 일치합니다.
EXAMPLE 요소에 radix 속성이 있고, 그 기본값이
"decimal"인 경우 DTD 조각:
<!ATTLIST EXAMPLE radix (decimal,octal) "decimal">
스타일 시트가 다음과 같다면:
EXAMPLE[radix=decimal] { /*... default property settings ...*/ }
EXAMPLE[radix=octal] { /*... other settings...*/ }
첫 번째 규칙은 radix 속성이 기본값(즉, 명시하지 않고 디폴트로 사용될 때)으로 설정된 요소에는
적용되지 않을 수 있습니다.
모든 경우를 처리하려면 기본값에 대한 속성 선택자를 빼야 합니다:
EXAMPLE { /*... default property settings ...*/ }
EXAMPLE[radix=octal] { /*... other settings...*/ }
여기서 EXAMPLE[radix=octal] 선택자가 타입 선택자 단독보다 더 구체적이므로,
radix 값이 "octal"인 요소에서는 두 번째 규칙 스타일이 첫 번째 규칙보다 우선합니다.
기본 케이스에만 적용하고자 하는 속성 선언은, 비기본 케이스의 스타일 규칙에서 반드시 모두 덮어써야 합니다.
6.6. 클래스 선택자(Class selectors)
클래스 선택자(class selector)는
마침표(. U+002E) 바로 뒤에 식별자를 붙여 표기합니다. 문서 언어에서 정의하는 바에 따라,
이 선택자는 해당 식별자가 표시하는 클래스에 속한 요소를 나타냅니다.
예를 들어, [HTML5], [SVG11], [MATHML] 등에서는
class 속성으로 클래스 소속이 결정됩니다: 따라서 해당 언어에선 ~=
표기법을 지역 class 속성에 적용한 것
(즉 [class~=identifier])과 동일합니다.
class~="pastoral" 인 모든 요소에 스타일을 지정할 때:
*.pastoral { color: green } /* class~=pastoral 인 모든 요소 */
혹은 이렇게도 쓸 수 있습니다
.pastoral { color: green } /* class~=pastoral 인 모든 요소 */
아래는 class~="pastoral"인 H1 요소에만 스타일을 지정합니다:
H1.pastoral { color: green } /* class~=pastoral 인 H1 */
이 규칙에서, 아래 두 H1 중 첫 번째는 초록색이 아니고 두 번째만 초록색이 됩니다:
<H1>Not green</H1> <H1 class="pastoral">Very green</H1>
이 규칙은 class 속성에 P 요소가,
공백으로 구분한 값 목록 중에
pastoral과 marine이 모두 포함돼 있으면 일치합니다:
p.pastoral.marine { color: green }
class="pastoral blue aqua
marine"에선 일치하지만, class="pastoral
blue"에선 일치하지 않습니다.
참고: CSS는 "class" 속성에 큰 역할을 부여하므로, 작성자가 구조적 의미는 거의 없는 요소(div·span 등)에 스타일 정보를 "class"로만 부여해서 자신만의 "문서 언어"를 설계할 수도 있습니다. 하지만 문서 언어의 구조적 요소(예: h1, p 등)는 인정된 의미가 있으므로, 이 관행은 권장하지 않습니다. 직접 정의한 클래스에는 의미가 인정되지 않을 수 있습니다.
참고: 만약 한 요소에 여러 개의 class 속성이 있다면, 검색 전에 값을 공백으로 연결해 하나의 문자열로 합쳐야 합니다. 다만 이런 상황이 실제로 발생할 수 있다는 근거를 워킹 그룹은 찾지 못해, 명세에서 이 동작은 엄격히 비규범적(non-normative)입니다.
문서가 쿼크 모드(quirks mode)라면, 클래스 이름은 ASCII 대소문자 구분 없이 매칭해야 합니다. 클래스 선택자는 그 외에는 대소문자를 구분하고, 완전히 동일한 클래스명과만 일치합니다. [INFRA]
6.7. 아이디 선택자(ID selectors)
문서 언어에는 ID 타입으로 선언된 속성이 있을 수 있습니다.
ID 타입 속성이 특별한 점은,
그런 속성은 문서에서 어떤 요소에 달려 있든 각각의 값이 반드시 유일해야 한다는 점입니다.
(즉, 서로 다른 요소에 같은 값의 ID 타입 속성이 있으면 안 됩니다.)
문서 언어와 관계없이,
ID 타입 속성은 해당 요소를 유일하게 식별할 수 있도록 해줍니다.
HTML에서는 모든 ID 속성의 이름이 id입니다.
XML 응용에서는 ID 속성 이름이 다를 수 있지만,
같은 제한이 적용됩니다.
어떤 속성이 “ID 속성”으로 간주되는지는 문서 언어에서 정의합니다.
ID 선택자는
“번호 기호”(U+0023, #) 바로 뒤에 ID 값을 붙여 표기합니다.
여기서 ID 값은 반드시 CSS 식별자(identifier)여야 합니다.
ID 선택자는
값이 해당 식별자와 일치하는 ID 속성을 가진 요소 인스턴스를 나타냅니다.
(표준을 지키지 않은 문서에서는 여러 요소가 하나의 ID 선택자와 일치할 수도 있습니다.)
h1#chapter1
다음 ID 선택자는 ID 타입 속성 값이 "chapter1"인 어떤 요소라도 모두 가리킵니다:
#chapter1
다음 선택자는 ID 타입 속성 값이 "z98y"인 모든 요소와 일치합니다.
*#z98y
참고: XML 1.0 [XML10]에서는, 어떤 속성이 요소의 ID를 담고 있는지는 DTD나 스키마에 정의되어 있습니다. XML을 파싱할 때, UA는 항상 DTD를 읽는 것이 아니기에 어떤 속성이 ID인지 UA가 모를 수도 있습니다 (하지만 UA가 네임스페이스에 특화된 지식이 있다면 해당 네임스페이스에서 어떤 속성이 ID 속성인지 알 수도 있습니다). 스타일시트 작성자가 UA가 해당 요소의 ID를 모를 수 있다고 생각한다면, #p371 대신 [name=p371]처럼 일반 속성 선택자를 써야 합니다.
만약 한 요소에 여러 개의 ID 속성이 있다면, ID 선택자 관점에서는 모두 ID로 취급해야 합니다. (xml:id, DOM3 Core, XML DTD, 네임스페이스별 지식 조합에서 이런 상황이 생길 수 있음)
문서가 쿼크 모드(quirks mode)인 경우, ID는 ASCII 대소문자 구분 없이 매칭해야 합니다. 그렇지 않은 경우 ID 선택자는 대소문자 구분하며, 완전히 동일한 ID만 일치합니다. [INFRA]
7. 언어 관련 가상 클래스(Linguistic Pseudo-classes)
7.1. 방향성 가상 클래스(The Directionality Pseudo-class): :dir()
테스트
- dir-pseudo-in-has.html (live test) (source)
- dir-pseudo-on-bdi-element.html (live test) (source)
- dir-pseudo-on-input-element.html (live test) (source)
- dir-pseudo-update-document-element.html (live test) (source)
- dir-selector-auto-direction-change-001.html (live test) (source)
- dir-selector-auto.html (live test) (source)
- dir-selector-change-001.html (live test) (source)
- dir-selector-change-002.html (live test) (source)
- dir-selector-change-003.html (live test) (source)
- dir-selector-change-004.html (live test) (source)
- dir-selector-ltr-001.html (live test) (source)
- dir-selector-ltr-002.html (live test) (source)
- dir-selector-ltr-003.html (live test) (source)
- dir-selector-querySelector.html (live test) (source)
- dir-selector-rtl-001.html (live test) (source)
- dir-selector-white-space-001.html (live test) (source)
- dir-style-01a.html (live test) (source)
- dir-style-01b.html (live test) (source)
- dir-style-02a.html (live test) (source)
- dir-style-02b.html (live test) (source)
- dir-style-03a.html (live test) (source)
- dir-style-03b.html (live test) (source)
- dir-style-04.html (live test) (source)
- part-dir.html (live test) (source)
:dir()
가상 클래스는 작성자가 요소의 방향성(좌우, 우좌 등)에 따라
선택자를 작성할 수 있게 해줍니다.
방향성은 문서 언어에 의해 결정됩니다.
예를 들어 [HTML5]에서는
요소의 방향성을 결정하는 방법이
dir 속성, 주변 텍스트, 기타 요인들의 조합에 따라 정의되어 있습니다.
또 다른 예로, Internationalization Tag Set의 its:dir 및 dirRule 요소
([ITS20])는
[XML10] 문서에서 방향성을 정의할 수 있습니다.
:dir() 가상 클래스는 스타일 상태(예: CSS direction 프로퍼티)에 영향을 받지 않으며, 스타일 상태는 일치 여부에 영향을 미치지 않습니다.
가상 클래스 :dir(ltr)은 좌에서 우로(ltr) 방향성을 갖는 요소를 나타내며,
:dir(rtl)은 우에서 좌로(rtl) 방향성을 갖는 요소를 나타냅니다.
:dir()의 인자는 반드시 단일
식별자여야 하며,
그렇지 않으면 선택자가 무효입니다.
식별자와 괄호 사이에는 공백이 선택적으로 허용됩니다.
ltr 및 rtl 이외의 값은 무효는 아니나, 어떤 것도 일치하지 않습니다.
(향후 마크업 명세에서 다른 방향값이 정의되면 그에 맞춰 확장될 수 있습니다.)
:dir(C)과 [dir=C]의 차이점은,
[dir=C]은 해당 요소의 속성값만 비교하는 반면
:dir(C) 가상 클래스는 UA가 알고 있는 문서의 의미론 정보까지
이용하여 비교를 수행한다는 점입니다.
예를 들어 HTML에서는 방향성이 상속되므로,
dir 속성이 없는 자식이라도 가장 가까운 상위에서 dir이 유효한 값을 가지면
그 방향성을 상속받게 됩니다.
또, HTML에서는 [dir=auto]로 일치하는 요소가
해당 내용물에 따라 :dir(ltr)이나 :dir(rtl)에도 일치할 수 있습니다.
[HTML5]
7.2. 언어 가상 클래스(The Language Pseudo-class): :lang()
테스트
- css3-selectors-lang-001.html (live test) (source)
- css3-selectors-lang-002.html (live test) (source)
- css3-selectors-lang-004.html (live test) (source)
- css3-selectors-lang-005.html (live test) (source)
- css3-selectors-lang-006.html (live test) (source)
- css3-selectors-lang-007.html (live test) (source)
- css3-selectors-lang-008.html (live test) (source)
- css3-selectors-lang-009.html (live test) (source)
- css3-selectors-lang-010.html (live test) (source)
- css3-selectors-lang-011.html (live test) (source)
- css3-selectors-lang-012.html (live test) (source)
- css3-selectors-lang-014.html (live test) (source)
- css3-selectors-lang-015.html (live test) (source)
- css3-selectors-lang-016.html (live test) (source)
- css3-selectors-lang-021.html (live test) (source)
- css3-selectors-lang-022.html (live test) (source)
- css3-selectors-lang-024.html (live test) (source)
- css3-selectors-lang-025.html (live test) (source)
- css3-selectors-lang-026.html (live test) (source)
- css3-selectors-lang-027.html (live test) (source)
- css3-selectors-lang-028.html (live test) (source)
- css3-selectors-lang-029.html (live test) (source)
- css3-selectors-lang-030.html (live test) (source)
- css3-selectors-lang-031.html (live test) (source)
- css3-selectors-lang-032.html (live test) (source)
- css3-selectors-lang-034.html (live test) (source)
- css3-selectors-lang-035.html (live test) (source)
- css3-selectors-lang-036.html (live test) (source)
- css3-selectors-lang-041.html (live test) (source)
- css3-selectors-lang-042.html (live test) (source)
- css3-selectors-lang-044.html (live test) (source)
- css3-selectors-lang-045.html (live test) (source)
- css3-selectors-lang-046.html (live test) (source)
- css3-selectors-lang-047.html (live test) (source)
- css3-selectors-lang-048.html (live test) (source)
- css3-selectors-lang-049.html (live test) (source)
- css3-selectors-lang-050.html (live test) (source)
- css3-selectors-lang-051.html (live test) (source)
- css3-selectors-lang-052.html (live test) (source)
- css3-selectors-lang-054.html (live test) (source)
- css3-selectors-lang-055.html (live test) (source)
- css3-selectors-lang-056.html (live test) (source)
- lang-pseudo-class-across-shadow-boundaries.html (live test) (source)
- lang-pseudo-class-disconnected.html (live test) (source)
- lang-pseudo-class-empty-attribute.xhtml (live test) (source)
- part-lang.html (live test) (source)
- lang-000.html (live test) (source)
- lang-001.html (live test) (source)
- lang-002.html (live test) (source)
- lang-003.html (live test) (source)
- lang-004.html (live test) (source)
- lang-005.html (live test) (source)
- lang-006.html (live test) (source)
- lang-007.html (live test) (source)
- lang-008.html (live test) (source)
- lang-009.html (live test) (source)
- lang-010.html (live test) (source)
- lang-011.html (live test) (source)
- lang-012.html (live test) (source)
- lang-013.html (live test) (source)
- lang-014.html (live test) (source)
- lang-015.html (live test) (source)
- lang-016.html (live test) (source)
- lang-017.html (live test) (source)
- lang-018.html (live test) (source)
- lang-019.html (live test) (source)
- lang-020.html (live test) (source)
- lang-021.html (live test) (source)
- lang-022.html (live test) (source)
- lang-023.html (live test) (source)
- lang-024.html (live test) (source)
- lang-025.html (live test) (source)
문서 언어가 요소의 (인간) 콘텐츠 언어를 어떻게 결정하는지 명시할 경우, 선택자로 특정 콘텐츠 언어를 기준으로 요소를 표현할 수 있습니다. :lang() 가상 클래스는 하나 이상의 언어 범위(language range)를 쉼표로 구분하여 인자로 받으며, 인자에 나열된 언어 중 하나가 요소의 콘텐츠 언어와 일치하는 경우를 나타냅니다. :lang() 내 각 언어 범위(language range)는 반드시 올바른 CSS <ident> 또는 <string>이어야 합니다. (따라서 예를 들어 별표(*)가 포함된 언어 범위는 적절히 이스케이프하거나 문자열로 인용되어야 하며, :lang(\*-Latn) 또는 :lang("*-Latn")과 같이 작성해야 합니다.)
참고: 요소의 콘텐츠 언어는 문서 언어에 의해 정의됩니다.
예를 들어, HTML [HTML5]에서는 콘텐츠 언어가
lang 속성,
meta 요소의 정보,
그리고 경우에 따라 프로토콜(예: HTTP 헤더) 등 여러 정보를 조합해서 결정됩니다.
XML 언어에서는 xml:lang 속성을 사용해
요소의 언어 정보를 표시할 수 있습니다. [XML10]
해당 요소의 콘텐츠 언어와 언어 범위(language range)가 매치되려면, 그 콘텐츠 언어(BCP 47 문법에 따라 표현)는 언어 범위와 확장 필터링(extended filtering) 방식으로 비교합니다. ([RFC4647] 3.3.2절 참조) 콘텐츠 언어와 언어 범위 모두 [RFC5646] 4.5절에 따라 정규화(canonicalized)되고 extlang form으로 변환된 뒤 확장 필터링이 적용되어야 하며, 매칭은 ASCII 범위에서 대소문자 구분 없이 수행됩니다.
언어 범위는 이 비교를 수행하기 위해 반드시 유효한 언어 코드일 필요는 없다.
이 목적상, 와일드카드 언어
범위("*")는
언어가 지정되지 않은(예: lang="") 요소엔 일치하지 않으며,
언어가 "und"로 태그된 경우에는 일치합니다(lang=und).
빈 문자열로 구성된 언어 범위(:lang(""))는
언어가 태그되지 않은 요소와만 일치합니다.
참고: 문서와 프로토콜에서는 [BCP47] 또는 그 후속의 코드로 언어를 명시하는 것이 권장되며,
XML 기반 포맷에서는 xml:lang 속성을 쓰는 것이 좋습니다. [XML10] “FAQ: 2글자/3글자 언어 코드?” 참고
html:lang(fr-be) html:lang(de) :lang(fr-be) > q :lang(de) > q
참고: :lang(C)과 |= 연산자의 차이점 중 하나는, |= 연산자는 해당 요소의 지정된 속성값만 비교하는 반면 :lang(C) 가상 클래스는 UA가 알고 있는 문서 의미 정보를 이용해 비교를 수행한다는 점입니다.
<body lang=fr> <p>Je suis français.</p> </body>
예를 들어, :lang(de-DE)는 de-DE, de-DE-1996, de-Latn-DE, de-Latf-DE, de-Latn-DE-1996 전부와 일치하지만, [lang|=de-DE]는 de-DE와 de-DE-1996에만 일치합니다.
첫 하위 태그(주 언어)에 대해 와일드카드 매칭을 하려면 별표(*)를 써야 합니다: *-CH는 de-CH, it-CH, fr-CH, rm-CH 전부 일치합니다.
이런 언어 범위 매칭을 lang 속성에 쓰려면 속성 선택자와 언어 가상 클래스를 함께 사용하시면 됩니다. 예: [lang]:lang(de-DE)
참고: 와일드카드 언어 매칭, 쉼표 구분 목록 기능은 Level 4에서 새로 도입되었습니다.
8. 위치 기반 가상 클래스(Location Pseudo-classes)
8.1. 하이퍼링크 가상 클래스(The Hyperlink Pseudo-class): :any-link
:any-link
가상 클래스는 하이퍼링크의 소스 앵커로 작동하는
요소를 나타냅니다.
예를 들어 [HTML5]에서,
a
또는
area
요소 중
href
속성이 있는 경우 하이퍼링크이며,
모두 :any-link와 일치합니다.
이 가상 클래스는 요소가 :link
또는 :visited 중
하나와 일치하면 일치하며,
:is(:link, :visited)와 동일합니다.
8.2. 링크 이력 가상 클래스(The Link History Pseudo-classes): :link 및 :visited
테스트
- caret-color-visited-inheritance.html (live test) (source)
- text-emphasis-visited-inheritance.html (live test) (source)
- text-fill-color-visited-inheritance.html (live test) (source)
- text-stroke-color-visited-inheritance.html (live test) (source)
- visited-in-visited-compound.html (live test) (source)
- visited-inheritance.html (live test) (source)
- visited-nested.html (live test) (source)
- visited-part-crash.html (live test) (source)
사용자 에이전트는 일반적으로 아직 방문하지 않은 하이퍼링크와 이전에 방문한 링크를 서로 다르게 표시합니다. Selector는 이들을 구별할 수 있도록 :link와 :visited라는 가상 클래스를 제공합니다:
이 두 상태는 동시에는 나타날 수 없습니다.
일정 시간이 지나면, 사용자 에이전트는 방문한 링크를 (방문 전) :link 상태로 다시 돌릴 수도 있습니다.
:visited 가상 클래스에는 사용자 프라이버시 관련 명백한 문제가 있습니다—다른 웹사이트의 방문 내역을 임의 웹사이트가 알게 되는 것은 다양한 이유로 문제가 될 수 있으므로, 사용자 에이전트는 :visited 구현에서 반드시 사용자의 프라이버시를 보호해야 합니다.
-
특정 origin에서 자력으로 관찰 가능한 히스토리 엔트리만 정확히 추적하여, 사이트의 origin에서 본래 관찰될 수 있는 경우에만 :visited 일치하도록 한다. 한 가지 구체적 방법은 부록 C: 프라이버시 보호 :visited 제한 참조.
-
어느 origin이라도 :visited 일치를 허용하되, 적용할 수 있는 스타일과
getComputedStyle()같은 스타일 조회 API에서 반환하는 정보에 매우 엄격한 제한을 둡니다. 이렇게 하면 사이트가 링크가 :link인지 :visited인지 알아내는 것을 방지할 수 있습니다. (이 접근법은 MDN에 문서화돼 있으며 브라우저의 과거 방식이기도 하지만, 완벽하진 않습니다; 악의적 페이지가 여전히 히스토리 정보를 추출할 여러 수단이 있습니다.)
8.3. 대상 가상 클래스(The Target Pseudo-class): :target
일부 문서 언어에서는 문서의 URL로 문서 내부의 특정 요소를 URL의 fragment로 지정할 수 있습니다. 이처럼 지정된 요소들이 바로 문서의 target 요소입니다.
https://example.com/index.html#section2라는 주소는
https://example.com/index.html 문서 내에서 id="section2"인 요소를 가리킵니다.
:target 가상 클래스는 문서의 target 요소와 일치합니다. 문서의 URL에 fragment 식별자가 없다면, 문서에는 target 요소가 없습니다.
:target { color : red }
:target::before { content : url(target.png) }
참고: 이 명세는 과거 :target-within 가상 클래스를 정의했으나, :focus-within과 유사하게 기능하지만, 그보다는 :has(:target)으로 같은 목적을 충분히 해결할 수 있으므로 삭제되었습니다.
8.4. 참조 요소 가상 클래스(The Reference Element Pseudo-class): :scope
일부 컨텍스트에서는 선택자가 하나 이상의 스코프 루트(scoping
root)를 기준으로
매칭됩니다. 예를 들어 [DOM]에서 querySelector() 메서드를 사용하면 그렇습니다.
:scope
가상 클래스는 이 스코프 루트를 나타내며,
실제 요소이거나
(예: 문서트리의 루트)
혹은 가상 요소일 수도 있습니다(예: DocumentFragment).
스코프 루트가 없으면 :scope는 해당 요소가 속한 트리의 루트 요소를 나타냅니다 (즉, :host 또는 그 외에는 :root). 이 가상 클래스가 루트 이외의 특정 요소와 일치하도록 하려면, 명세에서 그 스코프 루트를 명확히 정의해야 합니다.
가상 스코프 루트는 문서 조각의 루트를 나타내는 객체이며, 선택자 패턴에서 다른 요소들과의 관계 표현에 사용할 수 있습니다. 이 스코프 루트는 해당 문서 조각 내 모든 루트 요소의 부모 역할을 합니다. 가상 스코프 루트는 특징 없음(featureless)이며, 절대 선택자의 주체(subject)로 취급될 수 없습니다.
DocumentFragment
df가 있다면,
df. querySelectorAll( ":scope > .foo" )
는 해당 문서 조각에서 "최상위"에 있는(즉, document fragment가 parentNode인)
.foo 요소 모두에 일치합니다.
반면, df는
아무것에도 일치하지 않습니다.
document fragment 자체는 선택자의 주체가 될 수 없기 때문입니다.
9. 사용자 동작 가상 클래스(User Action Pseudo-classes)
인터랙티브 UI에서는 사용자의 동작에 따라 렌더링이 바뀔 수 있습니다. Selector는 사용자의 동작에 따라 요소를 선택할 수 있도록 여러 사용자 동작 가상 클래스(user action pseudo-class)를 제공합니다. (비인터랙티브 UA에서는 이 가상 클래스가 유효하더라도 어떤 요소에도 일치하지 않습니다.)
사용자 동작 가상 클래스는 상호 배타적이지 않습니다. 하나의 요소가 여러 가상 클래스와 동시에 일치할 수 있습니다.
a:hover /* 사용자가 링크 위에 마우스를 올렸을 때 */ a:focus /* 사용자가 링크에 포커스 했을 때 */ a:focus:hover /* 사용자가 포커스된 링크 위에 마우스를 올렸을 때 */
일부 사용자 동작 가상 클래스는 해당 속성을 가진 요소뿐 아니라 그 조상 요소도 일치시킵니다: :hover, :active, :focus-within. 구체적으로는, 이들 가상 클래스가 어떤 요소에 일치하면, 해당 요소의 플랫 트리(flat tree) 상 조상 요소들 중 첫 top layer 요소 또는 루트 요소까지도 동일하게 일치합니다. (먼저 만나는 쪽까지만)
참고: 이 섹션의 여러 가상 클래스가 언제 적용될지 판단하는, 히트 테스트의 구체 명세는 아직 정의되지 않았으며, 향후 추가될 예정입니다.
9.1. 포인터 hover 가상 클래스(The Pointer Hover Pseudo-class): :hover
테스트
- hover-001-manual.html (manual test) (source)
- hover-002.html (live test) (source)
- remove-hovered-element.html (live test) (source)
:hover 가상 클래스는 사용자가 포인팅 장치로(마우스 등) 어떤 요소(혹은 가상 요소)를 지정하고 있을 때 적용됩니다. 하지만 반드시 그 요소를 활성화하지는 않습니다. 예를 들어, 시각적 사용자 에이전트는 커서(마우스 포인터)가 요소가 만든 박스 위에 올라갔을 때 이 가상 클래스를 적용할 수 있습니다. 포인팅 장치의 하드웨어 한계로 hover를 감지할 수 없는 인터랙티브 사용자 에이전트(예: hover 감지가 불가능한 펜 입력 장치)도 규격에 부합합니다; 이런 UA에서는 이 선택자가 어떤 요소와도 일치하지 않을 뿐입니다.
요소의 flat tree에 속한 하위 노드(텍스트 노드처럼 비요소 노드 포함) 중 하나라도 위 조건에 맞으면, 그 요소 또한 :hover와 일치합니다.
문서 언어에 따라 :hover와
일치할 수 있는 추가 방법이 정의될 수 있습니다.
예를 들어, [HTML5]에서는
라벨이 hover될 때도
:hover와 일치하도록 정의합니다. 이 때 label 요소가 hover 대상이면 컨트롤 요소도 hover된 것으로 간주됩니다.
참고: :hover 상태는 자식이 포인팅 장치로 지정된 경우에도 적용될 수 있으므로, 실제로 포인터가 요소 위에 없더라도 :hover가 적용될 수 있습니다.
9.2. 활성화 가상 클래스: :active
:active 가상 클래스는 요소가 사용자에 의해 "활성화"되고 있는 동안 적용됩니다. 여기서 "활성화"의 기준은 호스트 언어가 정의합니다; 예를 들어, 하이퍼링크가 실행되는 순간 등입니다.
또한, :active 가상 클래스는 어떤 요소(또는 가상 요소)가 생성하는 어느 박스든 포인팅 장치로 실제로(버튼을 누르고 있는 "down" 상태 등) 명확히 지정되면 적용됩니다. 예: 사용자가 기본 마우스 버튼을 눌러서 뗄 때까지 혹은 손가락으로 터치스크린을 누르는 동안.
참고: [HTML5]에서는 HTML 요소가 활성화되는 구체 조건을 정의하고 있습니다.
요소의 flat tree에 속한 하위 노드(텍스트 노드처럼 비요소 노드 포함) 중 하나라도 위 조건에 맞으면, 그 요소 또한 :active와 일치합니다.
9.3. 입력 포커스 가상 클래스: :focus
테스트
:focus 가상 클래스는 요소(또는 가상 요소)가 포커스를 가질 때 (키보드 또는 기타 입력을 받을 때) 적용됩니다.
어떤 요소가 :focus를 가질 수 있는지는 문서 언어나 구현에 따라 제한이 있을 수 있습니다. 예를 들어, [HTML]은 포커스 가능한 영역 목록을 정의합니다.
문서 언어마다 :focus와 일치하는 추가 방식을 정의할 수도 있습니다. 단, :focus 가상 클래스는 부모 요소로 자동 전파되면 안 됩니다—부모까지 일치시키고 싶다면 :focus-within을 사용해야 합니다. (:focus가 다른 메커니즘으로 인해 부모 요소까지 전파될 수는 있지만, 단순히 부모라는 이유만으로는 안 됩니다.)
폼 컨트롤에서 연결된
label
요소까지 :focus 전파를
원하는 제작자 요구가 있습니다;
주요 반대 이유는 구현의 어려움입니다.
CSSWG issue (CSS)와 WHATWG issue (HTML) 참고.
9.4. 포커스 표시 가상 클래스: :focus-visible
테스트
- focus-visible-001.html (live test) (source)
- focus-visible-002.html (live test) (source)
- focus-visible-003.html (live test) (source)
- focus-visible-004.html (live test) (source)
- focus-visible-005.html (live test) (source)
- focus-visible-006.html (live test) (source)
- focus-visible-007.html (live test) (source)
- focus-visible-008.html (live test) (source)
- focus-visible-009.html (live test) (source)
- focus-visible-010.html (live test) (source)
- focus-visible-011.html (live test) (source)
- focus-visible-012.html (live test) (source)
- focus-visible-013.html (live test) (source)
- focus-visible-014.html (live test) (source)
- focus-visible-015.html (live test) (source)
- focus-visible-016.html (live test) (source)
- focus-visible-017-2.html (live test) (source)
- focus-visible-017.html (live test) (source)
- focus-visible-018-2.html (live test) (source)
- focus-visible-018.html (live test) (source)
- focus-visible-019.html (live test) (source)
- focus-visible-020.html (live test) (source)
- focus-visible-021.html (live test) (source)
- focus-visible-023.html (live test) (source)
- focus-visible-024.html (live test) (source)
- focus-visible-025.html (live test) (source)
- focus-visible-026.html (live test) (source)
- focus-visible-027.html (live test) (source)
- focus-visible-028.html (live test) (source)
- focus-visible-script-focus-001.html (live test) (source)
- focus-visible-script-focus-004.html (live test) (source)
- focus-visible-script-focus-005.html (live test) (source)
- focus-visible-script-focus-008-b.html (live test) (source)
- focus-visible-script-focus-008.html (live test) (source)
- focus-visible-script-focus-009.html (live test) (source)
- focus-visible-script-focus-010.html (live test) (source)
- focus-visible-script-focus-011.html (live test) (source)
- focus-visible-script-focus-012.html (live test) (source)
- focus-visible-script-focus-013.html (live test) (source)
- focus-visible-script-focus-014.html (live test) (source)
- focus-visible-script-focus-015.html (live test) (source)
- focus-visible-script-focus-018.html (live test) (source)
- focus-visible-script-focus-019.html (live test) (source)
- focus-visible-script-focus-020.html (live test) (source)
- parse-focus-visible.html (live test) (source)
:focus 가상 클래스는 항상 현재 포커스된 요소와 일치하지만, UA(사용자 에이전트)는 언제나 포커스를 시각적으로 표시하지는 않습니다(예: “포커스 링” 그리기 등). 실제로 UA는 다양한 휴리스틱을 사용하여 사용자가 포커스 표시를 필요로 할 때만 시각적으로 포커스를 나타냅니다. :focus-visible 가상 클래스는 바로 이러한 상황에서만 포커스된 요소(또는 가상 요소)와 일치해서, 작성자가 포커스 표시가 언제 나타나는지를 변경하지 않고도 포커스 표시의 외양을 바꿀 수 있게 해줍니다.
:root{ --focus-gold : #ffbf47; } :focus-visible{ outline : 3 px solidvar ( --focus-gold); } a:focus-visible{ background-color : var ( --focus-gold); }
-
사용자가 항상 시각적 포커스 표시를 원한다고 설정(시스템 또는 브라우저 설정 등)한 경우, 어떤 상황이든 포커스 표시를 합니다. (다른 방법으론 UA가 자체 포커스 표시를 작성자 스타일과 상관없이 항상 표시할 수 있습니다.)
-
키보드 입력을 지원하는 요소(예:
input요소이거나, 포커스 시 물리 키보드가 없어도 가상 키보드를 띄우는 요소)라면 포커스 표시를 합니다. -
사용자가 키보드 등 포인팅 장치가 아닌 입력 방식으로 페이지와 상호작용했다면 포커스 표시를 합니다. (즉, 키보드 사용 여부가 이 가상 클래스의 일치 상태에 영향을 줄 수 있지만, :focus 상태와 반드시 일치하진 않을 수 있습니다.)
-
마우스·터치스크린 등 포인팅 장치로 페이지와 상호작용했으며, 포커스된 요소가 키보드 입력을 지원하지 않을 경우, 포커스 표시를 하지 않습니다.
-
이전 포커스된 요소가 포커스 표시를 하고 있었고, 스크립트로 포커스가 다른 데로 이동했다면, 새 포커스 요소에도 포커스 표시를 합니다.
반대로 이전 포커스 요소가 포커스 표시를 안 하고 있었고, 스크립트로 포커스가 옮겨졌다면, 새 포커스 요소엔 포커스 표시를 하지 않습니다.
-
새로 표시된 요소가 자동으로 포커스를 받는 경우(예: 새로 열린 대화상자의 액션 버튼 등)는, 해당 요소에 포커스 표시를 해야 합니다.
UA는 또한 :focus-visible로 기본 포커스 스타일을 지정해야 하며, 작성자가 :focus-visible를 쓸 때 기본 :focus 스타일을 별도로 끄지 않아도 되도록 해야 합니다.
9.5. 포커스 컨테이너 가상 클래스: :focus-within
테스트
- focus-within-001.html (live test) (source)
- focus-within-002.html (live test) (source)
- focus-within-003.html (live test) (source)
- focus-within-004.html (live test) (source)
- focus-within-005.html (live test) (source)
- focus-within-006.html (live test) (source)
- focus-within-007.html (live test) (source)
- focus-within-008.html (live test) (source)
- focus-within-009.html (live test) (source)
- focus-within-010.html (live test) (source)
- focus-within-011.html (live test) (source)
- focus-within-012.html (live test) (source)
- focus-within-013.html (live test) (source)
- focus-within-display-none-001.html (live test) (source)
- focus-within-focus-move.html (live test) (source)
- focus-within-removal.html (live test) (source)
- focus-within-shadow-001.html (live test) (source)
- focus-within-shadow-002.html (live test) (source)
- focus-within-shadow-003.html (live test) (source)
- focus-within-shadow-004.html (live test) (source)
- focus-within-shadow-005.html (live test) (source)
- focus-within-shadow-006.html (live test) (source)
:focus-within 가상 클래스는 :focus 가상 클래스가 적용되는 어떤 요소(또는 가상 요소)에도 적용되며, 또한 flat tree 내 하위 요소(텍스트 노드 등 비요소 노드 포함)가 :focus 조건을 만족할 때에도 적용됩니다.
10. 리소스 상태 가상 클래스(Resource State Pseudo-classes)
이 섹션의 가상 클래스들은 로드된 리소스를 나타내는 요소, 특히 이미지/비디오 등에 적용되며, 저자의 의도에 맞는 상태 특성에 따라 선택할 수 있게 합니다.
10.1. 미디어 재생 상태: :playing, :paused, 그리고 :seeking 가상 클래스
:playing 가상 클래스는 “재생(play)” 또는 “일시정지(pause)”가 가능한 요소 중 현재 “재생 중”인 상태인 요소를 나타냅니다. (여기에는 명시적으로 재생 중인 경우뿐만 아니라, 사용자의 의도와 무관하게 일시적으로 중단되었으나 그 사유가 해소되면 자동으로 재생이 재개되는 예: “버퍼링” 혹은 “정체(stalled)” 상태 등도 포함됩니다.)
:paused 가상 클래스는 “재생” 또는 “일시정지”가 가능한 요소 중 현재 “일시정지”(즉, 재생중이 아닌) 상태에 있는 요소를 나타냅니다. (여기에는 명시적인 “일시정지” 상태뿐 아니라, “로드됨(재생이 아직 시작되지 않음)”과 같은 기타 비재생(non-playing) 상태도 포함됩니다.)
:seeking
가상 클래스는 “탐색(seeking)”이 가능한 요소 중
현재 “탐색 중”인 상태인 요소를 나타냅니다.
(HTML의
audio
및
video
요소는 HTML
§ 4.8.11.9 Seeking 참고.)
10.2. 미디어 로딩 상태: :buffering, :stalled 가상 클래스
테스트
:buffering 가상 클래스는 “재생” 또는 “일시정지”가 가능한 요소가 미디어 데이터를 적극적으로 받아오려고 시도하지만 아직 충분한 데이터를 받아 재생을 계속할 수 없는 상태일 때를 나타냅니다. (이때 요소는 여전히 “재생 중”으로 간주됩니다. :buffering이 요소에 적용되는 동안에는 :playing도 해당 요소에 함께 적용됩니다.)
:stalled
가상 클래스는 요소가
미디어 데이터를
받아오려고 적극적으로 시도하고 있지만
일정 시간 동안 데이터를 전혀 받지 못해 재생을 계속할 수 없는 상태일 때를 나타냅니다.
HTML의
audio
및
video
요소의 경우,
이 시간은 미디어 요소 stall timeout에 해당합니다. [HTML]
(그리고 :buffering과 마찬가지로,
이때도 요소는 “재생 중”으로 간주됩니다.
:stalled가 적용되는 동안
:playing도
해당 요소에 함께 적용됩니다.)
10.3. 사운드 상태: :muted, :volume-locked 가상 클래스
:muted
가상 클래스는
소리를 낼 수 있는 요소이지만,
현재 “음소거됨”(강제로 무음 상태)인 요소에 적용됩니다.
(HTML의
audio
및
video
요소에 대해서는 음소거(muted)를 참고. [HTML])
:volume-locked 가상 클래스는
소리를 낼 수 있는 요소로,
현재 UA나 사용자가 볼륨을 “잠금”하여
페이지 작성자가 이를 변경할 수 없는 경우에 적용됩니다.
(HTML의
audio
및
video
요소에 대해서는
요소의 실질적 미디어 볼륨(effective media volume) 설정 알고리즘을 참고. [HTML])
11. 요소 표시 상태 가상 클래스(Element Display State Pseudo-classes)
11.1. 접힘 상태: :open 가상 클래스
테스트
:open 가상 클래스는 “open”과 “closed” 상태를 모두 가질 수 있는 요소에서, 현재 “open” 상태인 요소를 나타냅니다.
여기서 “open”과 “closed”가 정확히 무엇을 의미하는지는 호스트 언어마다 다르지만,
예시는 HTML의
details,
select,
dialog,
그리고
input
요소처럼,
각각은 “open” 상태로 토글될 때 더 많은 내용(또는
dialog는
내용 전체)을
표시할 수 있습니다.
참고: “open” 또는 “closed”는 의미론적 상태입니다. 현재 화면에 표시되지 않는 요소 (예: visibility: collapse가 적용된 경우나, display: none이 적용된 서브트리 등) 역시 “open” 상태일 수 있고, 이 경우에도 :open에 일치합니다.
참고: ":closed" 가상 클래스는 :open을 지원하는 전체 대상을 모두 파악한 후, 앞으로 추가될 수도 있습니다.
11.2. 팝오버 상태: :popover-open 가상 클래스
:popover-open 가상 클래스는 “popover-showing”과 “popover-hidden” 두 상태를 모두 가질 수 있는 요소 중 현재 “popover-showing” 상태인 요소를 나타냅니다.
참고: 이것은 :open과는 구별됩니다. 하나의 요소가 요소 고유의 open/closed 상태와 팝오버로서의 popover-showing/popover-hidden 상태를 별도로 가질 수 있기 때문입니다.
“popover-showing”과 “popover-hidden” 상태가
구체적으로 무엇을 의미하는지는 호스트 언어에 따라 다르지만,
HTML의
popover
속성의 존재와,
이에 연계된 popover 표시 상태가 그 예입니다.
11.3. 모달(단독 상호작용) 상태: :modal 가상 클래스
:modal 가상 클래스는, 닫히기 전까지는 외부의 모든 요소와의 상호작용을 차단하는 상태에 있는 요소를 나타냅니다. 여러 요소가 동시에 :modal이 될 수 있지만, 이 중 입력을 받을 수 있는 활성 요소는 단 하나뿐입니다.
dialog
요소는 showModal()
API로 열렸을 때 :modal이 됩니다.
마찬가지로,
:fullscreen 요소도
requestFullscreen()
API로 전체화면이 되는 경우 :modal 상태가 되는데,
이때도 다른 페이지 나머지와의 상호작용이 차단되기 때문입니다.
11.4. 전체화면 표시 상태: :fullscreen 가상 클래스
:fullscreen 가상 클래스는 전체 화면 API 등에서 정의한 대로, 화면 대부분(보통은 전체)을 차지하는 모드로 표시된 요소를 나타냅니다. [FULLSCREEN]
11.5. 화면 속 화면(Picture-in-Picture) 표시 상태: :picture-in-picture 가상 클래스
:picture-in-picture 가상 클래스는 화면 대부분(보통은 전체 뷰포트)을 차지하지만, 그 뷰포트가 화면의 일부로 한정되어 있으면서 다른 콘텐츠 위에 표시되는(예: Pic-in-Pic API 사용 시) 상태의 요소를 나타냅니다. [picture-in-picture]
12. 입력 가상 클래스(The Input Pseudo-classes)
이 섹션의 가상 클래스들은 주로 사용자의 입력을 받는 요소, 예를 들어 HTML의 input 요소 등에 적용됩니다.
12.1. 입력 컨트롤 상태(Input Control States)
12.1.1. :enabled 및 :disabled 가상 클래스
:enabled 가상 클래스는 활성화(enabled) 상태에 있는 사용자 인터페이스 요소를 나타냅니다; 이런 요소는 반드시 비활성(disabled) 상태도 가질 수 있어야 합니다.
반대로, :disabled 가상 클래스는 비활성화(disabled) 상태의 사용자 인터페이스 요소를 나타냅니다; 이런 요소 역시 반드시 활성(enabled) 상태도 가질 수 있어야 합니다.
무엇이 활성/비활성 상태, 그리고 사용자 인터페이스 요소로 간주되는지는 호스트 언어에 따라 다릅니다. 일반적인 문서에서는 대부분의 요소가 :enabled이나 :disabled 어느 쪽에도 해당하지 않습니다. 예를 들어 [HTML5]에서는 비활성화되지 않은 인터랙티브 요소를 :enabled로, 해당 요소가 명시적으로 비활성화된 경우를 :disabled로 봅니다.
참고: 특정 사용자 인터페이스 요소에 대한 사용자 상호작용 가능성에 영향을 줄 수 있는 CSS 속성들은 :enabled나 :disabled와 일치하는지 여부에 영향을 주지 않습니다; 예를 들어, display나 visibility 속성은 요소의 활성/비활성 상태에 영향을 미치지 않습니다.
12.1.2. 변경 가능성 가상 클래스: :read-only 및 :read-write
테스트
문서 언어에서 정의한 대로 사용자가 값을 변경할 수 있는 경우 해당 요소는 :read-write와 일치합니다. 그렇지 않으면 :read-only입니다.
예를 들어, [HTML5]에서는
비활성화되지 않았고
readonly도 아닌 <input> 요소가
:read-write와 일치하며,
contenteditable 속성이 true로 설정되어 있는 모든 요소도 마찬가지입니다.
12.1.3. placeholder-표시 가상 클래스: :placeholder-shown
테스트
- placeholder-shown.html (live test) (source)
- placeholder-shown.html (live test) (source)
- selector-placeholder-shown-emptify-placeholder.html (live test) (source)
- selector-placeholder-shown-type-change-001.html (live test) (source)
- selector-placeholder-shown-type-change-002.html (live test) (source)
- selector-placeholder-shown-type-change-003.html (live test) (source)
인풋 요소는 때때로
사용자가 무엇을 입력하면 될지에 대한 힌트(placeholder 텍스트)를 보여줄 수 있습니다.
예: [HTML5]의 placeholder 속성.
:placeholder-shown 가상 클래스는
그와 같은 플레이스홀더 텍스트가 표시되고 있는 input 요소에 적용됩니다.
이 텍스트는 속성, 실제 요소, 혹은 UA의 내장 규칙 등 다양할 수 있습니다.
placeholder
속성은
input과
textarea
요소에 플레이스홀더 텍스트를 부여합니다.
따라서 :placeholder-shown 클래스는
이런 플레이스홀더 텍스트가 표시되고 있을 때 일치합니다.
12.1.4. 자동 입력 가상 클래스: :autofill
:autofill 가상 클래스는 UA(사용자 에이전트)에 의해 자동으로 값이 채워지고, 아직 사용자가 직접 편집하지 않은 input 요소에 적용됩니다.
12.1.5. 기본 옵션 가상 클래스: :default
:default 가상 클래스는 유사한 요소 집합 내에서 '기본값'이 되는 1개 이상의 UI 요소에 적용됩니다. 주로 컨텍스트 메뉴 아이템, 버튼, select 목록/메뉴 등에 사용됩니다.
예: 여러 버튼 중 기본 제출 버튼, 팝업 메뉴의 기본 옵션.
select-many 그룹(피자 토핑 등)에서는 여러 요소가 :default와 일치할 수 있습니다.
[HTML5]에 따르면,
:default는 폼의 “기본 버튼”,
<select>에서 처음 선택된 <option> 및 몇몇 다른 요소에 적용됩니다.
12.2. 입력 값 상태(Input Value States)
12.2.1. 선택 옵션 가상 클래스: :checked, :unchecked, :indeterminate
라디오·체크박스 등은 사용자가 토글할 수 있으며, 일부 메뉴 아이템은 사용자가 선택하면 "체크됨" 상태가 됩니다. 이 상태를 입력 값 가상 클래스(input value pseudo-classes)가 나타냅니다.
위 요소가 "on" 토글 상태일 때
:checked
가상 클래스가 적용됩니다.
예를 들어 [HTML5]는
:checked 체크박스, 라디오버튼,
선택된 <option>이 :checked에 일치함을 정의합니다.
이와 같이 "off" 토글 상태가 되면
:unchecked
가상 클래스가 적용됩니다.
:checked나 :unchecked가 될 수 있는 요소가 "on"도 "off"도 아닐 경우, :indeterminate 가상 클래스가 적용됩니다. :indeterminate는 "checked" 개념이 없는 값이 미정상태인(예: 진행 퍼센트가 모호한 progress meter) 요소와도 일치합니다.
이 세 가상 클래스는 상호 배타적입니다; 한 요소가 이들 중 둘 이상에 동시 일치할 수 없습니다. (해당 개념이 없는 요소라면 어느 것도 일치하지 않을 수 있습니다.) "indeterminate" 개념이 호스트 언어에서 "checked"/"unchecked"와 독립적(plausible)일 경우 (예: HTML 체크박스의 indeterminate 상태와 checked 상태 각각이 별도 불리언일 때), 이 가상 클래스 매칭 용도로는 indeterminate가 checked/unchecked보다 우선합니다.
-
checkbox의
indeterminate속성이 true이면 :indeterminate에 일치; 아니면 :checked 또는 :unchecked에, 각각checked속성 값에 따라 일치. -
라디오 버튼은
checked속성이 true일 때 :checked에 일치. 아니면 한 라디오 그룹 내(checked가 있는 그룹)에서 :unchecked에 일치. (checked 속성이 false이면서 그룹에 checked 버튼 없음 or 유일)일 때 :indeterminate. -
option요소(select내)는selected속성에 따라 :checked 또는 :unchecked에 일치. (:indeterminate에는 해당 없음.) -
progress요소는value속성이 없으면 :indeterminate에 일치
입력 값 가상
클래스들은 본질적으로 동적이지만,
사용자 조작 기반일 뿐 아니라 문서의 의미 속성(예: [HTML5]의
selected, checked)에 의해 정의될 수도 있기에,
모든 미디어에 적용됩니다.
12.3. 입력 값 유효성 검사(Input Value-checking)
12.3.1. 유효성 가상 클래스: :valid 및 :invalid
요소의 값이나 콘텐츠가 문서 언어의 데이터 유효성 의미([XFORMS11], [HTML5] 등)에 맞춰 유효/무효할 때 각각 :valid 및 :invalid 가상 클래스가 적용됩니다. 유효성 의미가 없는 요소는 :valid이나 :invalid 둘 중 어느 것도 해당하지 않습니다.
참고: 제약조건이 하나도 없는 요소(따라서 항상 :valid인 경우)와,
애초에 데이터 유효성 의미 자체가 없는 요소(둘 다 해당 없음)는 다릅니다.
예: <input type="text"> 요소에는 제약조건이 없을 수 있지만,
p 요소는 유효성 개념이 없으므로
어느 쪽 가상 클래스와도 일치하지 않습니다.
12.3.2. 값 범위 가상 클래스: :in-range, :out-of-range
:in-range 및 :out-of-range 가상 클래스는 값 범위 제한이 있는 요소에만 적용됩니다. 요소가 문서 언어에서 정의한 범위 내 값(들)에 있으면 :in-range, 벗어나면 :out-of-range가 적용됩니다. 범위 제한이 없거나 폼 컨트롤이 아닌 요소는 :in-range나 :out-of-range 어느 쪽에도 해당하지 않습니다. 예를 들어 slider 컨트롤이 1~10만 표시하는데 값이 11이면 :out-of-range, 메뉴는 "A,B,C"만 있는데 값이 "E"이면 :out-of-range.
12.3.3. 입력 필수/옵션 가상 클래스: :required, :optional
테스트
폼 요소는 해당 폼이 유효하게 제출되기 위해 값을 반드시 입력해야 한다면 :required이고, 반드시 입력할 필요가 없다면 :optional입니다. 폼 요소가 아닌 것은 required/optional 상태와 무관합니다.
12.3.4. 사용자 상호작용 가상 클래스: :user-valid, :user-invalid
테스트
:user-invalid 및 :user-valid 가상 클래스는 각각 잘못된(invalid) 또는 올바른(valid) 입력이 있는 요소를 나타내지만, 이는 오직 사용자가 그 요소와 충분히 상호작용한 이후에만 해당합니다. 이 가상 클래스의 목적은 사용자가 입력상의 실수를 쉽게 인식하도록 돕는 데 있습니다.
이 가상 클래스들은 최소한, 사용자가 폼 제출을 시도한 뒤 그 입력 요소에 다시 상호작용하거나 폼을 리셋하기 전까지는 해당 요소와 일치해야 합니다. 또, 적절하게 오류를 강조해주기 위해 다른 시점에도 일치하게 할 수 있습니다. 예를 들어, :user-invalid는 사용자가 값을 바꾸고 포커스가 다른 요소로 이동한 후, 잘못된(:invalid) input 요소에 일치하기 시작할 수도 있고, 사용자가 올바르게 값을 수정한 이후에만 일치를 해제할 수도 있습니다.
호스트 언어는 더 구체적인 매칭 규칙을 정의하거나 플랫폼 관행에 위임할 수 있습니다; 아니면 정확한 동작은 UA 정의에 따릅니다. 어떤 경우든 :user-invalid 가상 클래스는 반드시 :invalid 요소에만, :user-valid 가상 클래스는 반드시 :valid 요소에만 일치해야 합니다. HTML 요소에 대한 구체적 규칙은 HTML 명세를 참고하세요. [HTML]
input
요소는 페이지가 로드되자마자 :invalid와 일치하게 된다
(이유는
input의
초기 값이 max 제약 조건을 위반하기 때문이다)
그러나 사용자가 입력 필드와 의미 있게 상호작용하거나
해당 입력을 포함하는 폼을 제출하려고 시도하기 전까지는
:user-invalid와 일치하지 않는다.
<form>
<label>
Volume:
<input name='vol' type=number min=0 max=10 value=11>
</label>
...
</form>
13. 트리 구조 기반 가상 클래스(Tree-Structural pseudo-classes)
Selector는 구조적 가상 클래스(structural pseudo-classes)라는 개념을 도입하여, 문서 트리 내 추가 정보를 기반으로 선택이 가능하지만 기존의 단순 선택자나 결합자로는 표현할 수 없는 경우를 다룰 수 있게 합니다.
독립 텍스트 노드 및 기타 비요소 노드는 부모의 자식 목록에서 요소의 위치를 계산할 때 포함되지 않습니다. 요소의 자식 목록에서 위치를 계산할 때, 인덱스 번호는 1부터 시작합니다.
구조적 가상 클래스는 문서 트리 내 요소에만 적용됩니다; 가상 요소(pseudo-elements)에는 절대 적용되어서는 안 됩니다.
13.1. :root 가상 클래스
:root 가상 클래스는 문서의 루트 요소를 나타냅니다.
예를 들어, DOM 문서에서
:root
가상 클래스는 문서 요소(document element)와 일치합니다.
HTML의 경우,
이는 보통
html
요소가 됩니다
(스크립트로 문서가 수정되지 않는 한).
13.2. :empty 가상 클래스
:empty 가상 클래스는 (선택적으로 문서 공백 문자만 제외하면) 자식이 없는 요소를 나타냅니다. 문서 트리 관점에서, 오직 요소 노드와 콘텐츠 노드 (예: [DOM] 텍스트 노드, 엔터티 참조) 중 실제 데이터 길이가 0이 아니면 비어있지 않은 것으로 간주합니다; 주석, 처리 명령, 기타 노드들은 요소가 비어있는지 여부에 영향을 주지 않습니다.
p
요소를 올바르게 선택합니다:
<p></p> <p> <p> </p> <p> <!-- comment --></p>
div:empty는 다음 조각의 <div> 요소에는 올바른 표현이 아닙니다:
<div>text</div> <div><p></p></div> <div> </div> <div><p>bla</p></div> <div>this is not <p>:empty</p></div>
참고: Selector Level 2, 3에서는 :empty가 공백만 포함한 요소에 일치하지 않았습니다. 하지만, HTML에서는 공백이 대체로 합쳐지고 소스 코드 포매팅에 사용되는 점, 특히 종료 태그가 생략된 요소에 DOM 텍스트 노드로 흡수될 수 있으므로, 작성자가 '비어있다'고 여기는 요소를 기대대로 선택할 수 있도록 변경되었습니다.
13.3. 자식-인덱스 기반 가상 클래스(Child-indexed Pseudo-classes)
테스트
- child-indexed-no-parent.html (live test) (source)
- child-indexed-pseudo-class.html (live test) (source)
- negated-nth-child-when-ancestor-changes.html (live test) (source)
- negated-nth-last-child-when-ancestor-changes.html (live test) (source)
- nth-child-containing-ancestor.html (live test) (source)
- nth-child-in-shadow-root.html (live test) (source)
- nth-child-of-attr-largedom.html (live test) (source)
- nth-child-of-attr.html (live test) (source)
- nth-child-of-class-prefix.html (live test) (source)
- nth-child-of-class.html (live test) (source)
- nth-child-of-has.html (live test) (source)
- nth-child-of-id-prefix.html (live test) (source)
- nth-child-of-ids.html (live test) (source)
- nth-child-of-in-ancestor.html (live test) (source)
- nth-child-of-in-is.html (live test) (source)
- nth-child-of-in-shadow-root.html (live test) (source)
- nth-child-of-is.html (live test) (source)
- nth-child-of-pseudo-class.html (live test) (source)
- nth-child-of-sibling.html (live test) (source)
- nth-child-when-ancestor-changes.html (live test) (source)
- nth-child-when-sibling-changes.html (live test) (source)
- nth-child-whole-subtree.html (live test) (source)
- nth-last-child-containing-ancestor.html (live test) (source)
- nth-last-child-in-shadow-root.html (live test) (source)
- nth-last-child-of-attr.html (live test) (source)
- nth-last-child-of-class-prefix.html (live test) (source)
- nth-last-child-of-class.html (live test) (source)
- nth-last-child-of-has.html (live test) (source)
- nth-last-child-of-id-prefix.html (live test) (source)
- nth-last-child-of-ids.html (live test) (source)
- nth-last-child-of-in-ancestor.html (live test) (source)
- nth-last-child-of-in-is.html (live test) (source)
- nth-last-child-of-in-shadow-root.html (live test) (source)
- nth-last-child-of-is.html (live test) (source)
- nth-last-child-of-pseudo-class.html (live test) (source)
- nth-last-child-of-sibling.html (live test) (source)
- nth-last-child-when-ancestor-changes.html (live test) (source)
- nth-last-child-when-sibling-changes.html (live test) (source)
- nth-child-and-nth-last-child.html (live test) (source)
- nth-child-of-attribute.html (live test) (source)
- nth-child-of-classname-002.html (live test) (source)
- nth-child-of-classname.html (live test) (source)
- nth-child-of-complex-selector-many-children-2.html (live test) (source)
- nth-child-of-complex-selector-many-children.html (live test) (source)
- nth-child-of-complex-selector.html (live test) (source)
- nth-child-of-compound-selector.html (live test) (source)
- nth-child-of-has.html (live test) (source)
- nth-child-of-nesting.html (live test) (source)
- nth-child-of-no-space-after-of.html (live test) (source)
- nth-child-of-not.html (live test) (source)
- nth-child-of-nth-child.html (live test) (source)
- nth-child-of-pseudo.html (live test) (source)
- nth-child-of-tagname.html (live test) (source)
- nth-child-of-universal-selector.html (live test) (source)
- nth-child-specificity-1.html (live test) (source)
- nth-child-specificity-2.html (live test) (source)
- nth-child-specificity-3.html (live test) (source)
- nth-child-specificity-4.html (live test) (source)
- nth-child-spurious-brace-crash.html (live test) (source)
- nth-last-child-invalid.html (live test) (source)
- nth-last-child-of-classname.html (live test) (source)
- nth-last-child-of-complex-selector.html (live test) (source)
- nth-last-child-of-compound-selector.html (live test) (source)
- nth-last-child-of-nesting.html (live test) (source)
- nth-last-child-of-no-space-after-of.html (live test) (source)
- nth-last-child-of-style-sharing-1.html (live test) (source)
- nth-last-child-of-style-sharing-2.html (live test) (source)
- nth-last-child-of-tagname.html (live test) (source)
- nth-last-child-specificity-1.html (live test) (source)
- nth-last-child-specificity-2.html (live test) (source)
- nth-last-child-specificity-3.html (live test) (source)
- nth-last-child-specificity-4.html (live test) (source)
- sharing-in-svg-use.html (live test) (source)
- parse-anplusb.html (live test) (source)
이 절에서 정의된 가상 클래스는 요소의 포함 형제(inclusive siblings) 중 인덱스를 기준으로 요소를 선택합니다.
참고: Selectors 3는 이런 선택자를 부모의 자식 목록 내 인덱스를 기준으로 선택한다고 설명했었습니다. (이 설명은 본 절의 명칭과 여러 가상 클래스의 명칭에 남아 있습니다.) 하지만 부모가 없거나 비요소 부모를 가진 경우에도 일치 여부를 제외할 이유가 없으므로, 요소의 형제 중 상대 인덱스를 기준으로 설명을 바꿨습니다.
13.3.1. :nth-child() 가상 클래스
테스트
:nth-child(An+B [of S]? ) 가상 클래스 표기법은 포함 형제 중 선택자 목록 S에 일치하는 요소들 목록의 An+B번째에 해당하는 요소를 나타냅니다. 여기서 S는 <complex-real-selector-list>입니다. S를 생략하면 기본값은 *|*입니다.
An+B 표기법과 해석은 CSS Syntax 3 § 6 The An+B microsyntax에 정의되어 있습니다. 여기서 임의의 음이 아닌 정수 n에 대해, i = An + B가 됩니다.
참고: 이때 요소 목록은 1부터 시작하는 인덱스입니다;
즉, 어떤 요소의 첫 번째 자식이라면 인덱스 1이며,
:nth-child(2n+1)과 일치합니다.
(왜냐하면 n=0일 때 식이 1로 평가되기 때문입니다.)
예를 들어, 이 선택자를 이용해 테이블에서 홀수 행을 선택하거나, 네 개 단위로 문단 색상을 순환 적용할 수 있습니다.
:nth-child(even) /* 2번째, 4번째, 6번째 등 요소 :nth-child(10n-1) /* 9번째, 19번째, 29번째 등 요소 */ :nth-child(10n+9) /* 동일 */ :nth-child(10n+-1) /* 문법적으로 잘못되어 무시됨 */
참고: :nth-child() 가상 클래스의 특이성은 일반 가상 클래스 한 개의 특이성에 더해, S가 지정됐다면 S에서 가장 특이성이 높은 복합 선택자의 특이성까지 더해집니다. § 15 선택자 특이성 계산 참고. 따라서 S:nth-child(An+B)와 :nth-child(An+B of S)는 특이성은 같지만 동작에는 차이가 있습니다 (아래 예시 참고).
:nth-child(-n+3 of li.important)
이는 아래와 같이 선택자를 함수 밖에 두는 것과 다릅니다:
li.important:nth-child(-n+3)
이 경우에는 첫 세 번째 자식이 "important" 리스트 항목일 때만 선택하게 됩니다.
일반적으로 테이블 행에 얼룩무늬를 넣기 위해 저자는 다음과 비슷한 CSS를 사용할 수 있습니다:
tr {
background: white;
}
tr:nth-child(even) {
background: silver;
}
하지만, 일부 행이 숨겨지거나 표시되지 않으면 패턴이 깨지고, 동일 색상이 연속될 수도 있습니다. HTML의 [hidden] 속성으로 행을 숨긴다고 가정하면, 다음 CSS로 숨겨진 행과 상관없이 정상순서로 백그라운드가 교차되게 할 수 있습니다:
tr {
background: white;
}
tr:nth-child(even of :not([hidden])) {
background: silver;
}
13.3.2. :nth-last-child() 가상 클래스
:nth-last-child(An+B [of S]? ) 가상 클래스 표기법은 포함 형제 중 선택자 목록 S에 일치하는 요소들 목록에서 뒤에서부터 An+B번째 요소를 나타냅니다. S는 <complex-real-selector-list>입니다. S가 생략되면 기본값은 *|*입니다.
참고: :nth-last-child() 가상 클래스의 특이성은 :nth-child()와 마찬가지로, 일반 가상 클래스의 특이성에 selector 인자 S의 특이성까지 합산됩니다. § 15 선택자 특이성 계산 참고.
CSS Syntax Module [CSS3SYN]에서는 An+B 표기법을 정의합니다.
tr:nth-last-child(-n+2) /* HTML 테이블의 두 마지막 행 */
foo:nth-last-child(odd) /* 부모 요소 내 모든 홀수번째 foo 요소,
뒤에서부터 계산 */
13.3.3. :first-child 가상 클래스
:first-child 가상 클래스는 포합 형제(inclusive siblings) 중 첫 번째인 요소를 나타냅니다. :nth-child(1)과 동일합니다.
div > p:first-child
이 선택자는 다음 코드 조각에서 div 내부의 p 요소를 가리킬 수 있습니다:
<p> The last P before the note.</p> <div class="note"> <p> The first P inside the note.</p> </div>
하지만 다음 예시에서 두 번째 p에는 적용되지 않습니다:
<p> The last P before the note.</p> <div class="note"> <h2> Note </h2> <p> The first P inside the note.</p> </div>
다음 두 선택자는 보통 서로 동등한 결과를 냅니다:
* > a:first-child /* a가 어떤 요소의 첫 자식일 때 */ a:first-child /* 동일(단, a가 루트 요소가 아닌 경우에 한함) */
13.3.4. :last-child 가상 클래스
:last-child 가상 클래스는 포함 형제(inclusive siblings) 중 마지막인 요소를 나타냅니다. :nth-last-child(1)과 동일합니다.
13.3.5. :only-child 가상 클래스
:only-child 가상 클래스는 형제가 없는 요소를 나타냅니다. :first-child:last-child 또는 :nth-child(1):nth-last-child(1)과 같지만, 특이성은 더 낮습니다.
13.4. 타입 자식-인덱스 기반 가상 클래스(Typed Child-indexed Pseudo-classes)
이 섹션의 가상 클래스들은 자식 인덱스 가상 클래스와 유사하지만, 형제 리스트 내에서 같은 타입(태그 이름)의 요소들 중 인덱스를 기준으로 결정됩니다.
13.4.1. :nth-of-type() 가상 클래스
:nth-of-type(An+B) 가상 클래스 표기법은
:nth-child(|An+B| of
S)와 같은 요소를 나타내며,
여기서 S는 해당 요소와 네임스페이스 접두사가 일치하는 타입 선택자입니다.
예를 들어,
HTML의
img
요소가 이 가상 클래스와 일치하는지 판단할 때,
S는 html|img입니다(적절한 html 네임스페이스가 선언된 경우).
img:nth-of-type(2n+1) { float: right; }
img:nth-of-type(2n) { float: left; }
참고: 요소의 타입이 미리 정해져 있다면, 이 가상 클래스는 타입 선택자를 사용해 :nth-child()를 쓰는 것과 같습니다. 예를 들어 img:nth-of-type(2)은 *:nth-child(2 of img)와 동일합니다.
13.4.2. :nth-last-of-type() 가상 클래스
:nth-last-of-type(An+B) 가상 클래스 표기법은
:nth-last-child(|An+B| of
S)와 동일한 요소를 나타냅니다.
여기서 S는 해당 요소와 네임스페이스 접두사가 일치하는 타입 선택자입니다.
예를 들어,
HTML의
img
요소가 이 가상 클래스에 일치하는지 볼 때,
S는 html|img이며(적절한 html 네임스페이스가 선언되었다고 가정).
body의 모든 h2 자식 중 첫 번째와 마지막을 제외하려면
다음 선택자를 사용할 수 있습니다:
body > h2:nth-of-type(n+2):nth-last-of-type(n+2)
이 경우, :not()을 사용할 수도 있지만, 선택자 길이는 비슷합니다:
body > h2:not(:first-of-type):not(:last-of-type)
13.4.3. :first-of-type 가상 클래스
테스트
- first-of-type.html (live test) (source)
- negated-always-matches-negated-first-of-type-when-ancestor-changes.html (live test) (source)
- negated-first-of-type-in-nonsubject-position.html (live test) (source)
- negated-is-always-matches-negated-first-of-type-when-ancestor-changes.html (live test) (source)
- negated-is-never-matches-negated-first-of-type-when-ancestor-changes.html (live test) (source)
- negated-negated-first-of-type-when-ancestor-changes.html (live test) (source)
- negated-never-matches-negated-first-of-type-when-ancestor-changes.html (live test) (source)
- of-type-selectors.xhtml (live test) (source)
:first-of-type 가상 클래스는 :nth-of-type(1)과 동일한 요소를 나타냅니다.
dl 안에 있는 정의 제목 dt 중,
부모의 자식 중 해당 타입으로 첫 번째인 dt를 나타냅니다.
dl dt:first-of-type
아래 예제에서 처음 두 dt에는 해당되지만,
세 번째 dt에는 해당되지 않습니다:
<dl>
<dt>gigogne</dt>
<dd>
<dl>
<dt>fusée</dt>
<dd>multistage rocket</dd>
<dt>table</dt>
<dd>nest of tables</dd>
</dl>
</dd>
</dl>
13.4.4. :last-of-type 가상 클래스
테스트
- negated-always-matches-negated-last-of-type-when-ancestor-changes.html (live test) (source)
- negated-is-always-matches-negated-last-of-type-when-ancestor-changes.html (live test) (source)
- negated-is-never-matches-negated-last-of-type-when-ancestor-changes.html (live test) (source)
- negated-last-of-type-invalidation.html (live test) (source)
- negated-negated-last-of-type-when-ancestor-changes.html (live test) (source)
- negated-never-matches-negated-last-of-type-when-ancestor-changes.html (live test) (source)
:last-of-type 가상 클래스는 :nth-last-of-type(1)과 동일한 요소를 나타냅니다.
13.4.5. :only-of-type 가상 클래스
:only-of-type 가상 클래스는 :first-of-type:last-of-type과 동일한 요소를 나타냅니다.
14. 결합자(Combinators)
14.1. 자손 결합자(Descendant combinator) ( )
때로는 저자가 문서 트리에서 어떤 요소가 다른 요소의 자손임을 선택자로 표현하고 싶을 때가 있습니다 (예: "em 요소가 H1 요소 내부에 있을 때"). 자손 결합자(descendant combinator)가 이런 관계를 나타냅니다.
자손 결합자는 두 복합 선택자 사이를 띄어쓰기로 구분합니다.
A B 형태의 선택자는
어떤 조상 요소 A의 임의의 자손인
요소 B를 나타냅니다.
h1 em
이 선택자는 em 요소가 h1 요소의 자손인 경우를 나타냅니다. 다음 코드 조각의 부분적인(전체는 아님) 설명으로 정확하게 사용될 수 있습니다:
<h1>This <span class="myclass">headline is <em>very</em> important</span></h1>
다음과 같은 선택자도 있습니다:
div * p
이 선택자는 p 요소가 div 요소의 손자 또는 그 이후 자손임을 의미합니다.
"*" 좌우의 공백은 범용 선택자(universal selector)의 일부가 아니라,
공백 자체가 결합자(combinator)이며,
div가 어떤 요소의 조상이어야 하고,
그 요소가 또 p의 조상이어야 함을 뜻합니다.
아래의 선택자는 자손 결합자와 속성 선택자(attribute selectors)를 조합합니다.
이는
(1) href 속성이 설정되어 있고
(2) div 안 p 안에 포함된 어떤 요소를 나타냅니다:
div p *[href]
14.2. 자식 결합자(Child combinator) (>)
자식 결합자(child combinator) 는 두 요소 사이의 부모-자식 관계를 설명합니다. 자식 결합자는 "보다 큰 부등호(greater-than sign)" (U+003E, >) 문자로 이루어지며, 두 복합 선택자 사이를 구분합니다.
body의 자식일 때를 나타냅니다:
body > p
다음 예시는 자손 결합자와 자식 결합자를 같이 사용한 예시입니다.
div ol>li p
이 선택자는 p 요소가 li 요소의 자손이고;
li 요소가
ol 요소의 자식이고; ol
요소가 div의 자손일 때를 나타냅니다.
">" 결합자 주변에 공백이 없어도 된다는 점에 주의하세요.
요소의 첫 번째 자식을 선택하는 방법은, 위의 :first-child 가상 클래스 부분을 참고하세요.
14.3.
인접 형제 결합자(Next-sibling combinator) (+)
테스트
인접 형제 결합자(next-sibling combinator)는 “플러스 기호”(U+002B, +) 문자로 두 복합 선택자를 구분합니다. 두 복합 선택자가 나타내는 요소들은 문서 트리에서 같은 부모를 가지며, 첫 번째 복합 선택자가 두 번째 복합 선택자보다 바로 앞서 등장해야 합니다. 인접성 판단 시 비요소 노드(예: 요소 사이의 텍스트)는 무시합니다.
math + p
아래 선택자는 이전 예시와 개념적으로 유사하지만, 속성 선택자를 추가하여
h1 요소에 class="opener"라는 조건을 더합니다:
h1.opener + h2
14.4.
후행 형제 결합자(Subsequent-sibling combinator) (~)
후행 형제 결합자(subsequent-sibling combinator)는 "틸드" (U+007E, ~) 문자로 두 복합 선택자를 구분합니다. 두 복합 선택자가 나타내는 요소는 문서 트리에서 같은 부모를 가지며, 첫 번째 복합 선택자가 두 번째 복합 선택자보다 먼저 등장하기만 하면 됩니다(바로 앞이 아님).
h1 ~ pre
이는 pre 요소가 h1 이후에 등장하는 것을 의미합니다.
아래는 그런 구조의 예시(부분 설명)입니다:
<h1>Definition of the function a</h1> <p>Function a(x) has to be applied to all figures in the table.</p> <pre>function a(x) = 12x/13.5</pre>
15. 선택자 특이성 계산(Calculating a selector’s specificity)
선택자의 특이성(specificity)은 아래와 같이 계산합니다:
- 선택자 안의 ID 선택자 개수 세기(= A)
- 선택자 안의 클래스 선택자, 속성 선택자, 가상 클래스 개수 세기(= B)
- 선택자 안의 타입 선택자와 가상 요소 개수 세기(= C)
- 범용 선택자는 무시
선택자가 선택자 리스트라면, 리스트 안 각 선택자마다 개별적으로 계산합니다. 리스트에 대해 매칭이 일어날 때는, 일치하는 선택자 중에서 가장 높은 특이성이 적용됩니다.
일부 가상 클래스는 다른 선택자용 “평가 컨텍스트”를 제공하므로, 특이성이 다르게 정의됩니다:
- :is(), :not(), :has() 가상 클래스의 특이성은 인자로 넣은 선택자 리스트 안에서 가장 특이성이 높은 복합 선택자의 특이성으로 대체됩니다.
- 마찬가지로, :nth-child()나 :nth-last-child() 선택자의 특이성은 그 가상 클래스 자체의 특이성(가상 클래스 1개로 간주) + 인자 선택자 리스트에서 가장 높은 복합 선택자의 특이성(있다면)을 합친 값입니다.
- :where() 가상 클래스의 특이성은 0으로 처리합니다.
- :is(em, #foo)는
<em>,<p id=foo>,<em id=foo>기준 모두 (1,0,0) — 즉 ID 선택자(#foo)와 동일한 특이성. - .qux:where(em, #foo#bar#baz)는 (0,1,0) — :where() 안쪽은 특이성 계산에서 제외, 바깥 .qux만 적용.
- :nth-child(even of li, .item)는
<li>,<ul class=item>,<li class=item id=foo>에 대해 모두 (0,2,0) — 클래스 선택자(.item) + 가상 클래스 하나로 간주. - :not(em, strong#foo)는 아무 요소에나 (1,0,1) — 태그 선택자(strong)와 ID 선택자(#foo)의 합.
특이성 비교는 세 개의 값을 차례대로 비교합니다: A가 더 크면 특이성이 더 높음; A가 같으면 B가 더 크면 특이성이 더 높음; B까지 같으면 C가 더 큰 쪽이 더 높음; 모두 같으면 특이성도 동등합니다.
저장 한계로 인해, 구현체는 A나 B, C의 크기에 제한이 있을 수 있습니다. 이 한계를 넘는 값은 그 한계치로 고정(clamp)되어야 하며 오버플로우하면 안 됩니다.
* /* a=0 b=0 c=0 */
LI /* a=0 b=0 c=1 */
UL LI /* a=0 b=0 c=2 */
UL OL+LI /* a=0 b=0 c=3 */
H1 + *[REL=up] /* a=0 b=1 c=1 */
UL OL LI.red /* a=0 b=1 c=3 */
LI.red.level /* a=0 b=2 c=1 */
#x34y /* a=1 b=0 c=0 */
#s12:not(FOO) /* a=1 b=0 c=1 */
.foo :is(.bar, #baz)
/* a=1 b=1 c=0 */
참고: 같은 단순 선택자(simple selector)가 반복 등장해도 허용되며, 등장할 때마다 특이성을 더합니다.
참고: HTML style 속성으로 지정한 스타일의
특이성은 CSS Style Attributes에서 설명합니다. [CSSSTYLEATTR]
16. 문법(Grammar)
선택자는 다음 문법에 따라 구문 분석됩니다:
<selector-list> = <complex-selector-list>
<complex-selector-list> = <complex-selector>#
<complex-real-selector-list> = <complex-real-selector>#
<compound-selector-list> = <compound-selector>#
<simple-selector-list> = <simple-selector>#
<relative-selector-list> = <relative-selector>#
<relative-real-selector-list> = <relative-real-selector>#
<complex-selector> = <complex-selector-unit> [ <combinator>? <complex-selector-unit> ]*
<complex-selector-unit> = [ <compound-selector>? <pseudo-compound-selector>* ]!
<complex-real-selector> = <compound-selector> [ <combinator>? <compound-selector> ]*
<relative-selector> = <combinator>? <complex-selector>
<relative-real-selector> = <combinator>? <complex-real-selector>
<compound-selector> = [ <type-selector>? <subclass-selector>* ]!
<pseudo-compound-selector> = <pseudo-element-selector> <pseudo-class-selector>*
<simple-selector> = <type-selector> | <subclass-selector>
<combinator> = '>' | '+' | '~' | [ '|' '|' ]
<wq-name> = <ns-prefix>? <ident-token>
<ns-prefix> = [ <ident-token> | '*' ]? '|'
<type-selector> = <wq-name> | <ns-prefix>? '*'
<subclass-selector> = <id-selector> | <class-selector> |
<attribute-selector> | <pseudo-class-selector>
<id-selector> = <hash-token>
<class-selector> = '.' <ident-token>
<attribute-selector> = '[' <wq-name> ']' |
'[' <wq-name> <attr-matcher> [ <string-token> | <ident-token> ] <attr-modifier>? ']'
<attr-matcher> = [ '~' | '|' | '^' | '$' | '*' ]? '='
<attr-modifier> = i | s
<pseudo-class-selector> = : <ident-token> |
: <function-token> <any-value> )
<pseudo-element-selector> = : <pseudo-class-selector> | <legacy-pseudo-element-selector>
<legacy-pseudo-element-selector> = : [before | after | first-line | first-letter]
위 문법을 해석할 때, 다음 규칙이 적용된다:
-
공백은 금지된다:
-
<compound-selector> 또는 <complex-selector-unit>의 최상위 구성 요소들 중 어느 것 사이에도(즉, <type-selector>과 <subclass-selector> 사이, 또는 <pseudo-element-selector>과 <pseudo-class-selector> 사이 등) 공백이 허용되지 않는다.
-
<type-selector> 또는 <class-selector>의 구성 요소들 어떤 것의 사이에도 공백이 있어서는 안 된다.
-
<pseudo-element-selector> 또는 <pseudo-class-selector>의 ':'들 사이, 또는 ':'와 <ident-token> 또는 <function-token> 사이에는 공백이 있어서는 안 된다.
-
<wq-name>의 구성 요소들 어떤 것의 사이에도 공백이 있어서는 안 된다.
-
<attr-matcher>의 구성 요소들 사이에는 공백이 있어서는 안 된다.
-
<compound-selector> 또는 <pseudo-compound-selector>들이 <complex-selector-unit> 안에 있는 경우, 그들 사이에 공백이 있어서는 안 된다.
-
<combinator>의 구성 요소들 사이에는 공백이 있어서는 안 된다.
두 <complex-selector-unit> 사이에 <combinator>이 생략된 경우에는 (이는 descendant combinator가 사용되고 있음을 나타낸다) 그들 사이에는 공백이 필수이다.
-
- <id-selector>에서, <hash-token>의 값은 반드시 식별자(identifier)여야 한다.
- <pseudo-class-selector> 생성은 <legacy-pseudo-element-selector> 생성을 제외한다. (즉, :before/등은 결코 의사-클래스로 파싱되어서는 안 된다. 예를 들어, 그 뒤에 다른 단순 선택자가 따라옴으로 인해 선택자가 유효해진다 해도 마찬가지이다.)
참고: 선택자는 또한 다양한 더 구체적인 문법적 제약의 영향을 받으며, 위 문법을 준수하는 것은 선택자가 유효하다고 간주되기 위한 필수적이지만 충분하지는 않다. 선택자 파싱에 대한 추가 규칙은 § 3.9 잘못된 선택자 및 오류 처리를 보라.
참고: 일반적으로 <pseudo-element-selector>는 <complex-selector>에서 마지막 <compound-selector>의 끝에 위치해야만 유효하다. 그러나 경우에 따라 이후에 더 많은 <pseudo-element-selector>들이나 <pseudo-class-selector>들이 올 수 있다; 이는 사례별로 규정된다. (예를 들어, 사용자 동작 의사-클래스들은 어떤 <pseudo-element> 뒤에도 허용되고, 트리 준수 의사-요소들은 ::slotted() 의사-요소 뒤에 허용된다.)
레벨 2의 네 가지 의사-요소들 (::before, ::after, ::first-line, ::first-letter)은 레거시 이유로 앞에 ':' 하나만 사용하여 쓸 수 있으며, 이로 인해 그것들이 <pseudo-class-selector>처럼 보일 수 있다.
16.1. <forgiving-selector-list> 및 <forgiving-relative-selector-list>
레거시 이유로 인해, 선택자 목록의 일반적 동작은 목록 내 어떤 선택자라도 파싱에 실패하면 (예를 들어 새로운 또는 UA 전용 선택자 기능을 사용해서) 전체 선택자 목록이 무효가 되는 것이다. 이로 인해 최신 선택자를 사용하면서도 구형 사용자 에이전트에서도 CSS가 제대로 작동하게 작성하는 것이 어려워질 수 있다.
<forgiving-selector-list> 생성 규칙은 대신 목록 내 각 선택자를 개별적으로 파싱하여, 파싱에 실패한 선택자는 단순히 무시하고, 남은 선택자들은 여전히 사용할 수 있게 한다.
참고: 스타일 규칙은 여전히 일반, 관대한 동작이 아닌, 기존의 선택자 목록 동작을 쓴다. <forgiving-selector-list>는 :is()와 :where()에서만 사용된다. 특이성에 약간의 영향은 있지만, 스타일 규칙의 선택자를 :is()로 감싸면 (내부에 의사-요소가 없다면 — 의사-요소는 :is()나 :where() 안에서 유효하지 않음) 실제로 "관대한" 목록으로 승격된다.
구문적으로, <forgiving-selector-list>는
<any-value>?와
동일하다.
실제 값은 관대한 선택자 목록으로 파싱하여 얻는다.
-
목록을 파싱하여 <complex-real-selector>들을 input에서 얻고, 결과를 selector list라고 한다.
-
selector list에서 실패 항목과 잘못된 선택자인 모든 항목을 제거한 뒤, 나머지 항목을 나타내는 <selector-list>를 반환한다. (이 목록은 비어 있을 수 있다.)
<forgiving-selector-list> 내에서 무효인 항목은 (알 수 없는 선택자나 문법을 사용해서 명시적으로 무효이거나, 혹은 알려진 문법이지만 문맥상 무효인 경우든) 특이성이 0인 것으로 간주되어야 한다.
참고: <forgiving-selector-list>는 의도적으로 :is()와 :where()에서만 사용되며, 선택자 인자를 받는 다른 어떤 선택자에서도 사용되지 않는다.
17. API 후크
Selectors 개념을 사용하는 명세서 작성을 돕기 위해, 이 섹션은 다른 명세서들이 호출할 수 있는 여러 API 후크를 정의한다.
이제 match와 invalid selector에 대한 더 엄격한 정의가 있을 때에도 이것들이 여전히 필요한가? 명사는 술어보다 명세 간 조정이 훨씬 쉽고, 예를 들어 querySelector에서 반환되는 요소들의 정확한 순서 같은 세부사항은 Selectors보다 DOM 명세에 정의되는 것이 더 합리적으로 보인다.
17.1. 선택자 파싱
이 절은 문자열 source로부터 선택자를 파싱하는 방법을 정의한다. 결과는 복합 선택자 목록이거나 실패이다.
- selector를 <selector-list>로 파싱한 결과라 하자. 만약 이것이 실패를 반환하면, 그것은 잘못된 선택자이다; 실패를 반환하라.
- 만약 selector가 어떤 다른 이유(예: 선언되지 않은 네임스페이스 접두사를 포함하는 등)로 인해 잘못된 선택자라면, 실패를 반환하라.
- 그렇지 않다면, selector를 반환하라.
17.2. 상대 선택자 파싱
이 절은 문자열 source로부터 상대 선택자를 파싱하는 방법을 정의한다. 결과는 복합 선택자 목록이거나 실패이다.
- selector를 <relative-selector-list>로 파싱한 결과라 하자. 만약 이것이 실패를 반환하면, 그것은 잘못된 선택자이다; 실패를 반환하라.
- 만약 selector가 어떤 다른 이유(예: 선언되지 않은 네임스페이스 접두사를 포함하는 등)로 인해 잘못된 선택자라면, 실패를 반환하라.
- 그렇지 않다면, selector를 반환하라.
17.3. 선택자를 요소에 매치
이 절은 선택자를 요소에 매치하는 방법을 정의한다.
이 알고리즘을 사용하는 API는 selector와 element를 제공해야 한다.
호출자는 선택적으로 다음을 제공할 수 있다:
- 하나 이상의 scoping root (:scope 의사-클래스 해석용)
이 알고리즘은 성공 또는 실패를 반환한다.
주어진 selector의 각 복잡 선택자 (즉, 복잡 선택자 목록의 각 항목)에 대해 아래 단락에 따라 해당 복잡 선택자를 element에 매치시킨다. 어떤 복잡 선택자에서라도 매치가 성공하면 알고리즘은 성공을 반환한다. 그렇지 않으면 실패를 반환한다.
복잡 선택자를 요소에 매치하기 위해서는, 복잡 선택자를 복합 선택자 단위로 오른쪽에서 왼쪽으로 하나씩 처리한다. 이 과정은 다음과 같이 재귀적으로 정의된다:
- 오른쪽 끝 복합 선택자의 단순 선택자 중 하나라도 요소와 일치하지 않으면, 실패를 반환한다.
- 그렇지 않고, 복합 선택자가 한 개뿐이라면 성공을 반환한다.
- 그렇지 않으면, 이 요소와 오른쪽 끝 결합자로 연결될 수 있는 모든 가능한 요소들을 고려한다. 이 때 이 선택자에서 오른쪽 끝의 복합 선택자와 결합자를 제거한 선택자를 해당 요소들 중 어느 하나에 매치하여 성공하면 성공을 반환한다. 그렇지 않으면 실패를 반환한다.
17.4. 선택자를 의사-요소에 매치
이 절은 선택자를 의사-요소에 매치하는 방법을 정의한다.
이 알고리즘을 사용하는 API는 selector와 pseudo-element를 제공해야 한다. 그들은 선택적으로 요소에 선택자를 매치할 때 제공할 수 있는 동일한 선택적 매개변수들을 제공할 수 있다.
이 알고리즘은 성공 또는 실패를 반환한다.
주어진 selector의 각 복합 선택자에 대해, 만약 다음 둘 다 참이면:
- 복합 선택자의 오른쪽 끝 단순 선택자가 pseudo-element와 일치하고, 그리고
- 복합 선택자의 나머지 부분(오른쪽 끝 단순 선택자만 제거된)에 대해 요소에 복합 선택자를 매치하는 알고리즘을 실행한 결과가 pseudo-element에 대응하는 요소 및 제공된 선택적 매개변수들과 함께 성공이라면,
그렇지 않으면 (즉, 어떤 복합 선택자에서도 이런 일이 일어나지 않으면), 실패를 반환한다.
17.5. 선택자를 트리에 매치
이 절은 선택자를 트리에 매치하는 방법을 정의한다.
이 알고리즘을 사용하는 API는 선택자와, 선택자가 검색할 서브트리를 나타내는 하나 이상의 root elements를 제공해야 한다. 모든 root elements는 동일한 루트를 공유해야 하며, 그렇지 않으면 이 알고리즘을 호출하는 것은 무효이다.
그들은 선택적으로 다음을 제공할 수 있다:
- 하나 이상의 scoping roots (선택자가 범위 지정되었음을 나타내기 위해).
- 매치 목록에 나타나도 되는 의사-요소들의 목록. 명시되지 않으면 기본적으로 모든 의사-요소를 허용한다.
이 알고리즘은 (비어 있을 수 있는) 요소 목록을 반환한다.
- candidate elements 목록으로 시작하라, 이는 root elements와 그 모든 자손 요소들이며, 특별한 지정이 없는 한 shadow-including tree order로 정렬된다.
- 만약 scoping root가 제공되었다면, candidate elements에서 적어도 하나의 scoping root의 자손이 아닌 요소들을 제거하라.
- selector match list를 빈 것으로 초기화하라.
-
candidate elements의 각 element에 대해:
- 만약 요소에 선택자 매치하기의 결과가 성공이면, 그 element를 selector match list에 추가하라.
-
매치 목록에 나타나도 되는 의사-요소들 중 해당 element와 연관된 가능한 각 의사-요소에 대해,
만약 의사-요소에 선택자
매치하기의 결과가 성공이면,
그 의사-요소를 selector match list에 추가하라.
의사-요소들의 상대적 위치는 정의되어 있지 않다. 아직 이 정보를 노출하는 문맥이 없지만, 언젠가는 무언가가 노출되기 전에 무언가를 결정해야 한다.
부록 A: 소스 문서 및 데이터를 요소 트리에 매핑하는 안내
이 절은 정보 제공용이다.
DOM이 설명하는 요소 트리 구조는 강력하고 유용하지만, 트리 기반 데이터(또는 적절한 해석을 통해 그래프 기반도) 를 설명하는 거의 모든 언어를 모델링할 수 있을 만큼 충분히 일반적이다.
HTML과 같은 일부 언어는 리소스에서 DOM 객체를 생성하는 잘 정의된 절차를 이미 가지고 있다. 주어진 언어가 그렇지 않다면, Selectors가 해당 언어의 문서에 적용되려면 그러한 절차가 정의되어야 한다.
최소한 문서 언어는 무엇이 DOM 개념의 "요소"에 매핑되는지를 정의해야 한다.
노드들 간의 주된 일대다 관계—트리 기반 구조의 부모/자식, 그래프 기반 구조의 요소/이웃—는 요소의 자식 노드로 반영되어야 한다.
요소의 다른 특징들은 DOM의 동일한 기능과 유사한 목적을 제공하는 어떤 것에 매핑되어야 한다:
- type
-
문서 언어의 요소들이 서로 다른 그룹을 구분하는 "type" 개념을 가지고 있다면,
그것은 "type" 특징으로 반영되어야 한다.
이 "type"을 "기본" 이름과 이름들을 더 높은 수준 그룹으로 묶는 "네임스페이스"로 구분할 수 있다면, 후자는 "namespace" 특징으로 반영되어야 한다. 그렇지 않으면, 요소는 "namespace" 특징을 가지지 않아야 하며, 전체 이름이 "type" 특징으로 반영되어야 한다.
- id
-
문서 전체에서 고유 식별자로 작동하는 어떤 측면이 있다면,
그것은 "id" 특징으로 매핑되어야 한다.
참고: HTML은 요소가 단일 ID만 가지도록 허용하지만, 이것을 일반적인 제한으로 받아들여서는 안 된다. ID의 중요한 성질은 각 ID가 단일 요소와 연결되어야 한다는 것이며; 단일 요소는 유효하게 여러 ID를 가질 수 있다.
- classes and attributes
- 식별에 유용하지만 문서 내에서 일반적으로 고유하지 않은 요소의 측면들은, 그것들이 "레이블"(그 자체로 문자열)에 해당하는지 아니면 "속성"(이름/값 쌍)에 해당하는지에 따라 "class" 또는 "attribute" 특징으로 매핑되어야 한다.
- pseudo-classes and pseudo-elements
-
어떤 요소들이 의사-클래스와 일치하거나 의사-요소를 가지는 경우,
그것은 명시적으로 정의되어야 한다.
일부 의사-클래스는 문법적(*)이다, 예를 들어 :has()와 :is() 처럼, 따라서 항상 작동해야 한다. 이 점을 어딘가에 명시할 필요가 있다. 아마도 자식 목록이 정렬된 경우에는 구조적 의사들은 항상 작동할 것이다.
- JSON 문서의 "요소"들은 각 배열, 객체, 불리언, 문자열, 숫자 또는 null이다. 배열과 객체 요소들은 그 내용을 자식으로 가진다.
- 각 요소의 타입은 그 JS 타입 이름이다: "array", "object" 등.
- 객체의 자식들은 그 키를 클래스로 가진다.
- 배열의 자식들은 :first-child, :nth-child() 등 의사-클래스와 일치한다.
- 루트 객체는 :root 와 일치한다.
- 또한 특정 값과 일치하거나 특정 부분 문자열을 포함하는 불리언/숫자/문자열 요소를 매치하기 위해 :val() 및 :contains() 의사-클래스들을 정의한다.
이 구조는 선택자를 사용하여 JSON 문서를 강력하고 간결하게 질의할 수 있게 해주기에 충분하다.
부록 B: 웹 호환을 위한 폐기되었지만 요구되는 -webkit- 파싱 이형성
이 부록은 규범적이다.
레거시 웹 호환 제약으로 인해, 웹 문서를 파싱할 것으로 예상되는 사용자 에이전트는 다음 기능들을 지원해야 한다:
-
:-webkit-autofill은 레거시 선택자 별칭으로 처리되어야 하며 :autofill과 동일하게 취급되어야 한다.
-
이름이 문자열 "-webkit-"으로 시작하는(ASCII 대소문자 구분 없이 매칭되는) 모든 다른 의사-요소들은 함수 표기법이 아닌 경우 구문 분석 시 유효한 것으로 처리되어야 한다. (즉, ::-webkit-asdf는 구문 분석 시 유효하지만, ::-webkit-jkl()는 유효하지 않다.) 만약 그것들이 따로 인식되거나 지원되지 않는다면, 아무것과도 일치하지 않는 것으로 처리되어야 하며, 알려지지 않은 -webkit- 의사-요소들로 취급되어야 한다.
알려지지 않은 -webkit- 의사-요소들은 ASCII 소문자 형태로 직렬화되어야 한다.
이 특성은 무엇에 관한 것인가?
선택자들은 오랫동안 단일의 알려지지 않았거나 잘못된 선택자가 전체 선택자 목록을 무효화하는 동작을 가져왔다 (그 선택자가 속한 한 개의 복합 선택자만 무효화하는 대신). 이는 일반적으로 WG에서 레거시 실수로 간주되지만, 너무 많은 스타일시트가 이 동작에 의존하고 있기 때문에 이제 고칠 수 없다.
이와 관련된 한 측면은 벤더 전용 선택자의 사용이 이를 인식하지 못하는 다른 사용자 에이전트들에서 전체 선택자를 무효화시키고, 그로 인해 전체 스타일 규칙이 사라진다는 것이다. 과거에는 일부 브라우저로부터 스타일 규칙을 숨기기 위해 의도적으로(강력히 권장되지 않는 방식으로) 사용되었고, 의도치 않게도 어떤 사람들이 요소를 스타일링하면서 해당 스타일을 벤더 전용 의사-요소(예: 일부 브라우저가 노출하는 다양한
input-관련 의사들)에도 적용하여 다른 브라우저들에서 규칙 전체가 숨겨지는 것을 깨닫지 못한 채 사용되기도 했다.이보다 더 일반적인 이유 외에도, WebKit 계열 사용자 에이전트들(예: Safari, Chrome)은 벤더 접두사가 붙은 의사-요소와 관련된 추가적인 특성을 가지고 있다. 즉, 어떠한 ::-webkit- 접두사가 붙은 선택자들도 구문 분석 시 유효한 것으로 간주된다. (이는 아마도 초기에 모든 가능한 의사-요소를 구문 분석 시 유효하다고 취급하도록 의도된 기능의 잔재로 보이며, 이후 제거된 기능으로, 저자가 자신만의 의사-요소를 정의할 수 있게 될 것을 예상했던 것으로 보인다.)
다른 레거시 특이성과 마찬가지로, [QUIRKS]에 문서화된 사례들처럼, 이 벤더 전용 특이성 또한 충분히 널리 퍼져서, 의도적이든 아니든 이에 의존하는 사이트들 때문에 다른 사용자 에이전트에서도 사이트가 깨지는 일이 발생하고 있다. 따라서 실질적으로 이 특이성은 최신 웹을 올바르게 렌더링하기 위해 필수이므로, 명세에서 이를 분명히 규정하고 모든 사용자 에이전트에 요구함으로써 오늘날의 웹페이지가 현재와 미래의 사용자 에이전트 모두에서 올바르게 렌더링될 가능성을 높일 수 있다.
그러나 특이성에 관해 언제나 그렇듯, 의도적으로 이 동작에 의존하는 웹페이지들은 CSSWG 구성원들과 건전한 웹 개발자들로부터 부정적인 평가를 받을 것이다.
부록 C: 개인 정보 보호를 고려한 :visited 제한 예시
예전에 :visited의 사용자 프라이버시 보호를 위해 시도된 방법들은 링크가 :visited인지 또는 :link인지에 대해 "거짓말"하도록 하는 복잡한 제한 및 동작들을 포함하여, 적대적인 사이트가 사용자가 방문한 관련 없는 사이트들을 관찰할 수 있는 가능성을 줄이려 했지만, 여전히 :visited가 모든 경우에 작동하도록 허용하면서도 사용자가 이미 클릭한 링크를 알 수 있게 해주려 했다. 이는 결국 이길 수 없는 전쟁이다; 이러한 완화책이 있어도 사용자의 방문 기록을 추출할 수 있는 여러 문서화된 방법들이 존재한다.
이 절에서는 https://github.com/explainers-by-googlers/Partitioning-visited-links-history에서 처음 개발되어 문서화된 접근법을 설명한다. 이 방법은 사용자의 방문 기록 정보를 분할하여, 사이트의 오리진이 직접 관찰할 수 있었던 내비게이션에 해당하는 링크에만 :visited가 일치하도록 한다. 이렇게 하면 :visited는 일반적인 의사-클래스처럼 취급될 수 있으며, 위에서 설명한 복잡한 완화책 없이도 사이트에 이론적으로 이미 알려진 정보 이외의 어떤 정보도 노출하지 않으면서, 사용자를 위한 유용성도 최대한 보존할 수 있다.
-
visited history를 세 가지 정보 조각들의 튜플들을 포함하는 집합으로 정의하라:
-
내비게이션이 페이지 내에서 트리거될 때마다—예: 사용자가 링크를 클릭하거나, 페이지의 스크립트가 내비게이션을 시작하는 경우—visited history에 항목을 추가하여 내비게이션의 목적지 URL, 링크나 스크립트를 포함한 페이지의 오리진, 그리고 그 페이지를 포함하는 최상위 사이트(스킴 포함)를 기록하라.
참고: 이는 사이트가 자사 오리진 내 어디에서든 사용자가 클릭한 링크에 대한 :visited 정보를 볼 수 있게 한다. 다시 말해, 사이트가 A일 때의 모든
A -> B내비게이션에 대해 허용된다.추가로, 최상위 프레임이거나 최상위 프레임과 동일 오리진인 iframe에서 발생한 내비게이션에 대해서만, 목적지의 URL, 목적지의 오리진, 그리고 목적지의 사이트를 기록하는 항목을 visited history에 추가하라.
참고: 이는 어떤 사이트가 자사 페이지들에 대한 :visited 정보를 (사이트가 이미 관찰할 수 있는 정보) 해당 페이지로의 내비게이션을 누가 시작했는지와 관계없이 볼 수 있도록 허용한다. 다시 말해, 사이트가 B일 때의 모든
A -> B내비게이션에 해당한다.참고: 사용자 에이전트의 UI에 의해 직접 트리거되는 내비게이션들— 예: 주소 표시줄에 입력하거나, 북마크 클릭, 또는 다른 프로그램에서 링크를 드래그하여 페이지로 끌어오는 경우—은 visited history 항목을 추가하지 않는다. 이러한 것들은 물론 URL 표시줄에 입력할 때 URL 추천 등 브라우저가 다른 목적으로 사용하는 방문 사이트 기록에는 여전히 추가될 수 있다.
-
링크 요소가 :link 또는 :visited와 일치하는지 판단할 때, 링크의 목적지, 링크를 포함한 페이지의 오리진, 그리고 링크를 포함한 최상위 사이트가 visited history의 튜플과 일치하는 경우에만 해당 링크가 :visited와 일치하도록 허용하라.
-
만약 방문 기록 항목이 시작 사이트의 URL로만 키가 지정된다면, 추적 사이트는 여러 사이트에 숨겨진 iframe으로 포함되어 첫 방문 시 사용자에 대해 고유한 URL로 내비게이션을 트리거하고, 이후 방문들에서 많은 링크들을 사용하여 어떤 것이 방문되었는지 확인함으로써 새로운 "서드파티 쿠키"처럼 사용자를 식별할 수 있다. 방문 기록 항목을 최상위 사이트로 키를 지정함으로써, 이 정보는 다른 사이트들 간에 공유될 수 없다.
-
만약 방문 기록 항목이 최상위 사이트의 URL로만 키가 지정된다면, 악의적인 iframe(예: 광고의 일부로 포함된)이 최상위 사이트에서 어떤 사이트들이 방문되었는지를 관찰할 수 있다. 방문 기록 항목을 링크 자체의 사이트로 키를 지정하면, 최상위 사이트의 정보가 교차 오리진 iframe으로 "유출"되는 것을 방지할 수 있다.
18. 변경 사항
18.1. 2022년 11월 11일 워킹 드래프트 이후 변경
2022년 11월 11일 워킹 드래프트 이후의 주요 변경사항:
-
:read-write와 :has()의 at-risk 상태를 제거함
-
새로운 :popover-open 의사-클래스를 추가함. (Issue 8637)
-
:has()와 :nth-child()/:nth-last-child()의 선택자 인수가 더 이상 forgiving이 아니게 됨. (Issue 7676)
-
레거시 단일 콜론 의사-요소 문법을 문법 자체로 이동시킴. (Issue 8122)
-
:local-link 의사-클래스를 레벨 5로 연기함. (Issue 12799)
-
:interest-source 및 :interest-target 의사-클래스를 레벨 5로 연기함. (Issue 12799)
-
:blank 의사-클래스를 레벨 5로 연기함. (Issue 12799)
-
그리드 구조(열) 선택자를 레벨 5로 연기함. (Issue 12799)
-
시간 차원 의사-클래스들을 레벨 5로 연기함. (Issue 12799)
18.2. 2022년 5월 7일 워킹 드래프트 이후 변경
2022년 5월 7일 워킹 드래프트 이후의 주요 변경사항:
-
새로운 :open 의사-클래스를 추가함. (Issue 7319, Issue 11039)
-
의사-요소들이 :has() 내에서 명시적으로 허용되지 않는 한 허용되지 않도록 정의함. (Issue 7463)
-
:has()의 중첩을 금지함. (Issue 7344)
-
::lang("")과 언어 태그가 없는 요소들의 매칭을 정의함. (Issue 6915)
-
"스코프된"과 "상대적" 선택자의 개념을 완전히 분리함. (Issue 6399)
-
"선택자 절대화"도 제거하고, 상대 선택자 매칭을 앵커 요소 관점으로 정의함.
-
-
:nth-child()에 대한 합성 선택자 제한을 되돌림. (Issue 3760)
-
:-webkit-autofill을 레거시 선택자 별칭으로 정의함. (Issue 7474)
18.3. 2018년 11월 21일 워킹 드래프트 이후 변경
2018년 11월 21일 워킹 드래프트 이후의 주요 변경사항:
- 선택자 프로파일을 제거하고, :has()를 선택적(at-risk)으로 표시함. (Issue 3925)
- 하위 의사-요소를 정의하고 관련 용어를 규정하는 § 3.6.4 Sub-pseudo-elements를 추가함.
- :defined를 추가함. (Issue 2258)
- :modal를 추가함. (Issue 6965)
- :fullscreen 및 :picture-in-picture를 추가함. (Issue 3796)
- :seeking, :buffering, 및 :stalled 미디어 재생 상태 의사-클래스를 추가함. (Issue 3821)
- :muted 및 :volume-locked 사운드 상태 의사-클래스를 추가함. (Issue 3821 및 Issue 3933)
- :autofill를 추가함. (Issue 5775)
- :user-valid를 추가함. (Discussion)
- :is(), :where(), :has(), :nth-child(), 및 :nth-last-child()가 내부에 잘못된 선택자가 있어도 그들 자체가 무효화되지 않도록 정의함. (Issue 3264)
- :nth-child() 및 :nth-last-child()의 선택자를 당분간 합성 선택자로 제한함. (Issue 3760)
- 문자열 일치의 대소문자 민감도를 [INFRA]의 문자열 동일성 정의를 참조하여 명확히 함.
- UA가 제공하는 플레이스홀더 텍스트도 여전히 :placeholder-shown을 트리거한다는 점을 명확히 함.
- :focus-visible 정의를 명확히 하기 위해 재작성함.
- 문법 섹션의 알림 문구를 규범적 텍스트로 바꿔, <compound-selector>들 사이에 <combinator> 토큰이 없을 경우 공백이 필요함을 기술함.
18.4. 2018년 2월 2일 워킹 드래프트 이후 변경
2018년 2월 2일 워킹 드래프트 이후의 주요 변경사항:
- :where()라는 이름으로 제로 특이성 선택자를 명명함. (Issue 2143)
- :matches()를 :is()로 이름 변경함. (Issue 3258)
- :empty를 공백 문자만 포함하는 노드를 무시하도록 재정의함. (Issue 1967)
- :blank를 빈 사용자 입력을 나타내도록 재정의함(빈 요소가 아님). (Issue 1283)
- :is(), :has(), 및 :nth-child()의 특이성이 어떤 선택자 인수가 일치했는지에 의존하지 않도록 변경함. (Issue 1027)
- HTML이 관련 기능을 제거했으므로 :drop() 의사-클래스를 제거함. (Issue 2257)
- :focus-visible에 대한 추가 지침을 추가함.
- 속성 선택자에 대소문자 구분 플래그 s를 추가함. (Issue 2101)
- Appendix B에 -webkit- 파싱 특이성을 정의함. (Issue 3051)
- 공백이 허용되는 위치에 관한 문법 규칙을 재작성함. (참조: § 16 문법.)
18.5. 2013년 5월 2일 워킹 드래프트 이후 변경
2013년 5월 2일 워킹 드래프트 이후의 주요 변경사항은 다음을 포함한다:
- :target-within, :focus-within, :focus-visible, :playing, :paused 의사-클래스를 추가함.
- 제로 특이성 :matches()-유형의 의사-클래스(이름 미정)를 추가함.
- 주체 지시자(!) 기능을 :has()로 대체함.
- :nth-match() 및 :nth-last-match() 선택자를 :nth-child(… of selector) 및 :nth-last-child(… of selector)로 대체함.
- :active-drop-target, :valid-drop-target, :invalid-drop-target를 :drop()으로 대체함.
- 비었거나 공백만 있는 선택자를 스케치로 제시함 (참고: open issue)
- :user-error를 :user-invalid로 이름 변경함. (토론 참조)
- :nth-column()/:nth-last-column()을 :nth-col()/:nth-last-col()로 이름 변경하여 잠재적인 ::column 의사-클래스와의 이름 혼동을 피함.
- :local-link 의사-클래스의 비함수형식을 프래그먼트 URL을 고려하도록 변경함.
:local-link()의사-클래스와 참조 결합자 기능을 관심 부족으로 제거함.- 선택자 문법을 CSS 값 정의 문법(CSS Value Definition Syntax)으로 재작성함.
- 상대 선택자를 스코프 선택자에서 분리함, 이는 서로 다른 개념이며 독립적으로 호출될 수 있음.
- <An+B> 마이크로신택스 정의를 CSS Syntax로 이동함.
-
새로운 섹션이 추가됨:
- § 3.2 데이터 모델
-
§ 17 API 후크
- 이전 버전에서는 선택자의 평가(evaluating a selector)절이 있었으나, 이 절은 더 이상 존재하지 않는다. 이 절을 참조하던 명세서는 대신 트리에서 선택자 매치하기 알고리즘을 참조해야 한다.
- :matches()와 :not() 내부의 결합자에 대한 제한을 제거함; 토론 참조.
- 선택자 목록의 특이성 정의 추가 (이유?).
- :lang() 값에 별표(*)가 있을 경우 따옴표를 필수로 함; CSS 식별자가 될 수 있는 언어 코드에만 따옴표 없이 사용 가능.
참고: 2018년 2월 1일 초안에는 미완성 작업의 실수 커밋이 포함되었으나; 2월 2일 초안이 해당 커밋을 되돌리고(그리고 몇몇 링크를 고쳤다).
18.6. 2012년 8월 23일 워킹 드래프트 이후 변경
2012년 8월 23일 워킹 드래프트 이후의 주요 변경사항은 다음을 포함한다:
- :placeholder-shown 의사-클래스 추가.
- :matches() 및 :not()에 대한 일부 제한 완화.
- 빠르고 완전한 선택자 프로파일 정의(현재는 "live"와 "snapshot") 추가.
- :matches() 처리 개선을 위한 특이성 정의 개선.
- 문법 업데이트.
- <An+B> 표기 관련 정리.
- scope-relative 선택자 정의 추가 및 scope-constrained 명칭 변경 등.
- :local-link()가 후행 슬래시를 무시하도록 변경.
18.7. 2011년 9월 29일 워킹 드래프트 이후 변경
2011년 9월 29일 워킹 드래프트 이후의 주요 변경사항은 다음을 포함한다:
- RFC 4647에 따른 언어 변형 처리 추가.
- 스코프된 선택자 추가.
- :user-error 추가(현재는 :user-invalid로 불림).
- :valid-drop-target 추가.
- 열 결합자(column combinator)를 이중 슬래시에서 이중 파이프로 변경.
18.8. 레벨 3 이후 추가 사항
레벨 3 이후의 추가 사항:
- :not()가 선택자 목록을 허용하도록 확장됨.
- :is(), :where(), :has() 추가.
- :scope 추가.
- :any-link 추가.
- :target-within, :focus-within, :focus-visible 추가.
- :dir() 추가.
- :lang()의 와일드카드 및 언어 코드 목록 수용으로 확장됨.
- :nth-child()가 선택자 목록을 수용하도록 확장됨.
- 입력 선택자들이 병합되어 :indeterminate 추가.
- :user-invalid 추가.
- 대소문자 구분 속성 값 매칭 플래그 추가.
19. 감사의 글
CSS 작업 그룹은 그동안 이전 선택자 명세들에 기여한 모든 이들에게 감사를 표한다. 특히 Selectors Level 4에 구체적으로 기여한 다음 분들께 특별한 감사를 전한다: L. David Baron, Andrew Fedoniouk, Daniel Glazman, Ian Hickson, Grey Hodge, Lachlan Hunt, Anne van Kesteren, Jason Cranford Teague, Lea Verou
개인정보 보호 고려사항
- :visited 의사-클래스는 UA가 어떤 요소들이 이에 일치하는지를 드러내는 정보를 스크립팅으로부터 차단하지 않으면 사용자가 이전에 방문한 사이트에 관한 정보를 노출할 수 있다.
- :autofill 의사-클래스는 사용자가 이 폼과 이전에 상호작용했는지를 노출할 수 있다; 그러나 동일한 정보는 폼이 얼마나 빨리 채워지는지를 관찰함으로써도 파생될 수 있다.
보안 고려사항
개인정보 보호 고려사항은 보안에 영향을 미칠 수도 있다.