進捗と手順をバーで視覚化する
不定型・決定型・ステップ型の3パターンで、プログレスバーの作り方を解説します。各デモと同じ動きを再現できるHTML・CSS・JavaScriptを掲載しています。
HTML・CSS・JSコードプレビューツールでも動作を確認できます。
このページで作るもの
① 不定型プログレスバー — overflow と @keyframes で横断させる
速度: 2s 色: #4caf50
<div class="pg-flow-wrap">
<div class="pg-flow-bar"></div>
</div>
.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%;
}
}
外枠に position: relative と overflow: hidden、バーに position: absolute を付けます。@keyframes で left を枠外から枠外へ動かすと、終わりのない不定型バーになります。速度・色ボタンを押すとデモとコピペ用CSSが同時に更新されます。
② 決定型プログレスバー — チェック数から width をパーセントで算出
<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>
.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;
}
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();
change のたびにチェック済み数を数え、パーセントを style.width に入れます。CSS に transition: width を付けておくと、バーが滑らかに伸びます。タスクを増やしても計算式はそのまま使えます。
③ ステップ式プログレスバー — 現在ステップから幅を算出する
<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">← 前へ</button>
<button class="pg-step-next" type="button">次へ →</button>
</div>
</div>
.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;
}
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();
バー幅は (現在ステップ – 1) / (全ステップ数 – 1) × 100 で求めます。インデックスが現在ステップ未満の要素に is-done を付けると、円とラベルの色をまとめて変えられます。
不定型と決定型の使い分けは?
終わりが分からない待ち時間は①不定型、完了率が分かる処理は②決定型です。単純な待ち表示だけなら ローディングアイコン でも十分です。
バーが動かないときは?
外枠に overflow: hidden と position: relative、バーに position: absolute があるか確認してください。width / left の @keyframes が欠けていると動きません。
パーセント表示をバーの中央にできますか?
可能です。パーセンテージ要素を absolute で配置し、left / transform で中央寄せします。文字色はバーの色とコントラストが取れるよう調整してください。
ステップ数を増やすには?
HTML に .pg-step を追加し、JS の totalStp を同じ数に合わせます。③の計算式はそのまま使えます。
当サイトで公開しているWebデザインやUIの実装例は、一覧として以下記事に纏めています。

