TL;DR
- CSS에 아직 구현되지 않은
children-count()를 대신해sibling-count()와 스크롤 기반 애니메이션으로 자식 요소 수를 부모 요소에 전달하는 방법임. - 기본 구현은 컨테이너에 사용자 지정
<n>요소를 추가하고, 그 너비를 자식 수에 비례시킨 뒤 뷰 타임라인의 진행도를 이용해 값을 전달하는 방식임. - 대안 구현은 애니메이션 두 개로 요소의 양쪽 진행도를 계산하거나, 의사 요소에 뷰 타임라인을 설정해
position: relative와 컨테이너의 스크롤 설정을 피하는 방식임. - 전달된 값은
counter()로 표시하거나, 제곱근을 이용한 그리드 열 수와 같은 동적 레이아웃 계산에 활용할 수 있음. - 이 기법은 최신 CSS 기능을 살펴보는 개념 증명이며, 실제 프로젝트에서는
childElementCount를 사용하는 자바스크립트가 권장됨.
부모 요소로 `sibling-count()` 전달하기
sibling-count()는 형제 요소 수를 세므로 컨테이너의 자식 수를 직접 얻지 못함.:has()를 이용한 수량 쿼리 선택자는 만들 수 있지만, 자식 수를 값으로 가져오지는 못함.children-count()제안은 아직 논의 중이며 구현까지는 시간이 필요한 상태임.sibling-count()로 필요한 정보는 얻을 수 있지만 부모 요소가 그 값에 접근할 수 없으므로, 스크롤 기반 애니메이션(Scroll-Driven Animations)을 이용해 자식에서 부모 방향으로 값을 전달하는 방법을 제시함.- 상속은 요소에서 자손으로 값을 전달하는 네이티브 메커니즘이지만, 이 기법은 반대 방향의 전달을 CSS 핵으로 구현함. 글 작성 시점에 필요한 기능을 완전히 지원하는 브라우저는 Chrome과 Edge뿐임.
이전 사례
- 스크롤 기반 애니메이션을 이용해 순수 CSS로 요소의 너비와 높이를 얻고, 그 값을 페이지 어디서든 사용할 수 있음.
- 범위 슬라이더의 현재 값을 가져와 툴팁에 표시하고, 자바스크립트 없이 범위 슬라이더로 CSS 변수를 갱신하는 기법과
<progress>요소를 활용한 사례가 있음. - 그리드의 행 수, 열 수, 아이템 위치 같은 정보를 추출하는 기법도 다룬 바 있음.
- Roman Komarov는 요소의 크기 맞춤(shrinkwrap) 문제를 해결하고 요소 간 상태를 전달하는 방법을 비롯해 스크롤 기반 애니메이션을 활용하는 여러 기법을 소개함.
- 이러한 기법은 값을 계산한 뒤 다른 위치로 전달한다는 공통 원리를 따름. 너비, 높이, 위치, 거리 같은 값을 얻고 페이지의 다른 요소로 전달하는 것이 핵심임.
구현
- 컨테이너 안에 셀 요소와 별도의
<n>요소를 둠.<n>은 임의의 요소로 대체할 수 있으며, 실수로 스타일이 적용되지 않도록div나span대신 사용함. - 추가 요소는 HTML 구조를 변경하는 단점이 있고 자식 수에도 포함됨. 따라서 너비 계산에서 1을 빼 보정함.
<n>의 너비를calc((sibling-count() - 1) * 1px)로 설정해 자식 수에 비례하는 너비를 만듦. 이 너비를 전달할 값으로 취급함.- 기본 구현에서는 컨테이너에
position: relative,overflow: auto를 설정하고,<n>을left: 0에 배치함. 스크롤 기반 애니메이션은 참조할 스크롤 컨테이너가 필요하며, 실제로 스크롤할 내용이 없어도 스크롤 컨테이너를 지정해야 함. <n>에view-timeline: --n x를 설정해 가로 방향 뷰 진행 타임라인을 만듦. 컨테이너는timeline-scope,animation-timeline,animation-range로 그 타임라인에 연결하고, 사용자 지정 속성--n을 애니메이션함.<n>의 오른쪽 경계 위치는 너비에 따라 달라짐. 자식이 0개이면 너비가 0이므로 오른쪽 경계가 컨테이너 시작점과 일치하고,exit 100%가 0개 자식에 해당함.- 자식이 1,000개이면 너비가 1,000픽셀이므로 오른쪽 경계가 시작점에서 1,000픽셀 떨어짐. 따라서
exit calc(100% - 1000px)는 자식이 1,000개인 위치에 해당함. exit calc(100% - Npx)를 자식 수 N에 해당하는 위치로 삼고, 선형 애니메이션의 두 지점에--n: 1000과--n: 0을 설정해 범위 전체를 매핑함.exit calc(100% - 0px)는exit 100%와 같으며 끝 값을 생략하면 기본값이 100%임.- 1,000은 임의의 최댓값이므로 자식이 1,000개를 넘는 경우 더 큰 값으로 조정해야 함.
추가 구현
- 기본 구현은 추가 요소뿐 아니라 컨테이너의
position: relative와overflow: auto도 요구하며, 이 두 속성은 기존 레이아웃에 영향을 줄 수 있음. - 대안 구현은 애니메이션 두 개로 왼쪽과 오른쪽의 진행도를 각각 추적한 다음 차이를 계산해 요소의 너비를 구함. 컨테이너를 스크롤 가능하게 만들 필요가 없고 추가 요소를 페이지 어디에나 둘 수 있음.
- 또 다른 구현은 애니메이션 하나와 추가 요소의 의사 요소를 활용해 너비를 추출함. 컨테이너에
position: relative나overflow: auto를 설정할 필요가 없는 방식임. - 여러 구현은 같은 결과를 서로 다른 방식으로 표현함. 준비된 코드를 사용하는 것뿐 아니라 각 구현의 원리를 이해하는 것이 중요함.
활용 사례
- 의사 요소의
content에서counter()를 사용하고counter-reset에 전달된--n값을 설정하면 자식 수를 표시할 수 있음. - 콘텐츠가 처음에 숨겨지는 경우에도 아이템 수를 시각적으로 알릴 수 있음. 예를 들어
<details>안의 컨테이너에서 아이템 수를 계산해details요소로 전달하고,summary가 상속한 값을 의사 요소에 표시할 수 있음. - 자식 수를 바탕으로 동적 레이아웃, 특히 그리드 레이아웃을 만들 수 있음.
sqrt(var(--n))를 올림해 열 수를 정하면 행과 열 수가 균형을 이루는 정사각형에 가까운 배치가 가능함. - 자식이 15개이면 제곱근은 약 3.87이며 정수로 올림하면 열이 4개가 됨. 모든 아이템을 배치하려면 행도 4개가 필요함.
- 자식 수는 흐름에서 벗어난 콘텐츠(out-of-flow content)를 처리할 때도 활용할 수 있음. 요소를
translate로 배치해 진입 효과를 만들 때 넘치는 콘텐츠가 생기는 문제를 부모 높이 조정으로 해결할 수 있음. - 원형 레이아웃도 추가 활용 사례로 제시됨. 더 많은 활용 사례는
children-count()제안에서 공유해 해당 기능의 채택을 요청할 수 있음.
결론
- 실제 프로젝트에서는
.container요소의childElementCount를 가져오는 한 줄의 자바스크립트 사용을 권장함. - CSS만으로 구현한 방법은 최신 기능을 실험하는 연습이자
children-count()가 구현 가능하다는 점을 보여주는 개념 증명임. 공식 기능이 제공되기를 기대하는 사례임.
댓글 (0)
로그인하면 이 기사에 내 생각을 남길 수 있어요