이 문서는 CSS 코드를 최적화하는 방법을 제공한다. 특히, 선택자를 효율적으로 작성하는 방법에 대해 집중적으로 다룰 것이다.
CSS 명세는 브라우저가 어떻게 스타일 시스템을 구현하는지에 대해 정해두지 않았다. 이 때문에 브라우저마다 스타일 시스템 엔진이 다르다. 널리 사용되는 오픈소스 엔진인 Gecko와 Webkit은 비슷한 알고리즘으로 스타일 시스템을 구현하고 있으므로 장점과 단점이 비슷하다. 따라서 이 문서에 있는 팁은 실제 웹 문서에서 유용할 것이다.
첫번째 섹션에서는 일반적인 엔진이 CSS 규칙을 분류하는 것에 대해 논의한다. 이 다음 섹션에서는 이런 엔진의 특성으로부터 효율적인 스타일 규칙을 만드는 방법에 대해 이야기할 것이다.
스타일 엔진은 어떻게 스타일 규칙을 분류하는가
스타일 엔진은 다음 4개의 카테고리로 스타일 규칙을 분류한다.
- ID 규칙
- Class 규칙
- Tag 규칙
- Universal 규칙
이 4개의 규칙들은 스타일 규칙을 적용하는데 기본적인 역할을 하므로 이해하는것이 중요하다.
다음 문단부터 키 선택자라는 용어를 사용하겠다. 키 선택자란 선택자의 마지막 선택자를 의미한다(선택되는 엘리먼트을 가리키는).
예를들어, 다음과 같은 규칙에서
a img, div > p, h1 + [title] {…}
키 선택자는 img
, p 그리고
title이다.
ID 규칙
첫번째 카테고리는 ID 선택자를 키 셀렉터로 가지는 규칙들로 이루어진다.
예제
button#backButton {…} /* 이건 ID 규칙이다. */ #urlBar[type="autocomplete"] {…} /* 이것도 ID 규칙이다. */ treeitem > treerow > treecell#myCell:active {…} /* 이것도 ID 규칙이다. */
Class 규칙
어떤 규칙의 키 선택자에 class가 명시되어 있으면 이건 Class 규칙에 속한다.
예제
button.toolbarButton {…} /* Class 규칙 */ .fancyText {…} /* Class 규칙 */ menuitem > .menu-left[checked="true"] {…} /* Class 규칙 */
Tag 규칙
어떤 규칙의 키 선택자에 class와 ID가 명시되지 않고 tag가 있다면 이 규칙은 Tag 규칙에 속한다.
예제
td {…} /* Tag 규칙 */ treeitem > treerow {…} /* Tag 규칙 */ input[type="checkbox"] {…} /* Tag 규칙 */
Universal 규칙
위 세개의 규칙에 속하지 않는 모든 규칙은 여기에 속한다.
예제
[hidden="true"] {…} /* universal 규칙 */ * {…} /* universal 규칙 */ tree > [collapsed="true"] {…} /* universal 규칙 */
스타일 엔진은 어떻게 특정 엘리먼트에 규칙을 적용하는가
스타일 엔진은 키 셀렉터로부터 시작하여 왼쪽으로 이동하면서 엘리먼트가 규칙에 적합한지 확인한다. 만약 엘리먼트가 이 규칙에 적합하거나 적합하지 않다는게 확인되면 멈춘다.
가장 기본적인 개념은 규칙 필터링이다. 위에서 소개한 4개의 규칙 카테고리는 관계없는 규칙을 제거하기 위함이다(따라서 스타일 엔진은 엘리먼트와 관계없는 규칙을 매칭하는데 시간을 낭비하지 않을 수 있다).
성능을 비약적으로 향상시키는 방법은 바로 이것이다. 주어진 엘리먼트가 적합한지 확인하는데 고려해야할 규칙의 수가 적을수록 성능이 좋아진다.
예를 들어, 어떤 엘리먼트가 ID를 가지고 있다고 하자. 스타일 엔진은 이 엘리먼트의 ID와 같은 ID를 가지는 ID 규칙만을 적용할지 말지 확인할 것이다. 스타일 엔진은 이 엘리먼트의 class에 해당하는 Class 규칙만을 적용할지 말지 확인할 것이다. Tag 규칙도 이 엘리먼트의 태그에 해당하는 규칙만이 확인될 것이다. Universal 규칙은 모두 확인될 것이다.
효율적인 CSS를 작성하기 위한 지침
universal 규칙을 피하라
선택자가 universal 규칙에 속하지 않는지 확인하라.
ID 규칙에 쓸모없는 태그나 클래스를 붙이지 말라.
만약 어떤 규칙이 키 선택자로 ID 선택자를 가지면 여기에 부차적인 태그를 붙이지 말라. ID는 고유하므로 여기에 태그를 붙이는 것은 매칭 작업을 더디게 만든다.
- 나쁨
-
button#backButton {…}
- 나쁨
-
.menu-left#newMenuIcon {…}
- 좋음
-
#backButton {…}
- 좋음
-
#newMenuIcon {…}
Class 규칙에 쓸모없는 태그를 붙이지 말라
이전 내용이 여기에도 적용된다. class는 한 문서에서 여러번 사용되지만 태그보다 그 수가 적다.
하나의 관례는 class 이름에 적용할 태그 이름을 포함시키는 것이다. 그러나 이러면 유연성을 잃게 된다. 예를 들어, 디자인이 바뀌어 태그 이름이 달라지는 경우 class 이름을 모두 변경해야 한다. (의미가 있는 이름을 사용하는 것이 최선이다. 이것은 분리된 스타일시트를 사용하는 이유이기도 하다.)
- 나쁨
-
treecell.indented {…}
- 좋음
-
.treecell-indented {…}
- 최선
-
.hierarchy-deep {…}
가장 명확한 규칙을 적용하라
성능이 저하되는 가장 큰 이유는 Tag 규칙에 속하는 규칙이 너무 많이 때문이다. 엘리먼트에 클래스를 추가함으로써 Tag 규칙에 속하는 규칙을 Class 규칙에 속하는 규칙으로 바꿀 수 있다. 이는 같은 태그를 가진 다른 규칙을 매칭하는데 낭비되는 시간을 줄여준다.
- 나쁨
-
treeitem[mailfolder="true"] > treerow > treecell {…}
- 좋음
-
.treecell-mailfolder {…}
자손 선택자를 피하라
자손 선택자는 CSS에서 가장 속도가 느린 선택자이다. 이것은 끔찍하게 느리다. 특히 Tag 규칙이나 Universal 규칙에 속할 경우에는 말할 필요조차 없다.
흔히 자식 선택자로 대체할 수 있다. 예를 들어 자손 선택자는 속도가 너무 느려 파이어폭스 사용자 인터페이스 CSS에서 제거되었다. 당신의 웹 페이지를 이같이 변경하려는건 좋은 생각이다.
- 나쁨
-
treehead treerow treecell {…}
- 개선되었지만 여전히 나쁨 (다음 지침을 보라)
-
treehead > treerow > treecell {…}
Tag 규칙은 자식 선택자를 절대로 포함하지 말라
Tag 규칙에 속하는 규칙에 자식 선택자를 함께 사용하지 말라. 이것은 매칭하는데 소요되는 시간을 그 엘리먼트가 등장하는 만큼 비약적으로 증가시킨다(특히 그 규칙이 매칭될 것 같이 보일 때)
- 나쁨
-
treehead > treerow > treecell {…}
- 좋음
-
.treecell-header {…}
자식 선택자를 사용할 때에 항상 주의하라
자식 선택자를 사용할 때에 항상 주의하라. 가능하다면, 피하라.
특히 RDF 문서와 메뉴에서 자식 선택자는 자주 사용된다.
- 나쁨
-
treeitem[
IsImapServer="true"
] > treerow > .tree-folderpane-icon {…}
REF 속성은 템플릿에서 중복되게 할 수 있다는 것을 기억하라! 이것의 이점을 살려라. RDF 속성을 자식 XUL에 대해 중복되게하고 선택자를 간소화하라.
- GOOD
-
.tree-folderpane-icon[IsImapServer="true"] {…}
상속을 사용하라
어떤 속성들이 상속되는지 배우고 사용하라.
예를들어, XUL 위젯은 부모의 list-style-image나 font 규칙을 자식 엘리먼트에 대해 적용한다. 자식 엘리먼트들에 대해 이 규칙을 적용하는건 시간낭비다.
- 나쁨
-
#bookmarkMenuItem > .menu-left { list-style-image: url(blah) }
- 좋음
-
#bookmarkMenuItem { list-style-image: url(blah) }
위의 예처럼 상속되는 속성을 알고 있다면 class 규칙이 id 규칙으로 변환될 수 있다.
위의 "나쁜 규칙"은 모든 .menu-left가 #bookmarkMenuItem에 속하는지 확인하게 한다. 만약 여러개의 메뉴가 있다면 이는 매우 느리다. 반면 "좋은 규칙"은 엘리먼트가 #bookmarkMenuItem인지 아닌지만 확인한다.
-moz-image-region을 사용하라!
여러개의 이미지를 하나의 이미지에 담고 그것을
로 선택하는 것이 각 이미지를 각각의 파일에 넣는 것보다 훨씬 빠르다. -moz-image-region
Use scoped stylesheets
If you specify a stylesheet as an XBL resource, the styles only apply to the bound elements and their anonymous content. This reduces the inefficiency of universal rules and child selectors because there are fewer elements to consider.
Original Document Information
- Author: David Hyatt
- Original Document Date: 2000-04-21
- Original Document URL: https://www.mozilla.org/xpfe/goodcss.html