ウェブ開発において、データ可視化は必須の要素です。特に円グラフは比率を直感的に示すツールとして頻繁に使用されます。しかし、多くの開発者が手軽さから重いJavaScriptチャートライブラリを導入しています。これはページの読み込み速度に悪影響を与えるだけでなく、アクセシビリティの観点でも問題となる可能性があります。この記事では、CSSのconic-gradient()と最新のCSS関数を活用し、セマンティックなマークアップとアクセシビリティの両方を満たす円グラフを作成する方法を段階的に詳しく説明します。基礎となる考え方は参考資料でご確認いただけます。

A colorful pie chart displayed on a web developer's screen with code editor in the background IT Technology Image

セマンティックなHTML構造の設計

まず最初に、スクリーンリーダーが理解できる意味論的なマークアップを構築する必要があります。figureulを活用してデータを構造化します。

<figure class="pie-chart">
  <figcaption>先月販売されたキャンディ</figcaption>
  <ul>
    <li data-percentage="30" data-color="#4A90E2">
      <strong>チョコレート</strong>
    </li>
    <li data-percentage="25" data-color="#50E3C2">
      <strong>グミ</strong>
    </li>
    <li data-percentage="20" data-color="#F5A623">
      <strong>ハードキャンディ</strong>
    </li>
    <li data-percentage="25" data-color="#BD10E0">
      <strong>バブルガム</strong>
    </li>
  </ul>
</figure>

CSSで各スライスを描画

li要素は、自身のdata-percentagedata-color属性を読み取り、独自のスライスを描画します。最新のattr()関数を使用して、HTML属性をCSS変数として解析します。

.pie-chart {
  display: grid;
  place-items: center;
}

.pie-chart li {
  --radius: 20vmin;
  --percentage: calc(attr(data-percentage number) * 1%);
  --bg-color: attr(data-color color);
  --weighing: calc(attr(data-percentage number) / 100);
  
  width: calc(var(--radius) * 2);
  aspect-ratio: 1;
  border-radius: 50%;
  grid-row: 1;
  grid-column: 1;
  
  /* conic-gradientでスライスを生成 */
  background: conic-gradient(
    from var(--offset, 0deg),
    var(--bg-color) 0% var(--percentage),
    transparent var(--percentage) 100%
  );
}

JavaScriptによる累積値の計算

CSSだけでは、前のスライスのパーセンテージを累積することができません。簡単なJavaScriptで--accum変数を計算し、各スライスの開始角度を設定します。

const pieChartItems = document.querySelectorAll('.pie-chart li');
let accum = 0;

pieChartItems.forEach((item) => {
  item.style.setProperty('--accum', accum);
  accum += parseFloat(item.getAttribute('data-percentage'));
  item.style.setProperty('--offset', `${accum * 3.6}deg`);
});

Close-up view of a semantic HTML structure for a pie chart with data attributes highlighted Software Concept Art

ラベルの円形配置

cos()sin()のCSS関数を利用して、各スライスの中点にラベルを配置します。これにより、数学的な座標計算をCSS内で直接可能にします。

.pie-chart li {
  /* ... 既存のスタイル ... */
  
  /* ラベル位置の計算 */
  --theta: calc((360deg * var(--weighing)) / 2 + var(--offset) - 90deg);
  --gap: 4rem;
  --pos-x: calc(cos(var(--theta)) * (var(--radius) + var(--gap)));
  --pos-y: calc(sin(var(--theta)) * (var(--radius) + var(--gap)));
  
  display: grid;
  place-items: center;
}

.pie-chart li strong,
.pie-chart li::after {
  grid-row: 1;
  grid-column: 1;
  transform: translateX(var(--pos-x)) translateY(var(--pos-y));
}

/* パーセント表示 */
.pie-chart li::after {
  content: attr(data-percentage) '%';
  --pos-y: calc(sin(var(--theta)) * (var(--radius) + var(--gap)) + 1lh);
}

注意点と制限

この方法は純粋なCSSに近いですが、スライスの累積角度を計算するために最小限のJavaScriptが依然として必要です。また、cos()sin()関数のサポートはすべてのブラウザで完了していません。代替案としてCSSのtransform: rotate()を組み合わせることもできますが、計算がより複雑になります。色はdata-color属性でハードコーディングする必要があり、動的な色生成にはcolor-mix()関数または追加のJavaScriptが必要です。

Diagram showing the overlay of multiple conic-gradient slices to form a complete pie chart Development Concept Image

次の学習ステップ

この基本的な実装を基に、さまざまな高度な機能を追加してみることができます。

  1. 生データからのパーセンテージ自動計算: data-value属性に生の値を入力すると、CSSまたはJSが合計に対するパーセンテージを自動計算するように改良します。
  2. さまざまなチャートタイプへの適用: 同じセマンティックマークアップの原理を応用して、棒グラフやドーナツグラフを実装してみてください。
  3. インタラクションの追加: :hover時にスライスが強調表示されたりツールチップが表示される効果を適用すると、UXが大幅に向上します。
  4. CSS Houdiniの検討: 将来的にCSS Properties and Values APIのサポートが広まれば、JavaScriptなしでCSS内で状態を累積できるようになるかもしれません。

アクセシビリティとパフォーマンスを考慮したデータ可視化は、現代のウェブ開発における核心的なスキルです。このチュートリアルが、重いライブラリへの依存から脱却し、基本技術の力で問題を解決する一助となれば幸いです。