BLOG ブログ


2025.03.04 TECH

WebアクセシビリティのガイドラインWCAG 「達成基準3.1.2 一部分の言語」のチェックを一部自動化

こんにちは、普段は自治体のWebサイト制作をしながらアクセシビリティに取り組んでいるtaichiです!

WCAG(Webアクセシビリティのガイドライン)の達成基準「3.1.2 一部分の言語」を知っていますか?

この基準では、例えば日本語のページの中に英語が混ざっている場合は、英語の箇所にlang属性の値をenで設定し、この要素は英語で書かれているよ!ということを伝えることが求められています。

実装した後にlang属性の設定漏れがないか確認するようにしていますが、日本語ではないテキストがどこにあるのかを探すのが大変だし、見逃してしまうかもしれないし、本当にちゃんと見れたか不安になってしまいます。

そこでチェック工程の一部だけでも自動化できないか考えました。

自動化するために生成AIにお願いした

今回は、確認すべき要素を見つける工程の自動化を目指しました。基準を達成しているかの判定や、達成していない場合の修正は含めません。

現在の案件では、lang属性が必要な箇所があるとすれば基本的には英語なので、英語を見つけたいです。英語はアルファベットで構成されているので、アルファベットを見つければいいと考えました。

生成AIには以下の指示を順番に出しました。

  1. Webページの中からアルファベットが含まれる文字列を持つ要素を取得するJavaScriptを書いてください。
  2. テキストノードを持つ親要素だけを抽出したいです。例えば、 button > span > TEXT_NODE という構造の場合はspan要素を取得し、button要素は取得しなくていいです。
  3. style要素とscript要素は除外したいです。
  4. 取得した要素からlang="en"が付与されているものは除外してください
  5. テキストノード版はこれで良さそうです さらにalt版の処理も追加してください altにアルファベットが含まれていてlang="en"が指定されていない要素も配列に混ぜてほしいです
  6. 全行に解説コメントを加えてください 処理が難しいところについては、別途丁寧で優しい解説をしてください

いくつかの調整をし、最終的に出来上がった処理が以下です。

// アルファベット(A-Z, a-z)を見つけるためのパターンを作成
const alphabetRegex = /[a-zA-Z]/;

// 見つかった要素を入れるための空の配列を用意
const elementsWithDirectTextOrAlt = [];

// ページ内のすべての要素(タグ)を取得
const allElements = document.querySelectorAll("*");

// 取得したすべての要素に対して、一つずつ処理を行う
allElements.forEach(element => {
    // style要素とscript要素は処理対象から除外する(これらは表示されないため)
    if (element.tagName === "STYLE" || element.tagName === "SCRIPT") {
        return;
    }

    // アルファベットを含むテキストが見つかったかどうかを記録するフラグ
    let hasDirectTextWithAlphabet = false;

    // 要素の直接の子ノード(テキストや他の要素)をすべてチェック
    element.childNodes.forEach(child => {
        // もし子ノードがテキストノードなら
        if (child.nodeType === Node.TEXT_NODE) {
            // テキストの前後の空白を削除
            const text = child.textContent.trim();
            // テキストの中にアルファベットが含まれているかチェック
            if (alphabetRegex.test(text)) {
                // アルファベットが見つかったらフラグを立てる
                hasDirectTextWithAlphabet = true;
            }
        }
    });

    // 要素のalt属性(画像の説明テキスト)を取得
    const altText = element.getAttribute("alt");
    // alt属性が存在し、かつその中にアルファベットが含まれているかチェック
    const hasAltWithAlphabet = altText && alphabetRegex.test(altText);

    // テキストノードまたはalt属性にアルファベットが見つかった場合
    if (hasDirectTextWithAlphabet || hasAltWithAlphabet) {
        // その要素を結果の配列に追加
        elementsWithDirectTextOrAlt.push(element);
    }
});

// 見つかったすべての要素をコンソールに表示
console.log(elementsWithDirectTextOrAlt);

使用手順

この処理をブラウザのコンソールに貼り付け実行すると、アルファベットを含むテキストを持つ要素のリストが出力されます。(ブックマークレットとして登録し、ワンクリックで実行できるようにすると便利です。)

コンソールのスクリーンショット: (4) [h1, p, p, p]

このリストは展開することができます。

コンソールのスクリーンショット: (4) [h1, p, p, p]。0: h1。1: p。2: p。3: p。length: 4。[[Prototype]]: Array(0)。

そして、それぞれの要素はクリックすると該当箇所にジャンプすることができます。テキスト内容とlang属性の有無を確認し、必要であればlang属性を追加します。これを1つ1つ見ていきます。

<h1>North Detail</h1>

この方法であれば目視で確認せずに済むし、見逃さないし、不安も減ります。さらに、非表示の要素も拾ってくれます。特定の条件時のみ表示される要素は目視では気付きづらくなりますが、この方法であればDOMにさえあれば気付くことができます。

これでlang属性のチェックを一部自動化することができました。

生成AIでアクセシビリティに使う時間を作り出したい

こんなことができたらいいなと思っていたことでも、以前まではすぐには作れませんでした。でも今は生成AIがあって数分後にはできるようになったりしてすごいなあって思ってます。

自動化は精度も高まるし、時短もできます。時短できれば、さらに取り組みたかったことに使える時間が増やせます。例えば、アクセシビリティにもっと取り組むことができるようになります。生成AIも活用しながらアクセシビリティ向上に取り組んでいきたいです。

参考


一覧に戻る


LATEST ARTICLE 最新の記事

CATEGORY カテゴリー