ライブデモ Live Demo

進捗トラックの幅はアクティブステップインデックスから算出され、CSS width トランジションで適用されます。ドットは `is-active` / `is-complete` クラスで塗りつぶし状態を切り替えます。

The progress track width is derived from the active step index and applied to a CSS width transition. Dots receive `is-active` / `is-complete` classes to toggle their filled state.

Step 1

AI向け説明 AI Description

`N-002` はフレックスレイアウトのステッパーに、絶対位置の進捗トラックを組み合わせます。アクティブステップのインデックスからトラック幅を算出し、CSS `width` トランジションで適用します。ドットは `is-active` / `is-complete` クラスで状態を制御します。

`N-002` combines a flex-based stepper with an absolute-positioned progress track. Track width is derived from the active step index and applied via a CSS `width` transition. Dot states are controlled by `is-active` / `is-complete` classes.

調整可能パラメータ Adjustable Parameters

実装 Implementation

HTML + CSS + JS

<div class="stepper" data-stepper>
  <div class="stepper__track"></div>
  <div class="stepper__progress"></div>
  <button class="stepper__dot is-active" data-step="1">1</button>
  <button class="stepper__dot" data-step="2">2</button>
  <button class="stepper__dot" data-step="3">3</button>
  <button class="stepper__dot" data-step="4">4</button>
</div>

<style>
.stepper {
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: relative;
}

.stepper__track {
  position: absolute;
  top: 50%;
  left: 32px;
  right: 32px;
  height: 2px;
  background: rgba(255, 255, 255, 0.2);
  transform: translateY(-50%);
}

.stepper__progress {
  position: absolute;
  top: 50%;
  left: 32px;
  height: 2px;
  background: linear-gradient(90deg, #5c6ac4, #22d3ee);
  transform: translateY(-50%);
  transition: width 0.35s ease;
}

.stepper__dot {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.35);
  position: relative;
  cursor: pointer;
}

.stepper__dot.is-active { border-color: #22d3ee; color: #22d3ee; }
.stepper__dot.is-complete::after {
  content: "";
  position: absolute;
  inset: 6px;
  border-radius: 50%;
  background: linear-gradient(135deg, #5c6ac4, #22d3ee);
  opacity: 1;
}
</style>

<script>
const dots = document.querySelectorAll(".stepper__dot");
const progress = document.querySelector(".stepper__progress");
dots.forEach((dot, i) => {
  dot.addEventListener("click", () => goToStep(i));
});

function goToStep(index) {
  dots.forEach((d, i) => {
    d.classList.toggle("is-complete", i < index);
    d.classList.toggle("is-active", i === index);
  });
  const first = dots[0], current = dots[index];
  progress.style.width =
    (current.offsetLeft + current.offsetWidth / 2) -
    (first.offsetLeft + first.offsetWidth / 2) + "px";
}
</script>

React (JSX + CSS)

// react/N-002.jsx
import { useState, useRef, useEffect } from "react";
import "./N-002.css";

export default function StepperDotProgress({ steps = 4 }) {
  const [active, setActive] = useState(0);
  const stepperRef = useRef(null);
  const [progressWidth, setProgressWidth] = useState(0);

  useEffect(() => {
    const dots = stepperRef.current?.querySelectorAll(".stepper__dot");
    if (!dots?.length) return;
    const first = dots[0], current = dots[active];
    setProgressWidth(
      current.offsetLeft + current.offsetWidth / 2 -
      (first.offsetLeft + first.offsetWidth / 2)
    );
  }, [active]);

  return (
    <div className="stepper" ref={stepperRef}>
      <div className="stepper__track" />
      <div className="stepper__progress" style={{ width: progressWidth }} />
      {Array.from({ length: steps }).map((_, i) => (
        <button
          key={i}
          className={`stepper__dot ${i < active ? "is-complete" : ""} ${i === active ? "is-active" : ""}`}
          onClick={() => setActive(i)}
        >
          {i + 1}
        </button>
      ))}
    </div>
  );
}

AIへの指示テンプレート AI Prompt Template

以下のテンプレートをコピーしてAIアシスタントに貼り付けると、このパターンの実装を依頼できます。 Copy the template below and paste it into your AI assistant to request an implementation of this pattern.

注意とバリエーション Notes & Variations

同じ構造でラベル付きタイムラインや2段ステッパーも作成できます。マークアップを変更せずに `aria-current="step"` などのARIA状態でアクセシビリティを向上させられます。

The same structure powers labeled timelines or dual-row steppers. Add ARIA states such as `aria-current="step"` to enhance accessibility while keeping the markup unchanged.