N-002 Navigation medium

How to create a stepper dot progress ドットステップナビの作り方

A multi-step progress component using dots and a connecting line that animates to the active step. 複数ステップの進捗をドットとラインで可視化し、アクティブインジケーターが滑らかに切り替わるステッパーUI。

ライブデモ Live Demo

Step 1

概要・用途・特徴Overview, Usage & Features

何ができるかWhat it does

A multi-step progress component using dots and a connecting line that animates to the active step.

複数ステップの進捗をドットとラインで可視化し、アクティブインジケーターが滑らかに切り替わるステッパーUI。

どこで使うかWhere to use

website header, dashboard sidebar, mobile menu, admin panel

チェックアウトフロー、オンボーディング、フォームウィザード、プロセス表示

特徴Key features

Visual step progress indicator using dot or circle markers. Active, completed, and upcoming states with distinct styling. CSS-only progress line fill between steps. Responsive horizontal or vertical orientation.

ドットまたは丸マーカーを使用した視覚的なステップ進行インジケーター。アクティブ・完了・未完了の各状態に異なるスタイル。ステップ間のCSSオンリーの進行ラインフィル。水平または垂直方向のレスポンシブ表示。

調整可能パラメータ Adjustable Parameters

Parameter Default Description
step countadjust step count for different workflows
transition durationadjust `transition-duration` for faster/slower fills
labelsattach step titles or tooltips
reduced motionswitch to instant changes under reduced motion

実装コード Implementation Code

// 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>
  );
}
.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;
}
import { useState } from "react";
import "./N-002.css";

const steps = ["Plan", "Design", "Build", "Launch"];

export default function StepperDotProgress() {
  const [current, setCurrent] = useState(1);
  const percentage = (current - 1) / (steps.length - 1);

  return (
    <div className="stepper">
      <div className="stepper__track" />
      <div className="stepper__progress" style={{ width: `${percentage * 100}%` }} />
      {steps.map((label, index) => {
        const stepNumber = index + 1;
        const isActive = stepNumber === current;
        const isComplete = stepNumber < current;
        return (
          <button
            key={label}
            className={`stepper__dot${isActive ? " is-active" : ""}${isComplete ? " is-complete" : ""}`}
            onClick={() => setCurrent(stepNumber)}
          >
            {stepNumber}
          </button>
        );
      })}
    </div>
  );
}
.stepper {
  position: relative;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 20px;
}

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

.stepper__track {
  background: rgba(255, 255, 255, 0.2);
}

.stepper__progress {
  background: linear-gradient(90deg, #5c6ac4, #22d3ee);
  height: 2px;
  transition: width 0.35s ease;
}

.stepper__dot {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.35);
  background: rgba(255, 255, 255, 0.05);
  color: #fff;
  font-weight: 600;
  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);
}

仕組みとカスタマイズHow It Works & Customization

仕組みHow it works

Steps are flex items connected by a pseudo-element line. Completed steps get a filled background and a checkmark; the active step gets an accent border and pulse; upcoming steps are muted. The connector line uses a width or scaleX transition to animate fill as steps are completed.

ステップは疑似要素ラインで接続されたflexアイテム。完了済みステップはチェックマーク付きの塗りつぶし背景、アクティブステップはアクセントボーダーとパルス、未完了ステップはミュートされます。コネクターラインはステップ完了に伴ってwidthまたはscaleXトランジションでフィルをアニメーション。

カスタマイズ方法Customization

Replace dot markers with numbered circles for instructional flows. Add step labels below each marker. Switch to a vertical layout by changing flex-direction to column. Animate the connector fill on step advance.

説明フロー用にドットマーカーを番号付き丸に置き換え。各マーカーの下にステップラベルを追加。flex-directionをcolumnに変えて縦レイアウトに切り替え。ステップ進行時にコネクターフィルをアニメーション。

注意点Caveats

Provide aria-current="step" on the active step and aria-label on each step marker describing its position (e.g., "Step 2 of 4: Shipping"). Use a visually hidden live region to announce step changes to screen reader users.

アクティブステップにaria-current="step"を設定し、各ステップマーカーに位置を説明するaria-label(例:"4ステップ中ステップ2:配送")を追加してください。スクリーンリーダーユーザーへのステップ変更アナウンスには視覚的に非表示のlive regionを使用してください。

よくある質問 Frequently Asked Questions

How to customize the stepper dot progress? Stepper Dot Progressをカスタマイズするには?

Modify the CSS custom properties and class styles defined in the code section. Key adjustable values include colors, sizes, durations, and spacing. See the Adjustable Parameters section for specific variables.

コードセクションで定義されているCSSカスタムプロパティとクラススタイルを変更してください。色、サイズ、時間、間隔が主な調整可能値です。具体的な変数は調整可能パラメータセクションを参照してください。

How to use the stepper dot progress in React? ReactでStepper Dot Progressを使うには?

Import the provided React component and its CSS file. The component accepts props for customization. Check the React code section for the full implementation and available props.

提供されているReactコンポーネントとCSSファイルをインポートしてください。コンポーネントのpropsでカスタマイズできます。完全な実装と利用可能なpropsはReactコードセクションを参照してください。

What are the performance implications of stepper dot progress? Stepper Dot Progressのパフォーマンスへの影響は?

This implementation uses CSS transforms and opacity for animations, which are GPU-accelerated. It's lightweight and doesn't cause layout thrashing. Consider using prefers-reduced-motion for accessibility.

この実装はCSSのtransformとopacityを使用しており、GPUアクセラレーションされます。軽量でレイアウトスラッシングを引き起こしません。アクセシビリティのためにprefers-reduced-motionの使用を検討してください。

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

以下をAIに貼り付けると実装を依頼できます。 Paste the following into your AI assistant to request implementation.