進み具合のバー(プログレスバー)をCSSで作る|progress要素の色・しま模様・読み込み中・ステップ表示、コピペ4種類と使いどころ

進み具合のバーをCSSで作る。しま模様のバー・progress要素・ステップ表示の見本とコード

ファイルを送っている間や、フォームを順に進む間に、「いまどれくらい進んだか」を横長のバーで見せる。これがプログレスバー(進み具合のバー)です。HTMLには、そのための progress という部品があり、見た目はCSSで変えられます。

使いどころは「数秒以上かかり、どれだけ進んだか分かる処理」です。一瞬で終わる処理にバーを出すと、ちらつくだけになります。どれだけ進んだか分からない処理に数字つきのバーを出すと、止まって見えます。

この記事の要点

  • HTMLの progress 要素は、appearance: none と、ブラウザごとの書き方(::-webkit-progress-value・::-moz-progress-bar)で色や形を変えられる
  • 使いどころは、アップロードやフォームの段など「数秒以上かかり、進み具合が分かる」場面。終わりが分からないときは value を書かず、流れる帯にする
  • バーには名前(label)を付ける。たまった部分は土台と3:1以上の差をつける。ブラウザごとの書き方は1つのルールにまとめない
トミー

連載「WEBの技術」の34回目です。
今回は、進み具合のバー。1回目のローディングと同じく「待っている人に、止まっていないと伝える」ための部品です。

完成見本:進み具合のバー4種類

下の4つは、ページを開いた時点から、0%から100%まで進んではまた0%に戻る動きを自動でくり返しています。くり返しているのは見本だからで、実際には、処理の進み具合に合わせて数字を書きかえます(書きかえ方は後半の「応用」で紹介します)。

※ 見本は読み上げソフトでは読まれないようにしています。

コピペ用のコード

HTMLはバーを出したい場所に、CSSはサイトのCSSファイルや、WordPressならテーマの「追加CSS」などに入れます。クラス名の頭の kd-pg は、サイトのほかのデザインと名前がぶつからないようにするための目印です。id は、同じページで2つ以上使うときは別の名前にしてください。

1. progress 要素の色を変える

HTMLの progress(進み具合を表すための部品)を、そのまま使う形です。appearance: none でブラウザ標準の見た目を消してから、色と角の丸みを付けています。進み具合は value(いまの量)と max(全体の量)で書きます。

HTML
<label class="kd-pg-label" for="kd-pg-1">アップロード中</label>
<progress class="kd-pg" id="kd-pg-1" max="100" value="60">60%</progress>
CSS
/* progress 要素の、ブラウザ標準の見た目を消す */
.kd-pg {
  appearance: none;
  display: block;
  width: 100%;
  height: 12px;
  border: 0;
  border-radius: 999px;
  background: #E2EBF2;
  overflow: hidden;
}
/* Chrome・Edge・Safari:土台と、たまった部分 */
.kd-pg::-webkit-progress-bar {
  background: #E2EBF2;
  border-radius: 999px;
}
.kd-pg::-webkit-progress-value {
  background: #0369A1;
  border-radius: 999px;
}
/* Firefox:たまった部分(上と1つにまとめて書かない) */
.kd-pg::-moz-progress-bar {
  background: #0369A1;
  border-radius: 999px;
}
.kd-pg-label {
  display: block;
  margin-bottom: 6px;
  font-size: 14px;
  font-weight: 700;
}
/* 色を強制する設定(Windowsのハイコントラストなど)でも、たまった部分を見せる */
@media (forced-colors: active) {
  .kd-pg {
    border: 1px solid CanvasText;
  }
  .kd-pg::-webkit-progress-value {
    forced-color-adjust: none;
    background: Highlight;
  }
  .kd-pg::-moz-progress-bar {
    forced-color-adjust: none;
    background: Highlight;
  }
}

2. 数字つき・しま模様が流れる

バーの上に名前と「60%」の数字を置き、たまった部分にしま模様を流す形です。progress の中は自由に飾りにくいので、ここでは div で作り、role="progressbar"(進み具合のバーだと読み上げソフトに伝える指定)と aria-valuenow(いまの数字)を付けています。長さは style="--p: 60" の数字で決まります。

HTML
<div class="kd-pg-head">
  <span id="kd-pg-2">保存中</span>
  <span class="kd-pg-num" aria-hidden="true">60%</span>
</div>
<div class="kd-pg-track" role="progressbar" aria-labelledby="kd-pg-2"
     aria-valuenow="60" style="--p: 60">
  <div class="kd-pg-fill"></div>
</div>
CSS
/* 名前と数字を、バーの上に左右に分けて置く */
.kd-pg-head {
  display: flex;
  justify-content: space-between;
  margin-bottom: 6px;
  font-size: 14px;
  font-weight: 700;
}
.kd-pg-num {
  color: #0369A1;
  font-variant-numeric: tabular-nums;
}
.kd-pg-track {
  height: 16px;
  border-radius: 999px;
  background: #E2EBF2;
  overflow: hidden;
}
/* --p(0〜100)の分だけ伸ばす。しま模様を横へ流す */
.kd-pg-fill {
  width: calc(var(--p, 0) * 1%);
  height: 100%;
  border-radius: inherit;
  background-color: #0369A1;
  background-image: linear-gradient(-45deg,
    rgb(255 255 255 / .2) 25%, transparent 25% 50%,
    rgb(255 255 255 / .2) 50% 75%, transparent 75%);
  background-size: 24px 24px;
  animation: kd-pg-stripe .8s linear infinite;
  transition: width .3s ease-out;
}
@keyframes kd-pg-stripe {
  to { background-position: 24px 0; }
}
@media (prefers-reduced-motion: reduce) {
  .kd-pg-fill {
    animation: none;
    transition: none;
  }
}
@media (forced-colors: active) {
  .kd-pg-track {
    border: 1px solid CanvasText;
  }
  .kd-pg-fill {
    forced-color-adjust: none;
    background: Highlight;
  }
}

3. 終わりが分からないとき

どれだけ進んだか分からないときは、progress に value を書きません。この状態は :indeterminate(決まっていない状態)で選べます。短い帯を左から右へくり返し流して、「止まっていない」ことを見せます。1のCSSと一緒に使います。

HTML
<label class="kd-pg-label" for="kd-pg-3">読み込み中</label>
<progress class="kd-pg" id="kd-pg-3" max="100"></progress>
CSS(1のCSSと一緒に使う)
/* value がない(終わりが分からない)とき:短い帯を左から右へ流す */
.kd-pg:indeterminate {
  background: #E2EBF2 linear-gradient(#0369A1, #0369A1) no-repeat;
  background-size: 35% 100%;
  animation: kd-pg-slide 1.4s ease-in-out infinite;
}
.kd-pg:indeterminate::-webkit-progress-bar {
  background: transparent;
}
.kd-pg:indeterminate::-moz-progress-bar {
  background: transparent;
}
@keyframes kd-pg-slide {
  from { background-position: -60% 0; }
  to   { background-position: 160% 0; }
}
/* 止めると「固まった」ように見えるので、ゆっくり動かす */
@media (prefers-reduced-motion: reduce) {
  .kd-pg:indeterminate {
    animation-duration: 4s;
  }
}
@media (forced-colors: active) {
  .kd-pg:indeterminate {
    forced-color-adjust: none;
    background-color: Canvas;
    background-image: linear-gradient(Highlight, Highlight);
  }
}

4. フォームの何番目かを見せる

お問い合わせフォームなどで「いま何番目の画面か」を、丸と線で見せる形です。段は ol(番号つきの並び)で書き、いまの段の li に aria-current="step"(いまの段だと読み上げソフトに伝える指定)を付けます。終わった段には is-done というクラスを付けます。

HTML
<ol class="kd-pg-steps">
  <li class="is-done">入力</li>
  <li aria-current="step">確認</li>
  <li>完了</li>
</ol>
CSS
/* フォームの「いま何番目か」を、丸と線で見せる */
.kd-pg-steps {
  display: flex;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: kd-step;
}
.kd-pg-steps li {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: #5A6E7E;
  counter-increment: kd-step;
}
/* 丸の中の番号 */
.kd-pg-steps li::before {
  content: counter(kd-step);
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border: 2px solid #7B8A97;
  border-radius: 50%;
  background: #fff;
  font-weight: 700;
}
/* 前の丸とつなぐ線 */
.kd-pg-steps li + li::after {
  content: "";
  position: absolute;
  top: 15px;
  right: 50%;
  width: 100%;
  border-top: 2px solid #7B8A97;
}
/* 終わった段と、いまの段 */
.kd-pg-steps .is-done::before,
.kd-pg-steps [aria-current="step"]::before {
  border-color: #0369A1;
  background: #0369A1;
  color: #fff;
}
.kd-pg-steps .is-done + li::after {
  border-color: #0369A1;
}
.kd-pg-steps [aria-current="step"] {
  color: #0369A1;
  font-weight: 700;
}
@media (forced-colors: active) {
  .kd-pg-steps .is-done::before,
  .kd-pg-steps [aria-current="step"]::before {
    forced-color-adjust: none;
    border-color: Highlight;
    background: Highlight;
    color: HighlightText;
  }
}

2の数字(60%)には aria-hidden="true" を付けています。バーの aria-valuenow から同じ数字が読み上げられるので、2回読まれないようにするためです。

仕組み:progress 要素は「土台」と「たまった部分」でできている

まず、ブラウザ標準の見た目を消す

progress は、何も指定しないとブラウザやOSごとの見た目で表示されます。appearance: none は、この標準の見た目を消す指定です。これを書いてから、高さ・角の丸み・色を付けます。

ブラウザごとに、別の書き方で色を付ける

バーは「土台」と、その上の「たまった部分」の2つでできています。たまった部分の色は、ChromeやSafariでは ::-webkit-progress-value、Firefoxでは ::-moz-progress-bar という書き方で指定します。どちらも標準の仕様ではなく、各ブラウザが独自に用意している書き方です。MDNの対応表では、::-webkit-progress-value はFirefoxが対応していません。

この2つは、.kd-pg::-webkit-progress-value, .kd-pg::-moz-progress-bar { … } のように1つにまとめて書いてはいけません。CSSは、知らない書き方が1つでも混ざったルールを、まるごと読み飛ばします。まとめて書くと、どのブラウザでも色が付かなくなります。

value を書かないと「終わりが分からない」状態になる

<progress max="100"> のように value を書かないと、ブラウザは「進行中だが、あとどれくらいか分からない」状態として扱います。CSSでは :indeterminate で選べるので、3はこの状態にだけ流れる帯を付けています。JavaScriptで数字が分かったら value を入れると、自動で1の見た目に切りかわります。

div で作るときは、役割と数字を書き足す

2のように div で作ると、見た目は自由になりますが、読み上げソフトには「ただの箱」としか伝わりません。そこで role="progressbar" で役割を、aria-valuenow でいまの数字を伝えます。0〜100以外の範囲を使うときは、aria-valuemin・aria-valuemax も書きます。名前は、見えている文字があれば aria-labelledby で、その文字の id を指します。

数値を変えるとどうなるか

バーの高さ

4px(左)は、スマホの画面では線にしか見えず、進んでいることに気づきにくくなります。24px(右)は、ページの中で目立ちすぎて、ほかの内容より重たく見えます。ページの中に置くなら、8〜16pxあたりが目安です。

たまった部分の色

薄い水色(左)は、土台との差が1.4:1しかなく、どこまでたまったか分かりにくくなります。WCAG(ウェブのアクセシビリティの国際的な基準)2.2の達成基準1.4.11では、部品の見分けるのに必要な部分は、となりの色と3:1以上の差をつけることとされています。KAKERUブルー(#0EA5E9・中央)でも2.3:1なので、見本では濃い #0369A1(4.9:1・右)を使っています。

変えるところ指定今回の値目安
バーの高さheight12px(2は16px)8〜16px
たまった部分の色::-webkit-progress-value など#0369A1土台と3:1以上
しま模様の幅background-size24px高さの1.5倍前後
しまが流れる速さanimation の秒数0.8秒0.6〜1.2秒
帯が1回流れる時間animation の秒数(3)1.4秒1〜2秒

スマホと、見る人への配慮

バーには必ず名前を付ける

名前のないバーは、読み上げソフトで数字だけが伝わり、何の進み具合なのかが分かりません。progress なら label で、div なら aria-labelledby で「アップロード中」などの名前を付けます。MDNでも、progress の中に書いた文字(見本の「60%」)は名前にはならず、古いブラウザ向けの代わりの表示だと説明されています。

「動きを減らす」設定の人には、動きを小さくする

画面の動きが苦手な人は、スマホやパソコンで「動きを減らす」設定をオンにしていることがあります。prefers-reduced-motion を使い、2のしま模様は止め、3の流れる帯は4秒かけてゆっくり動かすようにしています。3を止めないのは、帯が止まると「固まった」「壊れた」と見えるためです。WCAGの達成基準2.2.2の解説でも、読み込み中で操作ができない間の動きは、進み具合が見えないと止まったと思われる場合には、必要なものとして扱えるとされています。

色を強制する設定でも、たまった部分を見せる

Windowsのハイコントラストなど、OSが色を決める設定(強制カラーモード)では、背景の色はOSの決めた色に置きかわり、グラデーションは消えます。そのままだと、たまった部分も、終わった段の丸も見えなくなります。そこで @media (forced-colors: active) の中で、forced-color-adjust: none(この部分だけ色を強制しない指定)を書き、OSの強調色 Highlight を使っています。

スマホでは、数字を大きくしすぎない

2の数字は font-variant-numeric: tabular-nums(数字の幅をそろえる指定)で、数字が変わっても横に揺れないようにしています。スマホの幅では、名前と数字が1行に収まるかを確かめます。4のステップ表示は、段の名前が長いと折り返すので、2〜4文字に収めます。

トミー

バーは、ただ置くだけでは「待たせている」ことは変わりません。
それでも、どこまで進んだかが見えると、待つ側は次に何が起きるか分かります。だから、数字が分かる処理には数字を出します。

応用:実際の進み具合でバーを動かす

実際のサイトでは、ファイルを送る処理などから進み具合(0〜100)を受け取り、そのたびにバーを書きかえます。下の関数は、1の progress にも、2の div にも使えます。100になったら、バーの下の文字で「保存が終わりました」と知らせます。

HTML(2の形)
<div class="kd-pg-head">
  <span id="kd-pg-try-name">保存中</span>
  <span class="kd-pg-num" aria-hidden="true">0%</span>
</div>
<div class="kd-pg-track" id="kd-pg-try" role="progressbar"
     aria-labelledby="kd-pg-try-name" aria-valuenow="0" style="--p: 0">
  <div class="kd-pg-fill"></div>
</div>
<p id="kd-pg-try-done" role="status"></p>
JavaScript
/* 進み具合(0〜100)を受け取って、バーと数字を書きかえる */
function kdSetProgress(id, p) {
  var bar = document.getElementById(id);
  if (bar.tagName === 'PROGRESS') {
    bar.value = p;
  } else {
    bar.style.setProperty('--p', p);
    bar.setAttribute('aria-valuenow', p);
    var num = bar.parentNode.querySelector('.kd-pg-num');
    if (num) num.textContent = p + '%';
  }
  /* 100になったら、終わったことを文字で知らせる */
  if (p >= 100) {
    document.getElementById(id + '-done').textContent = '保存が終わりました';
  }
}

role="status" を付けた文字は、中身が変わったときに読み上げソフトが読み上げます。途中の数字を毎回読み上げるとうるさくなるので、知らせるのは「終わった」ときだけにしています。下の見本の「試す」を押すと、3秒ほどで100%まで進みます(キーボードでも押せます)。

保存中

※ どれだけ進んだかをサーバーから受け取る仕組みは、使っているフォームやプラグインによって変わります。

AIに頼むなら

同じようなバーは、Claudeなどの生成AIに頼んでもすぐ作れます。そのときは、見た目だけでなく、使う部品・名前・配慮まで伝えると、直す回数が減ります。

ファイルのアップロード中に出す進み具合のバーを、HTMLの progress 要素で作って。
高さ12px・角丸・たまった部分は #0369A1、label で「アップロード中」と名前を付ける。
ChromeとFirefoxの書き方は別のルールにして、強制カラーモードでも見えるようにして。

AIが出したコードは、そのまま使う前に、次の3つを確かめます。

  • ブラウザごとの書き方が、1つのルールにまとまっていないか。::-webkit-progress-value と ::-moz-progress-bar がカンマでつながっていたら、別々に分けます
  • div で作ったバーに、役割と数字が書かれているか。role="progressbar" と aria-valuenow がなく、幅だけ変える作りになっていないかを見ます
  • 途中の数字を、毎回読み上げる作りになっていないか。数字を書きかえる場所に aria-live が付いていると、1%ごとに読み上げられます。知らせるのは終わったときだけにします

KAKERUならこう使う/使わない

最後に、作り手としての判断です。

使う場面

  • ファイルのアップロードや書き出しに「数字つきのバー」。数秒以上かかり、どれだけ送れたかが分かる処理に使います
  • 3画面以上に分かれたフォームに「ステップ表示」。入力→確認→完了のように、あと何画面あるかを最初に見せます
  • 終わりが分からない読み込みに「流れる帯」。ボタンを押してから結果が出るまで、止まっていないことを見せます

使わない場面

  • 1秒もかからない処理。バーが一瞬出て消えるだけになり、かえって画面がちらつきます
  • 進み具合が分からないのに、数字を出すこと。決まった速さで90%まで進めて止める、のような「それらしい数字」は出しません。止まったときに信用を落とします
  • 1画面だけのお問い合わせフォームのステップ表示。段が「入力」と「完了」しかないなら、表示しなくても迷いません
トミー

KAKERUなら、バーを出す前に「この処理は、どれだけ進んだか本当に分かるか」を確かめます。
分かるなら数字つきのバー、分からないなら流れる帯。ここを取りちがえないことが、いちばん大事だと考えています。

まとめ

  • 進み具合のバーは、HTMLの progress 要素と、appearance: none・ブラウザごとの書き方で作れる
  • ::-webkit-progress-value と ::-moz-progress-bar は、1つのルールにまとめずに別々に書く
  • value を書かなければ「終わりが分からない」状態になり、:indeterminate で流れる帯にできる
  • div で作るなら role=”progressbar” と aria-valuenow。バーには label などで名前を付け、土台と3:1以上の差をつける
  • 使うのは、数秒以上かかり進み具合が分かる処理と、3画面以上のフォーム

まずは1の「progress 要素の色を変える」をコピーして、高さや色を変えてみてください。

参考にした資料

いずれも2026年10月31日に確認しました。ブラウザの対応状況は変わることがあります。最新の情報は各ページでご確認ください。

ふだんの制作の話や、作ったものの裏側は Instagram と X でも出しています。

関連記事

CSSだけで作るローディングアニメーション コピペで使える5種類と、見る人への配慮
数字が0から増えていくカウンター。見本とコード
入力欄を選んだら色が変わる。見本とコード
チェックボックスの見た目をCSSで変える。見本とコード
進み具合のバーをCSSで作る。しま模様のバー・progress要素・ステップ表示の見本とコード

コメントを残す

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です

CAPTCHA


ABOUTこの記事をかいた人

25歳からWEBの世界に携わり、WEBデザインから始めて、今はWEBシステムまで一貫して制作しています。問題点を洗い出し、改善を提案する中で、WEB・グラフィック・動画・システムを縦断して提案するのが得意です。