プログレスバーの作り方|不定型・決定型・ステップ

進捗と手順をバーで視覚化する

不定型・決定型・ステップ型の3パターンで、プログレスバーの作り方を解説します。各デモと同じ動きを再現できるHTML・CSS・JavaScriptを掲載しています。
HTML・CSS・JSコードプレビューツールでも動作を確認できます。

① 不定型プログレスバー — overflow と @keyframes で横断させる

速度: 2s  色: #4caf50

HTML
<div class="pg-flow-wrap">
  <div class="pg-flow-bar"></div>
</div>
CSS
.pg-flow-wrap {
  position: relative;
  width: 100%;
  height: 20px;
  overflow: hidden;
  border-radius: 5px;
  background-color: #e2e8f0;
}

.pg-flow-bar {
  position: absolute;
  width: 50%;
  height: 100%;
  background-color: #4caf50;
  animation: pgFlow 2s infinite;
}

@keyframes pgFlow {
  0% {
    left: -50%;
  }
  50% {
    left: 25%;
  }
  100% {
    left: 100%;
  }
}
overflow: hidden ではみ出しを隠し、バーを横断させる

外枠に position: relative と overflow: hidden、バーに position: absolute を付けます。@keyframes で left を枠外から枠外へ動かすと、終わりのない不定型バーになります。速度・色ボタンを押すとデモとコピペ用CSSが同時に更新されます。

② 決定型プログレスバー — チェック数から width をパーセントで算出

0%
HTML
<div class="pg-task-bar">
  <div class="pg-task-fill"></div>
  <span class="pg-task-pct">0%</span>
</div>
<div class="pg-task-list">
  <label class="pg-task-item"><input type="checkbox" class="pg-task-chk"> Task 1</label>
  <label class="pg-task-item"><input type="checkbox" class="pg-task-chk"> Task 2</label>
  <label class="pg-task-item"><input type="checkbox" class="pg-task-chk"> Task 3</label>
</div>
CSS
.pg-task-bar {
  position: relative;
  width: 100%;
  height: 24px;
  margin-bottom: 20px;
  overflow: hidden;
  border-radius: 12px;
  background-color: #e2e8f0;
}

.pg-task-fill {
  width: 0%;
  height: 100%;
  border-radius: 12px;
  background-color: #4caf50;
  transition: width 0.4s ease;
}

.pg-task-pct {
  position: absolute;
  top: 50%;
  right: 10px;
  transform: translateY(-50%);
  font-size: 12px;
  font-weight: 700;
  color: #334155;
}

.pg-task-list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 16px;
}

.pg-task-item {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.9rem;
  color: #334155;
  cursor: pointer;
}

.pg-task-chk {
  width: 18px;
  height: 18px;
  accent-color: #4caf50;
  cursor: pointer;
}
JS
var boxList = document.querySelectorAll('.pg-task-chk');
var fillEl = document.querySelector('.pg-task-fill');
var pctEl = document.querySelector('.pg-task-pct');

function refreshBar() {
  var total = boxList.length;
  var tally = 0;
  boxList.forEach(function(box) {
    if (box.checked) tally++;
  });
  var pct = Math.round(tally / total * 100);
  fillEl.style.width = pct + '%';
  pctEl.textContent = pct + '%';
}

boxList.forEach(function(box) {
  box.addEventListener('change', refreshBar);
});

refreshBar();
チェック済み数 ÷ 全体数 × 100 を width に反映する

change のたびにチェック済み数を数え、パーセントを style.width に入れます。CSS に transition: width を付けておくと、バーが滑らかに伸びます。タスクを増やしても計算式はそのまま使えます。

③ ステップ式プログレスバー — 現在ステップから幅を算出する

1
STEP 1
2
STEP 2
3
STEP 3
4
STEP 4
HTML
<div class="pg-step-wrap">
  <div class="pg-step-track">
    <div class="pg-step-fill"></div>
  </div>
  <div class="pg-step-row">
    <div class="pg-step is-done">
      <div class="pg-step-circle">1</div>
      <span class="pg-step-lbl">STEP 1</span>
    </div>
    <div class="pg-step">
      <div class="pg-step-circle">2</div>
      <span class="pg-step-lbl">STEP 2</span>
    </div>
    <div class="pg-step">
      <div class="pg-step-circle">3</div>
      <span class="pg-step-lbl">STEP 3</span>
    </div>
    <div class="pg-step">
      <div class="pg-step-circle">4</div>
      <span class="pg-step-lbl">STEP 4</span>
    </div>
  </div>
  <div class="pg-step-btns">
    <button class="pg-step-prev" type="button">&#8592; 前へ</button>
    <button class="pg-step-next" type="button">次へ &#8594;</button>
  </div>
</div>
CSS
.pg-step-wrap {
  display: flex;
  flex-direction: column;
  gap: 20px;
  max-width: 400px;
}

.pg-step-track {
  width: 100%;
  height: 6px;
  overflow: hidden;
  border-radius: 3px;
  background: #e5e7eb;
}

.pg-step-fill {
  width: 0%;
  height: 100%;
  border-radius: 3px;
  background: #7c3aed;
  transition: width 0.4s ease;
}

.pg-step-row {
  display: flex;
  justify-content: space-between;
}

.pg-step {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.pg-step-circle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: 2px solid #e5e7eb;
  border-radius: 50%;
  background: #e5e7eb;
  font-size: 14px;
  color: #9ca3af;
  transition: background 0.3s, border-color 0.3s, color 0.3s;
}

.pg-step.is-done .pg-step-circle {
  border-color: #7c3aed;
  background: #7c3aed;
  color: #fff;
}

.pg-step-lbl {
  font-size: 11px;
  color: #9ca3af;
  transition: color 0.3s;
}

.pg-step.is-done .pg-step-lbl {
  color: #7c3aed;
}

.pg-step-btns {
  display: flex;
  gap: 12px;
}

.pg-step-prev,
.pg-step-next {
  padding: 8px 20px;
  border: 1px solid #7c3aed;
  border-radius: 8px;
  background: #fff;
  color: #7c3aed;
  cursor: pointer;
  transition: background 0.2s, color 0.2s;
}

.pg-step-prev:hover,
.pg-step-next:hover {
  background: #7c3aed;
  color: #fff;
}

.pg-step-prev:disabled,
.pg-step-next:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
JS
var stpNum = 1;
var totalStp = 4;
var fillEl = document.querySelector('.pg-step-fill');
var prevBtn = document.querySelector('.pg-step-prev');
var nextBtn = document.querySelector('.pg-step-next');
var stepList = document.querySelectorAll('.pg-step');

function refreshSteps() {
  fillEl.style.width = ((stpNum - 1) / (totalStp - 1) * 100) + '%';
  stepList.forEach(function(el, i) {
    el.className = i < stpNum ? 'pg-step is-done' : 'pg-step';
  });
  prevBtn.disabled = stpNum === 1;
  nextBtn.disabled = stpNum === totalStp;
}

prevBtn.addEventListener('click', function() {
  if (stpNum > 1) {
    stpNum--;
    refreshSteps();
  }
});

nextBtn.addEventListener('click', function() {
  if (stpNum < totalStp) {
    stpNum++;
    refreshSteps();
  }
});

refreshSteps();
現在ステップから進捗率を算出し is-done で見た目を切替

バー幅は (現在ステップ – 1) / (全ステップ数 – 1) × 100 で求めます。インデックスが現在ステップ未満の要素に is-done を付けると、円とラベルの色をまとめて変えられます。

注意点:不定型は「処理中だが進捗%が不明」なときに向きます。%が分かる処理なら決定型、ウィザードや会員登録のような段階があるならステップ型を選んでください。同じページで不定型と決定型を混ぜると意味が伝わりにくくなることがあります。

不定型と決定型の使い分けは?

終わりが分からない待ち時間は①不定型、完了率が分かる処理は②決定型です。単純な待ち表示だけなら ローディングアイコン でも十分です。

バーが動かないときは?

外枠に overflow: hidden と position: relative、バーに position: absolute があるか確認してください。width / left の @keyframes が欠けていると動きません。

パーセント表示をバーの中央にできますか?

可能です。パーセンテージ要素を absolute で配置し、left / transform で中央寄せします。文字色はバーの色とコントラストが取れるよう調整してください。

ステップ数を増やすには?

HTML に .pg-step を追加し、JS の totalStp を同じ数に合わせます。の計算式はそのまま使えます。


当サイトで公開しているWebデザインやUIの実装例は、一覧として以下記事に纏めています。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次