【アクセシビリティ】　チェックボックスを作ってみた

こんにちは
新卒1年目の小川です。

今回は、アクセシビリティに対応したチェックボックスの作成方法についてまとめていきたいと思います。

以下では、HTML、CSS、JavaScriptの各要素を使って、どのようにアクセシビリティを向上させるかを説明し、具体的なコードを例として紹介します。

# HTMLでのアクセシビリティ対応
まず、チェックボックスの基本となるHTML構造を作成します。
今回はaria-checked 属性を使って作成してみました。
この属性は、チェックボックスが選択されているかどうかをスクリーンリーダーに伝えることができます。

```:html
<div class="checkbox-list">
    <div class="checkbox-container"
         role="checkbox"
         aria-checked="false"
         tabindex="0"
         aria-labelledby="checkbox1-label"
         aria-live="polite">
        <span aria-hidden="true"></span>
        <p id="checkbox1-label">チェック１</p>
    </div>
    <div class="checkbox-container"
         role="checkbox"
         aria-checked="false"
         tabindex="0"
         aria-labelledby="checkbox2-label"
         aria-live="polite">
        <span aria-hidden="true"></span>
        <p id="checkbox2-label">チェック２</p>
    </div>
    <div class="checkbox-container"
         role="checkbox"
         aria-checked="false"
         tabindex="0"
         aria-labelledby="checkbox3-label"
         aria-live="polite">
        <span aria-hidden="true"></span>
        <p id="checkbox3-label">チェック３</p>
    </div>
    <div class="checkbox-container"
         role="checkbox"
         aria-checked="false"
         tabindex="0"
         aria-labelledby="checkbox4-label"
         aria-live="polite">
        <span aria-hidden="true"></span>
        <p id="checkbox4-label">チェック４</p>
    </div>
</div>
```

# アクセシビリティ対応のポイント：

* **role="checkbox"**: チェックボックスであることを明示します。
* **aria-checked="false"**: チェックボックスが未選択であることを示します。選択状態が変わるたびにこの属性の値を更新します。
* **aria-labelledby**: チェックボックスのラベルに対する参照を設定します。
* **aria-live="polite"**: 状態が変更された際に、スクリーンリーダーに通知します。

# CSSでのスタイリング
次に、チェックボックスのデザインをCSSで整えます。ここでは、選択された状態と非選択状態の違いを視覚的に分かりやすくするためのスタイリングを行います。

```:css
body {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
    background-color: #f0f4f8;
}

.checkbox-list {
    display: flex;
    flex-direction: column;
    width: 200px;
}

.checkbox-container {
    display: flex;
    align-items: center;
    cursor: pointer;
    background-color: #e2e8f0;
    padding: 0.3rem;
    margin-bottom: 0.5rem;
    border-radius: 0.5rem;
    font-size: 1.4rem;
    font-weight: bold;
    transition: background-color 0.4s ease;
    position: relative;
}

.checkbox-container:hover {
    background-color: #cbd5e0;
}

.checkbox-container:focus {
    outline: 3px solid #ff6347; /* フォーカスリングの色 */
    box-shadow: 0 0 0 2px rgba(255, 99, 71, 0.5); /* 視覚的な強調 */
}

.checkbox-container span {
    width: 1.5rem;
    height: 1.5rem;
    margin-right: 1rem;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 2px solid black;
    border-radius: 0.25rem;
    background-color: #fff;
    transition: background-color 0.4s ease;
    position: relative;
}

.checkbox-container[aria-checked="true"] span {
    background-color: #3959cc;
    border-color: black;
}

.checkbox-container[aria-checked="true"] span::before {
    content: '';
    position: absolute;
    left: 0.35rem;
    top: 0.1rem;
    width: 0.5rem;
    height: 0.9rem;
    border: solid #fff;
    border-width: 0 0.2rem 0.2rem 0;
    transform: rotate(45deg);
    opacity: 1;
}

.checkbox-container span::before {
    content: '';
    position: absolute;
    left: 0.35rem;
    top: 0.1rem;
    width: 0.5rem;
    height: 0.9rem;
    border: solid #ccc;
    border-width: 0 0.2rem 0.2rem 0;
    transform: rotate(45deg);
    opacity: 0;
    transition: opacity 0.2s ease;
}
```

# アクセシビリティ対応のポイント：
* **:focus スタイル:** キーボード操作を行った際にフォーカスがわかりやすくなるように、フォーカスリングとボックスシャドウを追加しています。
* **視覚的フィードバック**: チェック状態の視覚的な変更を行い、ユーザーがチェックボックスを選択したことを明確にします。

# JavaScriptでの動作制御
最後に、チェックボックスの状態を動的に変更するJavaScriptを追加します。ここでは、クリックイベントやキーボード操作（スペースキー）による状態変更を処理します。

```:javascript
document.addEventListener('DOMContentLoaded', function() {
    const checkboxes = document.querySelectorAll('.checkbox-container');
    
    function toggleCheckbox(checkbox) {
        const isChecked = checkbox.getAttribute('aria-checked') === 'true';
        if (isChecked) {
            checkbox.setAttribute('aria-checked', 'false');
        } else {
            checkbox.setAttribute('aria-checked', 'true');
        }
    }

    checkboxes.forEach(checkbox => {
        checkbox.addEventListener('click', function() {
            toggleCheckbox(this);
        });

        checkbox.addEventListener('keydown', function(event) {
            if (event.key === ' ') {
                event.preventDefault(); // Prevent default action
            }
        });

        checkbox.addEventListener('keyup', function(event) {
            if (event.key === ' ') {
                toggleCheckbox(this);
                event.stopPropagation();
            }
        });
    });
});
```

# アクセシビリティ対応のポイント：
* **キーボード操作の対応**: スペースキーでチェックボックスの状態を切り替えるため、keydown と keyup イベントを使って、キーボードだけで操作できるようにしています。
* **状態変更のトリガー**: チェックボックスをクリックしたり、キーボードで操作したりすると、aria-*checked の値が適切に更新され、状態が反映されます。

# 最後に
今回はアクセシビリティに対応したチェックボックスの作成方法についてまとめました。
アクセシビリティを勉強し始めて間もないので、不十分な点もあるかもしれませんが、一つでも参考になることがあれば幸いです。