GODRICH
#css애니메이션#버튼#로딩#전환효과#스크롤#대시보드#실전ui#디자인트렌드

css 리스트 디자인 9종 — 마커가 계산으로 움직이는 목록 꾸미기

아홉 가지 리스트 마커 중 하나는 다이얼 각도 값이 항목마다 쌓이며 불릿이 시계처럼 돌고, 하나는 카운터 값이 자릿수별로 분해되어 숫자가 주행계처럼 굴러가고, 하나는 소수 판정 값에 따라 그 번호의 마커만 글로우가 맥박칩니다.

트리거는 아홉 항목이 모두 click 리스너 하나씩입니다 — 버튼의 역할만 제각각이라 01 은 다음 단계를 진행하고, 02 는 1위 값을 올리며, 03 은 배속을 바꾸고, 04 는 행진을 멈췄다 켜고, 05 는 시작 번호를 옮기고, 06 은 집계를 순환하고, 07 은 깊이를 공개하고, 09 는 전체를 제출하며, 08 만 목록 각 행의 마커 버튼이 상태를 넘깁니다. 자동 시연은 is-demo 클래스가 남아 있고 prefers-reduced-motion 이 거짓일 때만 돌다가 첫 클릭에 풀리는데, 04 는 reduce 검사를 자동 시연 조건 밖에 둬서 사람이 조작하기 시작한 뒤에도 설정을 계속 지킵니다. 마커는 아홉 셋 모두 ::marker 가 하지 못하는 일을 하므로 list-style: none 으로 네이티브 마커를 지우고 같은 자리에 다시 세운 것으로, 01·02·05 는 <ol>, 나머지 여섯은 <ul> 위에서 돕니다.

자동 재생 · 눌러서 해당 항목으로 · 전부 한 zip

아홉 개의 해부 — 어떤 계산이 마커를 움직이는가

항목별로 화면을 얼마나 채웠는지(누적면적), 프레임 사이 픽셀 차가 얼마나 셌는지(강도), 24장 캡처 중 몇 장에서 움직였는지(움직인프레임)를 재면 다음 표와 같습니다.

항목 누적면적% 강도_평균 움직인프레임
01 2.81% 70.2 17/23
02 0.19% 115.5 19/23
03 0.93% 142.2 23/23
04 0.42% 124.9 23/23
05 2.42% 27.8 20/23
06 1.28% 98.1 15/23
07 0.93% 47.0 10/23
08 1.21% 109.4 11/23
09 0.37% 91.0 10/23

누적면적 1위는 01(2.81%)입니다 — 클릭마다 번호에 비례해 여러 바늘이 한꺼번에 돌아 활동 하이라이트까지 겹치니 픽셀이 바뀌는 폭이 가장 넓습니다. 꼴찌는 02(0.19%)로 굴러가는 숫자가 좁은 칸 안만 바꾸기 때문이고, 07 은 표에서 03 과 같은 0.93% 로 보이지만 측정 소수로는 03(0.931)이 근소하게 큽니다. 강도가 140 을 넘는 항목은 03(142.2) 하나뿐이고 최저인 05(27.8)는 글로우가 알파로 번지는 저대비 변화라 프레임 차가 작습니다. 움직인 프레임은 03·04 가 23/23 로 가장 많고 07·09 가 10/23 로 가장 적으며, 이는 흠이 아니라 단계 사이 머무는 정지 구간의 길이가 다를 뿐입니다.

계산 축으로 나누면 네 부류가 나옵니다.

누적 값으로 마커를 미는 01·02·09

01 은 클릭 한 번이 turns[i] 에 쌓여 바늘 각도가 번호를 곱해 커지고, 02 는 카운터 값을 10 의 거듭제곱으로 나눠 자릿수마다 분해하며, 09 는 터지는 시각을 i * DELAY_STEP_MS 로 누적합니다. 셋 모두 지금의 입력이 아니라 지나온 횟수·순서가 마커에 새겨지는 축입니다.

흐르는 시간을 넣는 03·04

03 은 sin(t * speed + i * PHASE_RAD) 로 공통 시간에 항목 번호만큼 위상을 밀어 같은 순간에 서로 다른 높이를 만들고, 04 는 acc += dt/1000 * MARCH_RATE_DEG_S 로 오프셋을 경과 시간에 정속 적분합니다. 이전 상태 없이 그 프레임의 시간이 값을 정한다는 점이 같습니다.

판정식이 켜고 끄는 05·07

05 는 번호마다 isPrime() 나눗셈을 다시 돌려 통과한 항목에만 is-prime 클래스를 붙이고, 07 은 revealed >= depth 비교식 하나로 전 레일의 is-open 을 즉시 갱신합니다. 정해둔 목록이 아니라 값이 바뀔 때마다 판정이 다시 돈다는 점이 이 축의 성질입니다.

비례식이 크기를 재는 06·08

06 은 factor = sqrt(v)/sqrt(max) 제곱근 비례로 면적이 값에 비례하게 반지름을 잡고, 08 은 max(1.5, BASE_AREA/size²·3) 면적 보존 식으로 커진 마커일수록 선을 얇게 역산합니다. 값의 크기가 마커의 크기·무게로 환산되는 축입니다.

패턴별 코드

01다이얼 회전 마커 — 항목 번호에 각도 값을 쌓아 불릿이 시계처럼 도는 방식

클릭 한 번이 항목이 지나온 횟수(turns[i])에 쌓이고, 바늘 각도는 여기에 항목 번호(i+1)와 DIAL_STEP_DEG(30)를 곱해 번호가 클수록 같은 클릭에 더 크게 돕니다. 자동으로도 STEP_MS(480)마다 한 칸씩 전진합니다.

  // 계산 겹: 항목 i 의 바늘 각도는 그 항목이 지금까지 지나온 횟수(turns[i]) 에 자기 번호(i+1) 를 곱해 쌓인다.
  // 뒤 항목일수록 같은 한 번의 전진에도 더 큰 각도를 받는다 — 단순 지연이 아니라 번호에 비례한 누적이다.
  var turns = items.map(function () { return 0; });

  function render() {
    items.forEach(function (el, i) {
      var deg = turns[i] * DIAL_STEP_DEG * (i + 1);
      el.style.setProperty('--angle', (deg % 360) + 'deg');
    });
  }
다이얼 회전 마커 — 항목 번호에 각도 값을 쌓아 불릿이 시계처럼 도는 방식
새 창에서 열기

01 · 다이얼 회전 마커 — 항목 번호에 각도 값을 쌓아 불릿이 시계처럼 도는 방식 — 측정 누적면적 2.805% · 움직인 프레임 17/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

DIAL_STEP_DEGrotate$subject-blue

02주행계 카운터 — 카운터 값을 자릿수로 분해해 숫자 마커가 굴러가는 방식

카운터 값을 place = 10^(ODO_DIGITS-1-d) 로 나눠 자릿수마다 분해하고, 0부터 9까지 스트립을 translateY(-digit * DIGIT_H) 로 끌어올립니다. 자리마다 전환 속도를 260 + d * 220 ms 로 달리해 왼쪽 높은 자리가 260ms 로 먼저 멈추고 오른쪽 낮은 자리가 260 + 220ms 로 뒤늦게 따라옵니다.

  // 계산 겹: 카운터 값을 10 의 거듭제곱으로 나눠 자릿수로 분해한다. 각 자릿수 칸은 서로 다른 전환 속도를 가져
  // 낮은 자리부터 먼저 자리를 잡고(빠름) 높은 자리가 뒤따른다(느림) — 단순 opacity 페이드가 아니라 자릿수별 롤링.
  function setDigits(odo, value) {
    var strips = odo.querySelectorAll('.odo-strip');
    for (var d = 0; d < ODO_DIGITS; d++) {
      var place = Math.pow(10, ODO_DIGITS - 1 - d);
      var digit = Math.floor(value / place) % 10;
      strips[d].style.transform = 'translateY(' + (-digit * DIGIT_H) + 'px)';
    }
  }

  function speedClass(odo) {
    var strips = odo.querySelectorAll('.odo-strip');
    strips.forEach(function (s, d) {
      // d=0(가장 왼쪽=가장 높은 자리)이 가장 느리고, 오른쪽(낮은 자리)일수록 빠르다
      var ms = 260 + d * 220;
      s.style.transitionDuration = ms + 'ms';
    });
  }
  odos.forEach(speedClass);
주행계 카운터 — 카운터 값을 자릿수로 분해해 숫자 마커가 굴러가는 방식
새 창에서 열기

02 · 주행계 카운터 — 카운터 값을 자릿수로 분해해 숫자 마커가 굴러가는 방식 — 측정 누적면적 0.189% · 움직인 프레임 19/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

ODO_DIGITStranslateY$subject-blue-light

03위상 물결 마커 — 항목마다 위상 값을 밀어 불릿이 물결치는 방식

불릿의 세로 위치를 진폭 AMPLITUDE_PX(6)의 사인값으로 정하고, 위상을 항목 번호만큼(i * PHASE_RAD) 밀어 넣어 목록 전체가 한 줄의 물결로 흐릅니다. SPEEDS [1, 2, 0.5] 프리셋을 클릭으로 순환합니다.

  // 계산 겹: 각 불릿의 세로 위치는 사인 함수에 항목 번호만큼 위상을 밀어 넣은 값이다.
  // t(공통 시간) 는 흐르되 위상이 다르면 같은 순간에도 서로 다른 높이가 된다 — 이것이 "물결"의 원리다.
  function apply(t) {
    var speed = SPEEDS[speedIdx];
    items.forEach(function (el, i) {
      var phase = i * PHASE_RAD;
      var y = AMPLITUDE_PX * Math.sin(t * speed + phase);
      el.style.setProperty('--y', y.toFixed(2) + 'px');
    });
  }
위상 물결 마커 — 항목마다 위상 값을 밀어 불릿이 물결치는 방식
새 창에서 열기

03 · 위상 물결 마커 — 항목마다 위상 값을 밀어 불릿이 물결치는 방식 — 측정 누적면적 0.931% · 움직인 프레임 23/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

Math.sintranslateY$subject-blue-deep

04진행 대시 마커 — 오프셋 값을 흘려 대시가 행진하는 방식

오프셋 각도를 매 프레임 acc += dt/1000 * MARCH_RATE_DEG_S(140) 로 경과 시간에 정속 적분해 점선 테두리가 원을 따라 흐릅니다. 멈췄다 다시 켜도 값이 이어져 흐름이 끊기지 않습니다.

  var last = 0;
  var acc = 0;
  function loop(ts) {
    if (!last) last = ts;
    var dt = ts - last;
    last = ts;
    if (reduce) {
      apply(90); // 계산은 유지, 시간 축소 대신 4분의1 회전 지점으로 즉시 고정 (자동 루프·실사용 공통)
    } else if (running) {
      acc += dt / 1000 * MARCH_RATE_DEG_S;
      apply(acc);
    }
    requestAnimationFrame(loop);
  }
진행 대시 마커 — 오프셋 값을 흘려 대시가 행진하는 방식
새 창에서 열기

04 · 진행 대시 마커 — 오프셋 값을 흘려 대시가 행진하는 방식 — 측정 누적면적 0.421% · 움직인 프레임 23/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

MARCH_RATE_DEG_Sdashed$subject-blue-light

05소수 글로우 마커 — 소수 판정 값을 계산해 해당 번호만 빛나는 방식

항목 번호마다 isPrime() 나눗셈을 직접 돌려 통과한 번호에만 글로우가 맥박칩니다. 시작 번호가 옮겨가면 판정이 매번 다시 돌고, 번호는 list-style: none 으로 지운 뒤 counter(item) 값으로 ::before 에 다시 그립니다.

  // 계산 겹: 각 항목 번호에 소수 판정을 직접 계산한다 — 미리 정해둔 목록이 아니라 실행마다 다시 돈다.
  function isPrime(n) {
    if (n < 2) return false;
    for (var d = 2; d * d <= n; d++) {
      if (n % d === 0) return false;
    }
    return true;
  }

  function recompute() {
    list.setAttribute('start', String(start));
    items.forEach(function (li, i) {
      var n = start + i;
      li.classList.toggle('is-prime', isPrime(n));
    });
  }
소수 글로우 마커 — 소수 판정 값을 계산해 해당 번호만 빛나는 방식
새 창에서 열기

05 · 소수 글로우 마커 — 소수 판정 값을 계산해 해당 번호만 빛나는 방식 — 측정 누적면적 2.419% · 움직인 프레임 20/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

counterbox-shadow$subject-blue-deep

06크기 순위 마커 — 값에 비례해 마커 면적을 계산하는 방식

마커 반지름을 factor = sqrt(v)/sqrt(max) 제곱근 비례로 잡아 면적이 값에 비례하게 합니다 — 선형 비례는 큰 값이 과장돼 보입니다. 집계 값은 결정적 프리셋 세트를 STEP_MS(550)마다 순환해 Math.random 없이 재현됩니다.

  // 계산 겹: 마커 반경은 값의 제곱근에 비례한다(면적이 값에 비례하도록) — 선형 비례는 큰 값이 과장돼 보인다.
  function apply(set) {
    var max = Math.max.apply(null, Object.keys(set).map(function (k) { return set[k]; }));
    items.forEach(function (li, i) {
      var key = li.getAttribute('data-key');
      var v = set[key];
      var factor = Math.sqrt(v) / Math.sqrt(max);
      markers[i].style.setProperty('--scale', factor.toFixed(3));
    });
  }
크기 순위 마커 — 값에 비례해 마커 면적을 계산하는 방식
새 창에서 열기

06 · 크기 순위 마커 — 값에 비례해 마커 면적을 계산하는 방식 — 측정 누적면적 1.283% · 움직인 프레임 15/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

Math.sqrtscale$subject-blue

07계층 레일 마커 — 깊이 값으로 인덴트 레일을 계산하는 방식

중첩 ul 마다 data-depth 를 두고 revealed >= depth 비교식 하나로 전 레일의 표시 여부를 즉시 갱신합니다 — 레일마다 별도 타이머가 아닙니다. 레일 선은 ::before 를 scaleY(0)에서 scaleY(1)로 뻗습니다.

  // 계산 겹: 레일 각각의 표시 여부는 "지금 공개된 깊이 ≥ 이 레일의 깊이" 라는 비교식의 결과다.
  // 값 하나(revealed)가 바뀌면 그보다 얕은 레일은 전부 즉시 갱신된다 — 레일마다 별도 타이머가 아니다.
  function apply() {
    tree.style.setProperty('--revealed', String(revealed));
    rails.forEach(function (rail) {
      var d = parseInt(rail.getAttribute('data-depth'), 10);
      rail.classList.toggle('is-open', revealed >= d);
    });
    button.setAttribute('aria-expanded', String(revealed >= MAX_DEPTH));
  }
계층 레일 마커 — 깊이 값으로 인덴트 레일을 계산하는 방식
새 창에서 열기

07 · 계층 레일 마커 — 깊이 값으로 인덴트 레일을 계산하는 방식 — 측정 누적면적 0.93% · 움직인 프레임 10/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

scaleYrevealed$subject-blue-light

08하이브리드 교체 마커 — 상태 값에 따라 마커 종류가 바뀌는 방식

상태(대기 중·진행 중·완료)마다 지름 SIZE_BY_STATE [14, 20, 24] 로 마커가 점에서 다이아·체크로 모프합니다. 두께는 max(1.5, BASE_AREA/size²·3) 면적 보존 식으로 역산돼 커질수록 선이 얇아져 무게가 맞물립니다.

  // 계산 겹: 두께는 "면적 보존" 식(BASE_AREA / size)으로 역산한다 — 커지는 마커일수록 선이 얇아져
  // 시각적 무게가 서로 비슷하게 맞물린다. 임의의 고정 두께 3종을 나열한 것이 아니다.
  function thicknessFor(size) {
    return Math.max(1.5, BASE_AREA / (size * size) * 3);
  }

  function apply(li) {
    var state = parseInt(li.getAttribute('data-state'), 10);
    var btn = li.querySelector('.marker');
    var size = SIZE_BY_STATE[state];
    var thick = thicknessFor(size);
    btn.style.setProperty('--size', size + 'px');
    btn.style.setProperty('--thick', thick.toFixed(2) + 'px');
    btn.className = 'marker state-' + state;
    btn.setAttribute('aria-label', '상태 전환: ' + STATES[state]);
    btn.textContent = STATES[state];
  }
하이브리드 교체 마커 — 상태 값에 따라 마커 종류가 바뀌는 방식
새 창에서 열기

08 · 하이브리드 교체 마커 — 상태 값에 따라 마커 종류가 바뀌는 방식 — 측정 누적면적 1.21% · 움직인 프레임 11/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

BASE_AREAthicknessFor$subject-mint

09연쇄 체크 마커 — 지연 값을 누적해 체크가 연쇄 터지는 방식

항목 i 가 터지는 시각을 i * DELAY_STEP_MS(110) 누적으로 정해 CSS 변수 --delay 로 animation-delay 에 그대로 실습니다. 자바스크립트는 클래스 토글 한 번만 하고 연쇄 타이밍은 CSS 가 계산합니다.

  // 계산 겹: 항목 i 가 터지는 시각은 지연 값을 i 번 누적한 값(i * DELAY_STEP_MS)이다 — CSS 변수로 실어
  // animation-delay 에 그대로 쓴다. 자바스크립트는 트리거 한 번(클래스 토글)만 하고 연쇄는 CSS 가 계산한다.
  items.forEach(function (li, i) {
    li.style.setProperty('--delay', (i * DELAY_STEP_MS) + 'ms');
  });

  function human() { if (isDemo) { wrap.classList.remove('is-demo'); isDemo = false; } }

  function burst() {
    list.classList.remove('is-bursting');
    // reflow 를 강제해 같은 클래스를 다시 걸어도 애니메이션이 재시작되게 한다
    void list.offsetWidth;
    list.classList.add('is-bursting');
  }
연쇄 체크 마커 — 지연 값을 누적해 체크가 연쇄 터지는 방식
새 창에서 열기

09 · 연쇄 체크 마커 — 지연 값을 누적해 체크가 연쇄 터지는 방식 — 측정 누적면적 0.367% · 움직인 프레임 10/23GODRICH 원작 · zip 에 SCSS·React 포함 · 비밀번호 보기

DELAY_STEP_MSanimation-delay$subject-mint

값이 마커를 바꾸는 곳 — 각도·자릿수·위상·판정 기준

한 걸음을 정하는 상수들

각 항목의 표정은 이름 붙은 상수가 정합니다 — 01 의 DIAL_STEP_DEG(30)·STEP_MS(480), 02 의 ODO_DIGITS(2)·DIGIT_H(18), 03 의 WAVE_PHASE_DEG(40)·AMPLITUDE_PX(6), 04 의 MARCH_RATE_DEG_S(140), 05 의 STEP_MS(900), 06 의 R_MAX(15), 07 의 MAX_DEPTH(2), 08 의 BASE_AREA(400), 09 의 DELAY_STEP_MS(110)·CYCLE_MS(950) 입니다. css 리스트 스타일이라고 하면 보통 list-style-type 으로 불릿 모양을 갈아 끼우는 일을 뜻하지만, 이 편에서 값을 손대는 자리는 모양 목록이 아니라 이 상수들입니다. 참고로 05 의 글로우 맥박 주기는 자바스크립트 상수가 아니라 scss 의 $dur-loop(2s) 토큰이 정합니다.

이웃 가지 — 리스트 축의 다른 편

목록 항목을 여닫는 상호작용은 아코디언 리스트 UI 9가지 — 체크리스트까지가 다루고, 이 편은 항목 앞 마커의 계산만 다룹니다. 항목을 밀어 지우고 넘기는 조작은 스와이프 삭제 리스트 UI 9가지 — 페이지네이션까지에서, 숫자를 세 올리는 움직임은 CSS 숫자 증가 애니메이션 9종 — 한 줄 복붙으로에서 다룹니다 — 이 편의 02 주행계는 값을 자릿수로 분해해 굴린다는 점에서 세 올리기와 갈립니다. 목록 문법 자체는 list-style 문서와 CSS counters 문서를 따릅니다.

어디서 깨지는가 — list-style 지원 범위, 폴백, reduced-motion

::marker 가 직접 받는 속성은 color·content·font 세 가지뿐이라 회전·이동·확대·글로우·애니메이션·자식 요소는 전부 불가능합니다. 그래서 아홉 항목 모두 list-style: none 으로 네이티브 마커를 지우고 같은 자리에 다시 세우는데, 01·03·05·09 는 li 의 ::before·::after 로 세우고 02·04·06·08 은 굴러가는 숫자 스트립과 클릭 가능한 버튼을 담아야 해서 실제 DOM 요소를 넣으며, 07 은 중첩 ul 자체에 ::before 레일을 붙입니다. 번호를 다시 그리는 건 05 하나로 counter-reset·counter-increment 와 content: counter(item) 값을 씁니다. css 리스트 점 없애기가 궁금해서 찾아온 사람에게는, 그 첫 동작이 이미 아홉 항목 전부에 들어 있습니다.

아홉 항목의 html·scss·js 전체는 6tdgyv9r 압축 비밀번호로 받아 상수를 직접 바꿔가며 열어볼 수 있습니다.

reduced-motion 이 남기는 것

reduce 설정이 켜지면 01 은 turns 를 i+1 종료 상태로, 02 는 값을 [42, 97, 5] 결과로, 03 은 위상을 π/2 파고 정점으로, 04 는 오프셋을 90 도로 즉시 고정합니다. 05 는 펄스를 끊고 4px 정적 링을 남기며, 06 은 두 번째 프리셋을 고정하고, 07 은 완전히 펼치며, 08 은 행마다 서로 다른 상태를, 09 는 체크가 다 찬 완료 상태를 보여 줍니다. CSS 쪽에도 항목마다 reduced-motion 블록이 있어 전환을 전부 끊습니다.

한 페이지에 아홉을 몰아 넣으면 requestAnimationFrame 루프가 동시에 아홉 개 도는 셈이라 저사양 기기에서는 프레임이 밀릴 수 있습니다 — 실서비스에 붙일 때는 필요한 마커 하나만 남기는 편이 안전합니다.

변형 세 가지와 접근성

변형 값 느낌
다이얼 각도 촘촘하게 하기 01 DIAL_STEP_DEG 30 → 15 DIAL_STEP_DEG 를 15 로 낮추면 같은 횟수의 전진에 바늘이 받는 각도가 작아져(turns[i] * DIAL_STEP_DEG * (i+1)) 다음 눈금에 닿기까지 클릭이 더 많이 필요해진다 — 다이얼이 한 걸음씩 촘촘하게 오른다
주행계 자릿수 늘리기 02 ODO_DIGITS 2 → 3 ODO_DIGITS 를 3 으로 올리면 자릿수 분해가 백의 자리까지 늘어나(Math.floor(value / place) % 10, place = 10^(ODO_DIGITS-1-d)) 000 부터 999 까지 세 자리 주행계로 굴러간다 — 값이 두 배가 아니라 열 배로 넓어진다
물결 위상 넓히기 03 WAVE_PHASE_DEG 40 → 80 WAVE_PHASE_DEG 를 80 로 올리면 인접 항목 사이 위상 간격이 넓어져(i * WAVE_PHASE_DEG * π/180) 같은 시각에 목록 전체에 파도 마디가 더 많이 들어온다 — 물결이 성기게 번지는 대신 촘촘한 겹결로 보인다

장식 마커는 스크린 리더가 읽지 않도록 02 의 주행계·04 의 링·06 의 칩이 aria-hidden 으로 숨겨져 있고, 번호를 다시 그리는 05 의 ::before 는 내용이 곧 번호라 그대로 노출됩니다. 08 의 마커는 상태를 aria-label 로 알리는 실제 button 이고, 04 는 행진 토글에 aria-pressed 를, 07 은 깊이 공개 버튼에 aria-expanded 를 상태에 맞춰 바꿉니다. 조작이 전부 button 이라 Enter·Space 로 그대로 되고, reduce 환경에서는 앞 절에서 본 대로 항목마다 저마다의 최종 모양이 애니메이션 없이 남습니다.

FAQ

css 리스트 가로정렬로 방향을 바꿔도 이 마커들을 그대로 쓸 수 있나요?

li 의 ::before·::after 로 마커를 세운 01·03·05·09 는 배경이 되는 목록을 가로로 흘려도 마커가 항목을 따라가고, 실제 요소를 넣은 02·04·06·08 도 인라인이라 같이 흐릅니다. 07 의 레일만 세로 신장을 전제로 그려져 있어 가로 배치에서는 레일 축을 다시 그려야 합니다.

::marker 에 직접 이 효과들을 걸 수는 없나요?

color·content·font 외의 속성은 ::marker 가 받지 못해 회전·굴림·글로우는 애초에 불가능합니다. 아홉 항목이 모두 list-style: none 으로 마커를 지우고 같은 자리에 다시 세우는 구조인 것도 그래서이고, 마커가 목록 문법 안에 있으면서도 움직이게 하려면 이 대체가 출발점입니다.

아홉 중 어느 항목이 화면에 가장 큰 영향을 주나요?

매 프레임 값을 다시 계산하는 바쁨으로는 03·04 가 23/23 로 가장 앞서고, 번지는 폭으로는 누적면적 2.81% 의 01 이, 픽셀 차의 셈으로는 강도 142.2 의 03 이 가장 큽니다. 계산량 자체는 모두 가볍습니다 — 05 의 나눗셈 판정도 이 시연의 번호 범위에서는 횟수가 적어 부담이 되지 않습니다.

압축 비밀번호를 입력하세요

비밀번호는 이 글 본문 안에 있습니다. 읽다 보면 나옵니다.