CSS counter로 다단계 순번 만들기

HTML의 순서 있는 목록(ordered list)에는 자동으로 번호가 붙게 돼 있다. 그런데 이 번호라는 게 기본 상태에서는 1, 2, 3,…이고 CSS의 list-style-type을 사용하면 숫자대신 알파벳이나 로마자를 사용할 수는 있기는 하지만 해당 단계에 대해서만 표시하고 다단계는 되지 않는다. 오늘은 CSS counter로 다단계 순번 만들기를 알아보자.


우선 기본적인 HTML을 사용해 순서 있는 목록을 사용한 예시를 보자.

  1. 서론
  2. 연구 내용 및 방법
    1. 조사 대상 및 기간
    2. 조사 내용
      1. 조사 대상자의 특성
      2. 만족도 조사 결과

위 결과는 다음과 같이 비교적 간단히 만들 수 있다.

<style>
.part { list-style-type: upper-roman; }
.section { list-style-type: lower-alpha; }
</style>
 
<ol class="part">
    <li>서론</li>
    <li>연구 내용 및 방법
        <ol class="unit">
            <li>조사 대상 및 기간</li>
            <li>조사 내용
                <ol class="section">
                    <li>조사 대상자의 특성</li>
                    <li>만족도 조사 결과</li>
                </ol>
            </li>
        </ol>
    </li>
</ol>

그럼 다음과 같이 다단계 순번을 붙이려면 어떻게 할까? 예를 들어 책을 보면 단원, 절에 따라 I-1, I-2,… II-1, II-2, II-2-1, II-2-2,…와 같이 나타나는 경우가 있다. 아래 결과는 IE8 이상이면 잘 되는 스타일이다.

  1. 서론
  2. 연구 내용 및 방법
    1. 조사 대상 및 기간
    2. 조사 내용
      1. 조사 대상자의 특성
      2. 만족도 조사 결과

HTML은 앞서의 예시과 같고 CSS Style을 다음과 같이 하면 된다.

  1. ol {list-style-type: none; }
  2. .part {
  3.     counter-reset: part;
  4.     list-style-type: none;
  5. }
  6. .part > li:before {
  7.     counter-increment: part; 
  8.     content: counter(part,upper-roman) ". ";
  9. }
  10. .unit {
  11.     counter-reset: unit;
  12.     list-style-type: none;
  13. }
  14. .unit > li:before {
  15.     counter-increment: unit;
  16.     content: counter(part,upper-roman) "-" counter(unit,decimal) ". ";
  17. }
  18. .section {
  19.     counter-reset: section; 
  20.     list-style-type: none;
  21. }
  22. .section > li:before {
  23.     counter-increment: section;
  24.     content: counter(part,upper-roman) "-" counter(unit,decimal) "-" counter(section,lower-alpha) ". ";
  25. }

설명을 하자면 1행에서 일단 순번 자체를 없애고 있다. counter라는 별도의 순번 체계를 사용하기 위해서다. counterol, ul 뿐 아니라 임의의 HTML 요소에 대해 사용할 수 있다.

3행에서는 .part 클래스에 counter-increment를 사용해 순번을 붙일 변수를 설정하고 있다. 위에서 “part”, “unit”, “section”은 클래스명이 아니라 임의의 변수명이다. 그 결과 ol.part가 나타나면 “part”라는 변수를 새로 시작하게 된다.

7행에서는 .part > li에 대해 “part” 변수를 점증시키도록 하고 있다. 그런데 이제 중요한 것은 8행이다. content를 사용함으로써 li:before, 즉 li 내용의 앞에 순번을 삽입하게 된다.

8행의 counter(part,upper-roman) ". "은 “part” 변수의 순번 값을 대문자 로마자로 출력하고 그 뒤에 마침표와 빈칸을 붙이라는 의미다.

이제 나머지는 설명하지 않아도 이해할 것이다. 같은 스타일로 반복하고 있으며 3단계까지 출력하는 것이다.

그렇다면 3단계가 아니라 임의의 단계까지 다단계 번호를 붙이려면 어떻게 할까?

1단계만 로마자를 사용하고 그 하위 단계는 모두 숫자로만 표시하는 예제를 들어본다면 다음과 같다. counters라는 새로운 CSS 속성을 사용하는 것을 볼 수 있다.

ol.part {
    counter-reset: part;
    list-style-type: none;
}
ol.part > li:before {
    counter-increment: part;
    content: counter(part,upper-roman) ". ";
}
li > ol {
    counter-reset: section;
    list-style-type: none;
}
li > ol > li:before {
    counter-increment: section;
    content: counter(part,upper-roman) "-" counters(section,"-") ". ";
}

이 방식이 강력하긴 하지만 아직도 자유자재로 순번을 붙이기에는 한계가 있다. 예를 들어 순번 값을 한글이라든가 임의의 기호를 넣는 것은 아직 지원되지 않는 게 많다. 하지만 현재 WWW 표준으로 임의의 리스트 스타일을 CSS3로 지정하는 것을 제정하고 있는 과정이다. 자세한 사항은 여기(주의: 100% 영문!)를 참고해보기 바란다.

의견 있으시면 냉큼 작성해주세요~