本記事では、svgの基本を抑えつつ、円形プログレスバーをSVGとCSSでシンプルに実装する方法を解説します。
✅ svgで円を表示する方法
svgのcircle
タグを使用することで、簡単に円を表示することができます。
<svg viewBox="0 0 100 100" width="100" height="100" fill="none">
<circle cx="50" cy="50" r="45" stroke="lightgray" stroke-width="10" />
</svg>
各属性について説明します。
属性 | 説明 |
---|---|
viewBox | SVGの描画領域を定義します。xの最小値 、yの最小値 、幅 、高さ の順で指定します。 |
width・height | SVGの表示サイズ(px単位)を指定します。 |
cx・cy | 円の中心座標を指定します。デフォルトでは中心が座標の (0, 0) に配置されます。 |
r | 円の半径を指定します。stroke-width の影響を受けるので、viewBoxに収めるには注意が必要です。 |
stroke | 円周の線の色を指定します。 |
stroke-width | 円周の線の太さを指定します。線の中心を軸に、内側と外側の両方に太さが広がります。 |
横幅:100px、高さ:100pxの円に、10pxのstrokeを指定した場合、
半径r
の値は45pxになります。

viewBox="0 0 100 100"
の中央に円を表示するには、
cx="50"
cy="50"
と指定する必要があります。

✅ 円形プログレスバーの仕組み
今回作成するプログレスバーは、
- 進捗の背景となる円
- 進捗を表す円
を重ねることで実現できます。
進捗を表す円は、12時の位置から線が時計回りに描画される場合
進捗率25%の時は、最初の4分の1だけ色がついた線で描画されていることになります。

このように円周の一部だけに色をつけるには、
stroke-dasharray
stroke-dashoffset
を使って、円周を破線で表すことで実現できます。
属性 | 説明 |
---|---|
stroke-dasharray | 線の長さと空白の長さを指定し、破線のパターンを定義します。 |
stroke-dashoffset | 破線をどの位置から見せるかを指定します。 |
💡値の求め方
半径45px、進捗率25%の場合を例に求め方を説明します。
①円周の長さを求める
- 半径が45pxなので、直径は90px
- 円周率を3.14とすると、円周の長さは 90 × 3.14 = 282.6pxとなります
円周の長さ = 直径 × 円周率(3.14)
②stroke-dasharray
に指定する
求めた円周の長さを、次のようにstroke-dasharray
に指定します。
stroke-dasharray="282.6 282.6"
これは、「282.6pxの実線」と「282.6pxの空白」が1セットになった破線を定義するという意味です。
※破線は実線から始まります。
③stroke-dashoffset
を求める
進捗率25%を表現するには、円の最初の1/4だけ実線を表示し、それ以外は空白にする必要があります。
そのためには、実線部分の開始位置を、75%分ずらして見せる必要があります。
計算式:282.6 ÷ 4 × 3 = 211.95px
これをstroke-dashoffset
に指定します。
stroke-dashoffset="211.95"
⚠️注意点:circleタグの描画開始位置は3時の方向
SVGの<circle>
は、デフォルトでは 3時の方向(右側)から描画が始まります。
進捗の開始を 12時方向(上) にしたい場合は、CSSで円を -90度回転させる必要があります。
それらを考慮すると、ソースコードは以下のようになります。
<svg viewBox="0 0 100 100" width="100" height="100" fill="none">
<!-- 背景となる円 -->
<circle cx="50" cy="50" r="45" stroke="lightgray" stroke-width="10" />
<!-- 進捗を表す円 -->
<circle cx="50" cy="50" r="45" stroke="#FB7E51" stroke-width="10" stroke-dasharray="282.6 282.6" stroke-dashoffset="211.95" class="progressCircle" />
</svg>
<style>
.progressCircle {
position: relative;
transform-origin: 50% 50%;
transform: rotate(-90deg);
}
</style>
このように、stroke-dasharrayで破線を定義し、その破線をstroke-dashoffsetでどの位置から見せるかを指定することで、進捗率を表現することができます。
その他の進捗率はstroke-dashoffset
の値を変更することによって、任意の進捗率を表現することができます。
進捗率50%の場合
進捗率が50%の場合は、円の半分だけ実線で表示されるようにします。
円周の50%分をstroke-dashoffset
に指定します。
計算式:282.6 × 0.5 = 141.3px
進捗率75%の場合
進捗率が70%の場合は、円の4分の3だけ実線で表示されるようにします。
円周の25%分をstroke-dashoffset
に指定します。
計算式:282.6 × 0.25 = 84.78px
<!-- 進捗50% -->
<svg viewBox="0 0 100 100" width="100" height="100" fill="none">
<circle cx="50" cy="50" r="45" stroke="lightgray" stroke-width="10" />
<circle cx="50" cy="50" r="45" stroke="#FFE369" stroke-width="10" stroke-dasharray="282.6 282.6" stroke-dashoffset="141.3" class="progressCircle" />
</svg>
<!-- 進捗75% -->
<svg viewBox="0 0 100 100" width="100" height="100" fill="none">
<circle cx="50" cy="50" r="45" stroke="lightgray" stroke-width="10" />
<circle cx="50" cy="50" r="45" stroke="#7AEAD6" stroke-width="10" stroke-dasharray="282.6 282.6" stroke-dashoffset="70.65" class="progressCircle" />
</svg>
<style>
.progressCircle {
position: relative;
transform-origin: 50% 50%;
transform: rotate(-90deg);
}
</style>
まとめ
本記事では、SVGの基本構造を理解しながら、SVGとCSSで円形プログレスバーを表現する方法を解説しました。
ポイントを以下にまとめます:
<circle>
で円を重ねる
- 進捗の背景となる円
- 進捗を表す円
背景が不要な場合、1つの円でも表現できます
進捗はstroke-dasharray
とstroke-dashoffset
で表現する
- 円周の長さを
stroke-dasharray
に指定することで、円周の長さ分の実線と空白が繰り返される破線を定義する -
stroke-dashoffset
にどの位置から破線を見せるのか指定することで、任意の進捗率を表現できる
<ciecle>
はデフォルトで3時の位置から描画される点に注意
- 12時の位置から描画されるようにするには、
<svg>
や<circle>
を-90度回転させ表示させる必要がある