【アクセシビリティ】アクセシビリティを意識したアラートの作り方

## はじめに
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390720/c54f3f5b-9c02-9f08-6332-a9c614c0f0eb.png)
みなさんアクセシビリティを意識して開発できていますか？

必要なところに`role属性`を記述したり、`tabキー`でフォーカスができるようにしたりなど、意識しないといけないことも多いです。
そのため、アクセシビリティを完璧にやろうとするのは一苦労です。

ただ、コンポーネントごとに区切って、アクセシビリティを理解しておけば、実装するタイミングに思い出しやすく、アクセシビリティも意識しやすいと思います。

そのため、この記事では「**アラート**」に焦点を当てて、アクセシビリティを意識したアラートの実装方法とアラートで意識した方がいいアクセシビリティを解説しようと思います。

## アクセシビリティを意識したアラートの仕様
### ⚪︎ アラートとは？
アラートは、ユーザーのタスクを中断することなく、ユーザーの注意を引く方法で短く重要なメッセージを表示する要素です。

動的にレンダリングされたアラートは、スクリーンリーダーによって自動的に読み上げられ、一部のオペレーティングシステムではアラート音が鳴る場合があります。
現時点では、ページの読み込みが完了する前に、スクリーンリーダーはページ上に存在するアラートをユーザーに通知しないことに注意することが重要です。

アラートは、以下の3点に注意して設計することが重要です。

+ **キーボードフォーカスに影響を与えないこと**
  + ユーザーの作業を妨げることなく、重要で一刻を争う情報を提供することが目的
+ **自動的に消えないように設計すること**
  + WCAG2.0の成功基準2.2.3「タイミング非依存」を満たすため
    + 制限時間のあるインタラクションを要求するコンテンツの提供を最小限にすること
+ **頻繁な中断はさせないこと**
  + WCAG2.0の成功基準2.2.4「割り込み」を満たすため
    + 緊急を要する割り込みを除いて、利用者が延期、抑制できること

### ⚪︎ キーボードインタラクション
キーボード操作は必要ありません。

### ⚪︎ WAI-ARIA の役割、状態、プロパティ
+ `role="alert"`を設定する

## アクセシビリティを意識したアラートの完成形
<p class="codepen" data-height="500" data-default-tab="result" data-slug-hash="zYyQoRe" data-editable="true" data-user="sp_degu" style="height: 500px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/sp_degu/pen/zYyQoRe">
  Accordion Accessibility</a> by でぐぅー | Qiita (<a href="https://codepen.io/sp_degu">@sp_degu</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## アクセシビリティを意識したアラートの作り方
### 1. HTMLを実装する
```sample.html
<button type="button" id="alert-trigger">
  Alertを表示する
</button>
<div id="alert" role="alert"></div>

<script type="text/template" id="alert-template">
  <span class="material-symbols-outlined">warning</span>
  <p>メールアドレスの承認が完了していません</p>
  <button id="alert-button">閉じる</button>
</script>
```
### ２. CSSを実装する
```sample.css
body {
  background-color: #212529;
  color: #fff;
  display: grid;
  gap: 24px;
  height: calc(100vh - 40px);
  margin: 0;
  padding: 20px 0;
  align-content: center;
  justify-items: center;
  width: 100vw;
}

button {
  align-items: center;
  background: none;
  border: none;
  color: #ffffff;
  cursor: pointer;
  display: flex;
}

#alert-trigger {
  background: linear-gradient(0deg, rgba(94, 94, 94, 0.18) 0%, rgba(94, 94, 94, 0.18) 100%), rgba(255, 255, 255, 0.06);
  background-blend-mode: color-dodge, lighten;
  border-radius: 100px;
  font-size: 16px;
  font-weight: bold;
  justify-content: center;
  width: 200px;
  padding: 8px 16px;
  position: relative;
}

#alert-trigger::before {
  background: linear-gradient(135deg, rgb(255 255 255 / .4) 0, rgb(255 255 255 / 0) 40%, rgb(255 255 255 / 0) 60%, rgb(255 255 255 / .1) 100%);
  border: 1.4px solid transparent;
  border-radius: 24px;
  content: "";
  inset: 0;
  position: absolute;
  -webkit-mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0) border-box;
  -webkit-mask-composite: destination-out;
  mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0) border-box;
  mask-composite: exclude;
  z-index: -1;
}

#alert-trigger:hover {
  background: radial-gradient(101.08% 100% at 50% 100%, rgba(94, 94, 94, 0.32) 0%, rgba(94, 94, 94, 0.00) 73.85%), radial-gradient(100.02% 100% at 50% 100%, rgba(255, 255, 255, 0.12) 0%, rgba(255, 255, 255, 0.00) 68.75%), linear-gradient(0deg, rgba(94, 94, 94, 0.18) 0%, rgba(94, 94, 94, 0.18) 100%), rgba(255, 255, 255, 0.06);
  background-blend-mode: color-dodge, normal, color-dodge, lighten;
  box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.10);
}

#alert {
  align-items: center;
  background-color: rgb(128 128 128 / .3);
  border-radius: 100px;
  display: flex;
  gap: 8px;
  padding: 8px;
  position: relative;
  background-blend-mode: luminosity;
  backdrop-filter: blur(50px);
}

#alert:empty {
  display: none;
}

#alert::before {
  background: linear-gradient(135deg, rgb(255 255 255 / .4) 0, rgb(255 255 255 / 0) 40%, rgb(255 255 255 / 0) 60%, rgb(255 255 255 / .1) 100%);
  border: 1.4px solid transparent;
  border-radius: 100px;
  content: "";
  inset: 0;
  position: absolute;
  -webkit-mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0) border-box;
  -webkit-mask-composite: destination-out;
  mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0) border-box;
  mask-composite: exclude;
  z-index: -1;
}

.material-symbols-outlined {
  color: #FFD60A;
  padding: 8px;
}

p {
  font-weight: 600;
  margin: 0;
}

#alert-button {
  background: linear-gradient(0deg, rgba(94, 94, 94, 0.18) 0%, rgba(94, 94, 94, 0.18) 100%), rgba(255, 255, 255, 0.07);
  background-blend-mode: color-dodge, normal;
  border-radius: 100px;
  font-weight: 600;
  padding: 8px 16px;
  margin-left: 8px;
}

#alert-button:hover {
  background: radial-gradient(101.08% 100% at 50% 100%, rgba(94, 94, 94, 0.32) 0%, rgba(94, 94, 94, 0.00) 73.85%), radial-gradient(100.02% 100% at 50% 100%, rgba(255, 255, 255, 0.12) 0%, rgba(255, 255, 255, 0.00) 68.75%), linear-gradient(0deg, rgba(94, 94, 94, 0.18) 0%, rgba(94, 94, 94, 0.18) 100%), rgba(255, 255, 255, 0.06);
  background-blend-mode: color-dodge, normal, color-dodge, lighten;
}
```

### 3. JavaScriptを実装する
```sample.js
window.addEventListener('load', function () {
  var addButton = document.getElementById('alert-trigger');
  addButton.addEventListener('click', addAlert);
});

function addAlert() {
  var alert = document.getElementById('alert');
  var template = document.getElementById('alert-template').innerHTML;

  alert.innerHTML = template;
  
  var removeButton = document.getElementById('alert-button');
  removeButton.addEventListener('click', removeAlert);
}

function removeAlert() {
  var alert = document.getElementById('alert');
  alert.innerHTML = ""
}
```

## まとめ
この記事では、「**アラート**」に焦点を当てて、アクセシビリティを意識したアラートの実装方法とアラートで意識した方がいいアクセシビリティを解説しました。

ぜひこの記事をストックして、アラートを実装する時にアクセシビリティについて思い出してもらえると嬉しいです。

Advent Calendar 2023では、他のコンポーネントにも焦点を当てて、アクセシビリティについても解説しているので、ぜひ購読していてください。

https://qiita.com/advent-calendar/2023/degudegu2510

---

最後まで読んでくださってありがとうございます！

普段はデザインやフロントエンドを中心にQiitaに記事を投稿しているので、ぜひQiitaのフォローとX(Twitter)のフォローをお願いします。

https://twitter.com/degudegu2510