관련 문서: CSS
프로그래밍 언어 문법 | ||
{{{#!wiki style="margin: -16px -11px; word-break: keep-all" | <colbgcolor=#0095c7><colcolor=#fff,#000> 언어 문법 | C(포인터 · 구조체 · size_t) · C++(자료형 · 클래스 · 이름공간 · 상수 표현식 · 특성) · C# · Java · Python(함수 · 모듈) · Kotlin · MATLAB · SQL · PHP · JavaScript · Haskell(모나드) |
마크업 문법 | HTML · CSS | |
개념과 용어 | 함수(인라인 함수 · 고차 함수 · 람다식) · 리터럴 · 상속 · 예외 · 조건문 · 참조에 의한 호출 · eval | |
기타 | #! · == · === · deprecated · NaN · null · undefined · 배커스-나우르 표기법 | |
프로그래밍 언어 예제 · 목록 · 분류 | }}} |
1. 개요
選擇子 / SelectorCSS에서 스타일을 입힐 HTML 등 마크업 언어의 요소를 선택하는 문자이다.
#!syntax css
선택자 { (스타일 속성): (스타일 값); }
HTML 요소에 스타일을 입히는 대부분의 CSS 코드는 위와 같은 구조로 이루어져 있다. 보다시피 스타일들을 나열한 중괄호의 앞부분에 오는 게 바로 선택자이다.
스크립트 언어에서도 선택자를 사용할 수 있다. jQuery에서는
$('선택자')
와 같은 방식으로 HTML 태그를 선택한다. 바닐라 자바스크립트에서는 document.querySelector('선택자')
와 document.querySelectorAll('선택자')
의 두 가지 방법이 있는데, 전자는 해당 선택자의 기준을 만족하는 요소 중 첫 번째 요소만 반환하고, 후자는 해당 선택자의 기준을 만족하는 모든 요소를 배열 형태[1]로 반환한다.나무위키에서는 wiki, html 문법에서 인라인 스타일, 즉 태그에 직접 적용되는 스타일만 다루기 때문에 나무위키에서 선택자를 사용할 일은 사실 없다.
2. 종류 및 문법
이 문단에서는 혼동을 피하기 위해 '바로 아래' 같은 모호한 표현 대신 특수한 표현을 사용한다.- '부모'/'자식'은 어떤 태그 안에 다른 태그가 있는 관계를 뜻한다. 예를 들어
<p><span></span></p>
와 같은 구조에서 <span>은 <p>의 자식이고, <p>는 <span>의 부모이다. - '형제'는 같은 부모를 둔 태그들을 뜻한다. 예를 들어
<p><span></span><img></p>
와 같은 구조에서 <span> 바로 다음에 오는 형제는 <img>이다.
*
이나 유형 선택자가 맨 앞에 오고, 그 뒤에 button.foo.bar:hover
와 같이 여러 종류를 중첩할 수 있고, 태그 없이 다른 선택자만 중첩할 수도 있다. 예시로 든 선택자는 'foo', 'bar' 클래스의 <button>
태그 중 마우스를 올린 요소를 선택한다는 의미이다. p.foo, p.bar, ...
와 같은 형태로 콤마로 구분하면 여러 선택자를 한꺼번에 선택할 수도 있다.구조 선택자의 경우 인자로 수열을 받는 선택자가 있는데,
an+b
/an
형태의 등차수열이나 even
(짝수, =2n), odd
(홀수, =2n+1)이 올 수 있다. 이때 첫 번째 자식이 1이며, n은 0 이상의 정수이다. -n+3
과 같이 써서 처음 3개만 선택할 수도 있다.2.1. 기본 선택자
- 전역 선택자
* 모든 요소를 선택한다.
- 유형 선택자
태그 해당 태그의 요소를 선택한다.
- ID 선택자
#ID 해당 ID의 요소를 선택한다.
- 클래스 선택자
.클래스 해당 클래스의 요소를 선택한다. [2]
- 속성 선택자
[속성] <colbgcolor=#fff,#1c1d1f>태그에 해당 속성이 명시되어 있는 요소를 선택한다.[3] [속성=문자열] 태그에 해당 속성이 명시되어 있고 그 값이 해당 문자열인 요소를 선택한다. [속성~=문자열] 해당 속성의 값에 해당 문자열이 완전한 단어로(즉, 앞뒤가 띄어쓰기로 구분되어서) 포함되어 있는 요소를 선택한다. [속성|=문자열] 해당 속성의 값이 해당 문자열이거나 그 뒤에 하이픈(-)이 붙는 것으로 시작하는 요소를 선택한다.[4] [속성*=문자열] 해당 속성의 값에 해당 문자열이 포함되어 있는 요소를 선택한다.[5] [속성^=문자열] 해당 속성의 값이 해당 문자열로 시작하는 요소를 선택한다. [속성$=문자열] 해당 속성의 값이 해당 문자열로 끝나는 요소를 선택한다.
2.2. 가상 클래스(pseudo-class)
- 구조 선택자
:first-child <colbgcolor=#fff,#1c1d1f>형제 중 첫 번째로 오는 요소를 선택한다. :last-child 형제 중 마지막으로 오는 요소를 선택한다. :nth-child(수열) 형제 중 (수열) 번째에 있는 요소를 선택한다. :nth-last-child(수열) 형제 중 뒤에서 (수열) 번째에 있는 요소를 선택한다. :nth-of-type(수열) 태그별로 형제 중 (수열) 번째에 있는 요소를 선택한다. 태그 이외 다른 선택자에는 반응하지 않는다.
- 반응 선택자
:active <colbgcolor=#fff,#1c1d1f>클릭하고 있는 요소를 선택한다. :hover 커서가 올라와 있는 요소를 선택한다.
- 상태 선택자
:checked 체크되어 있는 <input> 체크박스, 라디오 버튼이나 드롭다운 메뉴의 선택되어 있는 선택지(<option>)를 선택한다. :focus <colbgcolor=#fff,#1c1d1f>현재 입력하고 있는, 즉 커서가 깜박이고 있는 요소를 선택한다. :enabled 활성화되어 있는, 즉 내용을 수정할 수 있는 요소를 선택한다. :disabled 비활성화되어 있는, 즉 내용을 수정할 수 없는 요소를 선택한다.
- 링크 선택자
:link <colbgcolor=#fff,#1c1d1f>href 속성이 명시된[6] <a> 요소를 선택한다. :visited 방문했던 링크가 걸린 요소를 선택한다.
- 부정 선택자
:not(선택자) 해당 선택자에 해당하지 않는 요소들을 선택한다.
- :root 선택자
:root html 전체를 선택한다.[7] 보통 전역 변수를 선언할 때 쓴다.
2.3. 가상 요소(pseudo-element)
특정한 요소를 고르는 것이 아니라 이미 선택된 요소의 특정 부분에 스타일을 적용한다. 콜론(:)을 2개 사용하며, CSS Level 3 이전에는 콜론 1개를 사용했었기 때문에 1개만 써도 대부분의 브라우저에서는 정상적으로 작동하긴 하지만 권장하지 않는다.- 가상 요소
::first-letter <colbgcolor=#fff,#1c1d1f>첫 번째 글자를 선택한다. ::before
의 영향을 받는다. 특정한 CSS 속성만 사용할 수 있는 제한이 있다(영어).[8]::first-line 첫 번째 줄을 선택한다. 특정한 CSS 속성만 사용할 수 있는 제한이 있다(영어). ::before 태그 앞에 위치하는 공간을 선택한다. CSS 속성 'content'를 이용하여 이 공간에 추가로 내용을 입력할 수 있다. ::after 태그 뒤에 위치하는 공간을 선택한다. ::before
와 같이 'content'를 이용하여 이 공간에 추가로 내용을 입력할 수 있다.::selection 드래그한 글자를 선택한다. 'color', 'background-color', 'cursor', 'caret-color', 'outline-*', 'text-decoration-*', 'text-shadow' 속성만 적용할 수 있다.
2.4. 조합자
- 후손 조합자
(선택자 1) (선택자 2) 선택자 1의 모든 하위 요소(자식, 자식의 자식, ...) 중 선택자 2를 선택한다.
- 자손 조합자
(선택자 1) > (선택자 2) 선택자 1 바로 밑의 자식 중 선택자 2를 선택한다.
- 동위 조합자
(선택자 1) + (선택자 2) <colbgcolor=#fff,#1c1d1f>선택자 1의 형제 중 바로 다음에 오는 선택자 2 하나를 선택한다. (선택자 1) ~ (선택자 2) 선택자 1의 형제 중 자신보다 다음에 오는 모든 선택자 2를 선택한다.
3. 특이성
한 요소를 가리키는 스타일이 2개 이상 있을 때, 스타일이 정의된 선택자의 종류와 개수에 따라 특이성(specificity) 점수가 계산되고 더 높은 특이성을 가진 선택자의 스타일이 적용된다.원문은 specificity이며 한국어 명칭이 통일되지 않아 여러 가지 이름으로 불린다. 크로뮴 기반 브라우저 개발자 도구에서 사용하는 명칭이 특이성이며, MDN 문서의 한국어 번역 기여본에서는 명시도, 그 밖에 특수성, 특이도 등 많은 명칭이 혼재되고 있다. 이 문서에서는 특이성으로 서술한다.
특이성은 3개의 점수(A, B, C)가 따로 있으며, A 점수를 먼저 비교해서 같으면 B, 그다음 C 점수를 차례대로 비교한다. 올림픽 메달 순위 집계 방식으로 생각하면 된다. 이 방식은 Selectors Level 4부터 적용되었으며, Level 3까지는 총점수를 로 계산하여 비교했었다.[9]
각 점수는 아래 선택자의 개수에 따라 정해진다.
- A: ID 선택자
- B: 클래스 선택자, 속성 선택자, 가상 클래스
- C: 유형 선택자, 가상 요소
이밖에 전역 선택자(*), 조합자 등은 특이성에 영향을 주지 않는다. 이 점수를 플랑크톤, 물고기, 상어에 비유한 Specifishity라는 사이트가 있어 참고하면 좋다.
만약 특이성 점수가 같을 경우에는 나중에 적은 속성이 이전에 적은 속성을 덮어씌우고 적용된다. 애시당초 CSS의 본말이 'Cascading' Style Sheet('내리' 꾸미기 서식) 이다.
<style>
태그 사용(internal style)과 <link>
태그 사용(external style)은 우선순위가 동등하여 위의 글처럼 나중에 서술된 속성이 반영된다. 그러나 웹 브라우저나 네트워크 환경에 따라 호이스팅[10]이 발생할 수 있기 때문에 웹 브라우저에서 확인해야 한다.인라인 스타일, 즉,
<div style="color: red;">
와 같이 태그 자체에 정의된 스타일은 CSS 파일의 특이성 점수를 무시하고 우선적으로 적용된다.속성값 뒤에
!important
를 붙일 경우 모든 규칙을 무시하고 우선적으로 적용된다. 그렇기 때문에 스타일 시트 내 자연스러운 종속을 깨뜨려 디버깅을 더 어렵게 만든다. 따라서 일반적으로 브라우저에서 CSS를 테스트해 보는 등의 특수한 상황 외에는 사용하는 것이 권장되지 않는다. 만약 !important
를 가진 스타일조차 2개일 경우 !important
스타일이 정의된 선택자의 특이성 점수에 따라 적용된다.[1] 다만 실제 배열 자료형은 아니고 유사 배열이라 배열 메소드를 사용하려면
[...document.querySelectorAll('선택자')]
와 같이 실제 배열로 바꾸는 과정이 필요하다.[2] 클래스 여러 개가 모두 있는 요소를 선택할 경우 .foo.bar
처럼 해당 클래스명을 붙여서 쓴다.[3] 예를 들어 input[disabled]
는 (disabled에 무슨 값을 지정했는지에 상관없이, 심지어 값을 아예 지정하지 않고 disabled만 명시해도) 해당 속성이 있는
태그를 선택한다.[4] 예를 들어 [lang|=zh]
는 lang 속성이 zh, zh-CN, zh-TW, ...인 요소를 모두 선택한다. (출처)[5] 예를 들어 어떤 요소의 클래스를 yellow box
의 2개로 설정했을 때, [class*=ow]
의 경우 yellow
클래스에 'ow'가 있으므로 선택이 되지만, [class~=ow]
의 경우 ow
클래스는 설정되어 있지 않기 때문에 선택이 되지 않는다.[6] href 속성이 없어도 링크만 안 될 뿐이지 태그 자체는 정상적으로 작동한다(placeholder hyperlink라고 한다).[7] 즉, html 파일을 대상으로 하는 경우 기능적으로는 html을 선택자로 지정하는 것과 거의 동일하다. 그렇다고 완전히 동일한 것은 아니며, :root가 특이성이 더 높기 때문에 :root와 html에 같은 스타일 속성을 다르게 설정한다면 순서에 상관없이 :root의 스타일 값이 우선된다.[8] 특정한 문장 부호('-', '_', 따옴표, 괄호 등)로 시작할 경우 그 문장 부호부터 본문의 첫 번째 글자까지 선택된다. 예를 들어 '"foobar"'의 ::first-letter
는 '"f'의 두 글자이다.[9] 물론 대부분의 경우 Level 4와 비슷하게 동작하긴 했지만, 만약 정말 특이하게 클래스가 10개를 초과하는 선택자를 쓸 경우 아이디 선택자 1개의 우선순위를 뛰어넘게 되어 의도치 않은 결과를 낼 수 있기 때문에, 이러한 예외를 미연에 방지하기 위해 일관적인 방식으로 수정한 것으로 보인다.[10] 원래라면 나중에 서술되었음에도 먼저 서술된 문법을 덮어쓰지 못하는 현상.