SVGの管理方法でカスタムコンポーネント化を選んだ理由


こんにちは。Gaji-Labo 横田です。今回は SVG の管理方法について議論したことをまとめます。

前提

  • 開発環境は Next.js/React
  • 管理したい SVG 画像の数は多く、開発メンバーも複数いるため、一元管理で開発コストを下げたいという目的があります
  • 運用のしやすさも重要です
  • アクセシビリティとして WCAG 2.1 の AA(ダブルA)に配慮した対応をします

いくつかの選択肢

たとえばロゴやアイコンなど SVG 画像をどう指定するかは色々な方法があります。よくある方法としては以下が挙げられます。

  1. img 要素として直接読み込む
  2. インラインで直接指定する
  3. SVGR のようなライブラリを使用する
  4. ライブラリを使用せずにカスタムコンポーネント化する

今回は、SVG の fill や path などをカスタマイズしたいケースを含むので1.は除外、コンポーネントとして汎用的に使い回したいので2.も除外しました。

どの管理方法がプロジェクトにとって適切か

3のライブラリ使用か、4のカスタムコンポーネント化というところで双方にいくつかの意見がでました。

  • SVGR は最適化を自動で行ってくれるので数の多さに対応しやすい
  • SVGR は React コンポーネントに変換してくれる
  • カスタムコンポーネント化は手動で最適化をする必要があるが、カスタマイズはしやすい
  • 運用を考慮すると依存ライブラリは少ない方がよい

こういったメリットデメリットを踏まえつつ、前提条件が決め手となってきます。

アクセシビリティとして WCAG 2.1 の AA(ダブルA)に配慮した対応をする

スクリーンリーダーへの対応として、SVG が文書構造の中で情報として意味を持たない装飾であれば、aria-hidden を指定して読み上げをスキップさせたいです。
また情報として意味を持たせる SVG アイコンなどであれば、aria-label で適切な説明テキストを挿入し、かつ同時に role="img" を指定して意味のある画像であることを明示させ、読み上げさせたいです。SVG に title 要素で説明テキストを挿入する方法もありますが、ホバー時に tooltip が表示されてしまうことがあるため、コンポーネントとして使い回すことを想定すると aria-label を使いたい。

これらの要件を満たすために、カスタムコンポーネント化を選択しました。最適化を個別に行う必要はありますが、aria 属性の指定など柔軟な実装が可能なためです。

以下、実装したカスタムコンポーネントの一部を紹介します。

export const convertProps = (props: React.SVGAttributes<SVGElement>) => {
  return {
    ...props,
    // aria-label を指定すれば role="img" を自動で付与
    role: props['aria-label'] ? 'img' : undefined,
    // aria-label を指定しない時は aria-hidden を自動で付与
    'aria-hidden': !props['aria-label'],
  };
};

SVG ごとに .tsx ファイルを作成し svg.ts を import します。

import { convertProps } from '../svg';

export const HogeIcon = () => (
  <svg {...convertProps} viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'>
 ...
  </svg>
);

これで個々の SVG ごとにサイズや色などのバリエーションを props で渡すこともできます。

他のコンポーネントで SVG を使う時は、以下のように使います。

import { HogeIcon } from '@/components/ui/Svg/Icon';
...
// 説明テキストが必要な SVG アイコン
<HogeIcon width='10' height='10' aria-label='説明テキスト' />

終わりに

今回は SVG をカスタムコンポーネント化する管理方法を選択しましたが、プロジェクトの要件次第ではもちろん他の方法を選択することもあります。
どの管理方法にもメリットデメリットがあるので、Gaji-Labo ではひとつの技術や方法にこだわるのではなく、ヒアリングした内容をもとに技術要件やフェーズ、要望に合わせ、都度、最適な選択肢を提案したり議論を深めることを大事にしています。
そのためにはまず複数の選択肢を持つための知見をためておくことも重要で、メンバーひとりひとりが知識をアップデートしたり、アップデートした知見を共有することを心がけています。

Gaji-Labo フロントエンドエンジニア向けご案内資料

Gaji-Labo は Next.js 開発の実績と知見があります

フロントエンド開発の専門家である私たちが御社の開発チームに入ることで、バックエンドも含めた全体の開発効率が上がります。

「既存のサイトを Next.js に移行したい」
「人手が足りず信頼できるエンジニアを探している」
「自分たちで手を付けてみたがいまいち上手くいかない」

フロントエンド開発に関わるお困りごとがあれば、まずは一度お気軽に Gaji-Labo にご相談ください。

オンラインでのヒアリングとフルリモートでのプロセス支援にも対応しています。

フロントエンドの相談をする!

投稿者 Yokota Tomoko

運用やアクセシビリティに配慮したHTML/CSSの設計やコンポーネント作成、スタイルガイドの構築、コードレビュー、組み込み、要件の整理、社内進行管理、顧客とのコミュニケーションまで、ジョインしたチームを前に進めるためにあれこれ担当しています。子育てと仕事のバランスを楽しめるよう、日々模索しています。