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では、React経験が豊富なフロントエンドエンジニアを募集しています

弊社ではReactの知見で事業作りに貢献したいフロントエンドエンジニアを募集しています。大きな制作会社や事業会社とはひと味もふた味も違うGaji-Laboを味わいに来ませんか?

もちろん、一緒にお仕事をしてくださるパートナーさんも随時募集中です。まずはお気軽に声をかけてください。お仕事お問い合わせや採用への応募、共に大歓迎です!

求人応募してみる!

投稿者 Yokota Tomoko

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