判定の仕組み
FigmaNaviは、AIや機械学習を一切使用していません。すべての判定はWCAG(Web Content Accessibility Guidelines)の基準に基づき、数学的な計算とルールベースのロジックで行われます。
透明性を重視し、各チェック項目がどのように判定されているかを完全に公開しています。
検出する問題
| チェック項目 | 判定基準 | 重大度 |
|---|---|---|
| コントラスト不足 | WCAG 2.1 コントラスト比 | Error |
| Alt未設定 | 画像のpluginData確認 | Warning |
| タッチターゲット小 | 48×48px未満 | Warning |
| フォーカス順序未設定 | pluginData確認 | Info |
ロービジョン(弱視)のユーザーや、明るい屋外でスマートフォンを使用する場合でもテキストを読めるように、文字色と背景色の明度差を検証します。コントラストが不十分だと、多くのユーザーにとって読みづらいUIになります。
相対輝度の計算
コントラスト比を求めるために、まず各色の相対輝度(Relative Luminance)を計算します。
sRGB値(0-1の範囲)を線形値に変換する処理:
function sRGBtoLinear(value: number): number { // value は 0-1 の範囲 return value <= 0.03928 ? value / 12.92 : Math.pow((value + 0.055) / 1.055, 2.4); }
コントラスト比の計算
2つの色の相対輝度から、コントラスト比を算出します。
function getContrastRatio(fg: RGBColor, bg: RGBColor): number { const l1 = getRelativeLuminance(fg); const l2 = getRelativeLuminance(bg); const lighter = Math.max(l1, l2); const darker = Math.min(l1, l2); return (lighter + 0.05) / (darker + 0.05); }
判定基準
| WCAGレベル | 通常テキスト | 大きいテキスト |
|---|---|---|
| AA | 4.5:1 以上 | 3:1 以上 |
| AAA | 7:1 以上 | 4.5:1 以上 |
背景色の検出
テキストノードの背景色は、親要素を再帰的に辿って最初に見つかったソリッドフィルを使用します。
function findBackgroundColor(node: SceneNode): RGBColor | null { let current = node.parent; while (current) { if ('fills' in current) { const solidFill = fills.find( fill => fill.type === 'SOLID' && fill.visible !== false ); if (solidFill) return solidFill.color; } current = current.parent; } // デフォルトは白 return { r: 1, g: 1, b: 1 }; }
スクリーンリーダーを使用する視覚障害のあるユーザーに、画像の内容を伝えるための代替テキストが設定されているかを検証します。Altテキストがないと、画像が何を表しているのか全く伝わりません。
画像ノードの検出
Figmaでは、画像はノードのfillsプロパティ内にIMAGEタイプとして格納されます。
const imageNodes = targetNodes.filter((node) => { if ('fills' in node) { const fills = node.fills; if (Array.isArray(fills)) { return fills.some((fill) => fill.type === 'IMAGE'); } } return false; });
判定ロジック
各画像ノードに対して、pluginDataを確認します。
const ALT_TEXT_KEY = 'a11y_alt_text'; const DECORATIVE_KEY = 'a11y_is_decorative'; for (const imageNode of imageNodes) { const altText = imageNode.getPluginData(ALT_TEXT_KEY); const isDecorative = imageNode.getPluginData(DECORATIVE_KEY); // Altテキストがなく、装飾画像でもない場合は警告 if (!altText && isDecorative !== 'true') { issues.push({ issueType: 'missingAlt', severity: 'warning' }); } }
装飾目的の画像はisDecorative: trueを設定することで、警告をスキップできます。
運動機能に障害のあるユーザーや、指が太いユーザー、揺れる電車内でスマートフォンを操作するユーザーでも正確にタップできるよう、ボタンやリンクのサイズを検証します。小さすぎるターゲットは誤タップの原因になります。
最小サイズ基準
タッチ操作を行うインタラクティブ要素は、最小48×48pxのサイズが推奨されます。
インタラクティブ要素の検出
ノード名に特定のキーワードが含まれるか、コンポーネントインスタンスかどうかで判定します。
const interactiveElements = targetNodes.filter((node) => { const name = node.name.toLowerCase(); return ( name.includes('button') || name.includes('btn') || name.includes('link') || name.includes('input') || name.includes('checkbox') || name.includes('radio') || name.includes('select') || name.includes('tab') || node.type === 'INSTANCE' ); });
サイズ判定
const MIN_TOUCH_TARGET = 48; if (element.width < MIN_TOUCH_TARGET || element.height < MIN_TOUCH_TARGET) { issues.push({ issueType: 'smallTouchTarget', severity: 'warning', message: `${element.width}×${element.height}px(推奨: 48×48px)` }); }
キーボードのみで操作するユーザーが、Tabキーで要素間を移動する際の順序を検証します。視覚的なレイアウトと操作順序が一致しないと、ユーザーは混乱し、目的の要素にたどり着けなくなります。
フォーカス順序とは
キーボードユーザーがTabキーで要素間を移動する際の順序です。論理的で予測可能な順序が重要です。
判定ロジック
インタラクティブ要素にpluginDataでフォーカス順序が設定されているかを確認します。
const FOCUS_ORDER_KEY = 'a11y_focus_order'; for (const element of interactiveElements) { const focusOrder = element.getPluginData(FOCUS_ORDER_KEY); if (!focusOrder) { issues.push({ issueType: 'noFocusOrder', severity: 'info', message: 'フォーカス順序が設定されていません' }); } }
フォーカス順序は「情報」レベルの問題として報告されます。視覚的な順序と一致していれば、明示的な設定は必須ではありません。
参考資料
FigmaNaviの判定基準は以下のガイドラインに基づいています。