CSS

CSS - 선택자 우선순위

제이널 2021. 12. 30. 16:14

 

CSS 선택자는 ID, Class, 태그 등 여러 종류가 있습니다.

실제 개발할 때, 상위 CSS 요소가 적용되어 있는 상태에서 새로운 CSS 요소를 적용하려 하면 적용이 적절히 안 되는 경우가 있는데, 이는 CSS의 적용 우선순위 때문입니다.

 

CSS에는 어떤 선택자가 있는지, 그리고 우선순위에 대한 점수가 어떻게 측정되는지 알아보려 합니다.

 

 

목차

1. !important

2. 인라인 스타일

3. ID 선택자

4. 클래스 선택자

5. 속성 선택자

6. 가상 선택자

7. 태그 선택자

8. 전체 선택자

9. 우선순위 비교

 

 

1. !important

!important는 선택자가 아니지만, CSS 속성에 이를 지정하면 가장 우선적으로 스타일을 적용합니다.

따라서, 어떤 선택자가 있든 !important 속성이 가장 우선시 됩니다.

!important가 여러 곳에서 사용되었다면, 가장 마지막에 선언된 !important 속성이 최종적으로 적용됩니다.

 

예를 들어, 아래의 코드에선 !important가 인라인 스타일보다 우선순위가 높기 때문에 div 요소의 배경은 빨간색으로 채워집니다.

 

div { width:100px; height:100px; background:red!important; }

<div style="background:blue;"></div>

 

!important 속성은 우선순위가 가장 높기 때문에, MDN에선 사이트 전반이나 플러그인을 만드는 등 전역적인 CSS에서는 절대 사용하지 말라고 권고하고 있습니다.

 

2. 인라인 스타일

태그 요소에 스타일을 직접 삽입하는 방법으로, !important를 제외한 선택자 요소들보다 우선순위가 가장 높습니다.

<div style="background:blue;"></div>

 

3. ID 선택자

태그에 id Attribute가 지정되어있는 요소를 선택하는 선택자입니다.

#apple { width:100px; height:100px; background:red; }

<div id='apple'></div>

 

4. 클래스 선택자

태그에 class Attribute가 지정되어있는 요소를 선택하는 선택자입니다.

.apple { width:100px; height:100px; backgorund:red; }

<div class='apple'></div>

 

5. 속성 선택자

태그에 Attribute가 지정되어 있는 요소를 선택하는 선택자입니다.

[apple] { background:red; }
[apple='sweet'] { background:blue; }

<div apple='sweet'></div>

 

6. 가상 선택자

가상 선택자는 웹문서에는 존재하지 않지만, 어떠한 상황이나 구조를 대상으로 요소를 선택하는 선택자입니다.

 

6-1. 가상 클래스 선택자

패턴 의미
E:link 방문하지 않은 링크 E를 선택합니다.
E:visited 방문한 링크 E를 선택합니다.
E:active E 요소에 마우스 클릭 또는 키보드 엔터가 눌린 동안 E를 선택합니다.
E:hover E 요소에 마우스가 올라가 있는 동안 E를 선택합니다.
E:focus E 요소에 포커스가 머물러 있는 동안 E를 선택합니다.

 

6-2. 구조적 가상 클래스 선택자

패턴 의미
E:root 문서의 최상위 요소(html)를 선택합니다.
E:nth-child(n) 앞에서부터 지정된 순서와 일치하는 요소가 E라면 선택합니다.
(E 아닌 요소의 순서가 계산에 포함)
E:nth-last-child(n) 뒤에서부터 지정된 순서와 일치하는 요소가 E라면 선택합니다.
(E 아닌 요소의 순서가 계산에 포함)
E:nth-of-type(n) E 요소 중 앞으로부터 순서가 일치하는 E 요소를 선택합니다.
(E 요소의 순서만 계산에 포함)
E:nth-last-of-type(n) E 요소 중 뒤에서부터 순서가 일치하는 E 요소를 선택합니다.
(E 요소의 순서만 계산에 포함)
E:first-child 첫 번째 등장하는 요소가 E 라면 선택합니다.
(E 아닌 요소의 순서가 계산에 포함)
E:last-child 마지막에 등장하는 요소가 E 라면 선택합니다.
(E 아닌 요소의 순서가 계산에 포함)
E:first-of-type E 요소 중 첫 번째 E를 선택합니다.
(E 요소의 순서만 계산에 포함)
E:last-of-type E 요소 중 마지막 E를 선택합니다.
(E 요소의 순서만 계산에 포함)
E:only-child E 요소가 유일한 자식이면 선택합니다.
(E 아닌 요소가 하나라도 포함되면 선택하지 않습니다.)
E:only-of-type E 요소가 유일한 타입이면 선택합니다.
(E 아닌 요소가 포함되어도, 그 중 E 타입이 유일하면 선택합니다.)
E:empty 텍스트 및 공백을 포함해 자식 요소가 없는 E를 선택합니다.

 

6-3. 언어 선택자

패턴 의미
E:lang(ko) HTML lang 속성의 값이 'ko'으로 지정된 요소를 선택합니다.

 

6-4. 부정 선택자

패턴 의미
E:not(S) S가 아닌 E 요소를 선택합니다.

 

6-5. 목적 선택자

패턴 의미
E:target E의 URI가 요청되면 선택합니다.
(E는 ID가 지정되어 있어야 합니다.)

 

6-6. UI 요소 상태 선택자

패턴 의미
E:enabled 사용 가능한 폼 컨트롤(input, textarea, select, button) E를 선택합니다.
E:disabled 사용 불가능한 폼 컨트롤(input, textarea, select, button) E를 선택합니다.
E:checked 선택된 폼 컨트롤(input, textarea, select, button) E를 선택합니다.

 

6-7. 가상 요소 선택자

패턴 의미
E:first-line E 요소의 첫 번째 라인을 선택합니다.
E:first-letter E 요소의 첫 번째 문자를 선택합니다.
E:before E 요소의 시작 지점에 생성된 요소를 선택합니다.
E:after E 요소의 끝 지점에 생성된 요소를 선택합니다.

 

7. 태그 선택자

간단히 태그를 지정해 선택하는 선택자입니다.

div { width:100px; height:100px; background:red; }

<div></div>

 

8. 전체 선택자

모든 요소를 선택하는 선택자입니다.

* { width:100px; height:100px; background:red; }

<div></div>

 

이렇게 선택자들의 종류와 특징을 간단히 알아보았습니다.

이제 선택자들이 가지는 우선순위를 비교하고, 그 정도를 어떻게 측정할 수 있는지 알아보겠습니다.

 

9. 우선순위 비교

각 선택자들의 점수는 아래와 같습니다.

선택자 사용 예 점수
!important div { color:red!important; }
인라인 스타일 <div style=""> 1,000 점
ID 선택자 #apple 100 점
속성 선택자 [apple='mac'] 10 점
클래스 선택자 .apple 10 점
가상 선택자 div:first-child / :hover / :not(div) ... 10 점
태그 선택자 div 1 점
전체 선택자 * 0 점

 

위 점수를 기반으로 선택자의 점수를 계산해서 우선순위를 가늠할 수 있습니다.

예를 들어, 아래와 같은 선택자들이 있다면, 다음과 같이 점수를 계산할 수 있을 것입니다.

 

li.apple { } /* li(1) + .apple(10) = 11 점 */
li.apple div:first-child { } /* li(1) + .apple(10) + div(1) + :first-child(10) = 22 점 */

 

이렇게 계산된 점수가 높은 선택자가 우선순위가 높다고 할 수 있습니다.

우선순위가 같다면, 가장 마지막에 선언된 선택자가 우선 적용됩니다.

결국, 좀 더 구체적으로, 또 높은 점수를 가진 선택자를 사용한 코드가 우선순위가 높다고 할 수 있을 것 같습니다.

 

하지만, 위와 같은 우선순위를 매번 계산하며 개발하기는 쉽지 않기 때문에, CSS 충돌을 피하기 위해선 다음과 같은 규칙이 권장됩니다.

  • Class만 사용하기: 요소가 한 번만 나타나는 경우에도 #apple 대신 .apple로 통일합니다.
  • <div class="apple banana">와 같이, 단일 HTML 요소에 여러 클래스 적용을 지양합니다.
  • <div style="">과 같은 인라인 스타일을 지양합니다.