본문 바로가기
FrontEnd

CSS Counter를 활용한 컨텐츠 넘버링 처리

by E_van 2025. 4. 3.

목록이나 리스트를 다룰 때, 자동으로 넘버링을 처리할 수 있다면 얼마나 깔끔할까요? 이런 코드를 만들 때 순수 CSS만으로 이런 처리를 하기가 쉽지 않다고 느낄 수 있습니다. 하지만 CSS Counter를 이용하면 간단하게 해결할 수 있습니다.

이번 글에서는 CSS Counter를 활용해서 콘텐츠 자동 넘버링을 구현하는 방법을 소개합니다.


결과 미리 보기

아래는 우리가 만들게 될 결과 화면입니다.

두 가지 버전이 보이죠?

  1. 일반적인 넘버링 리스트
  2. 넘버링과 라벨을 함께 사용하는 리스트


핵심 기술: CSS Counter

CSS Counter는 HTML 요소에 숫자를 자동으로 부여할 수 있는 기능입니다. counter-reset, counter-increment, content 속성을 조합해서 리스트 스타일을 제어합니다.


예제 코드

공통 래퍼 스타일

const ListWrap = styled.ul`
  display: block;
  text-align: left;

  & > :first-child {
    counter-reset: number;
  }
`;

여기서는 ul 요소 안에서 첫 번째 자식 요소에 counter-reset: number를 설정해 넘버링을 초기화합니다.

 

기본 넘버링 처리 리스트

const ListItem = styled.li`
  display: block;
  list-style: unset;

  &:before {
    counter-increment: number;
    content: counter(number) '. ';
  }
`;

각 li 요소 앞에 자동으로 숫자가 붙습니다. 브라우저의 기본 list-style은 제거하고, before 가상 요소로 dom 요소에 넘버링을 삽입합니다.

컴포넌트로 사용하면 이렇게 됩니다:

export const SortableNumber = () => {
  return (
    <ListWrap>
      <ListItem>Content Item</ListItem>
      <ListItem>Content Item</ListItem>
      <ListItem>Content Item</ListItem>
    </ListWrap>
  );
};
 

넘버링 + 라벨 처리 리스트

const ListItemWithLabel = styled.li`
  display: block;
  list-style: unset;

  &:before {
    counter-increment: number;
    content: counter(number) '. ' attr(data-label);
  }
`;

이번엔 data-label 속성에 저장된 값을 함께 출력합니다. 넘버링 외에 텍스트 커스터마이징이 필요할 때 유용합니다.

export const SortableLabel = () => {
  return (
    <ListWrap>
      <ListItemWithLabel data-label="First Content Item" />
      <ListItemWithLabel data-label="Second Content Item" />
      <ListItemWithLabel data-label="Third Content Item" />
    </ListWrap>
  );
};

마무리

이처럼 CSS Counter를 활용하면 JavaScript 없이도 유연하고 확장성 있는 넘버링 UI를 만들 수 있습니다.

리스트가 많거나 동적으로 생성되는 구조라면, 이런 방식으로 넘버링을 처리해보는 걸 추천합니다!