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

## はじめに
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390720/763f81bf-7304-b939-9016-abf393ffba93.png)

みなさんはちゃんとアクセシビリティを意識して開発できていますか？

必要なところに`role属性`を記述したり、tabキーでフォーカスが当たるようにしたりなど、意識しないといけないことも多いです。
そのため、完璧にやろうとするのは難しいと思います。

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

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

*※ アクセシビリティの基本については以下の記事をご参照ください。*

https://qiita.com/degudegu2510/items/dd072655880adbe3f58c

## アクセシビリティを意識したTooltipの仕様
:::note warn
重要な情報などは、Tooltipなどで隠すのではなく、明確で簡潔で常に表示されている情報として表示されているのがベストです。
:::

そのため、UI的に、余裕がある場合は、Tooltip以外の方法を取るのがいいと思います。
上記のことを理解・検討した上で、Tooltipは実装しましょう。

アクセシビリティを意識したTooltipの仕様は、以下の通りです。

1. Tooltipがフォーカスを受け取った時、マウスがhoverした時に表示される
1. Tooltipがフォーカスを失った時、マウスがhoverが外れた時に非表示になる
1. Tooltipが表示されている時、`Escapeキー`を押すと非表示になる
1. Tooltipとして表示される要素には、`role="tooltip"`を追加する
1. Tooltipを表示されるトリガーとなる要素に `aria-describedby="..."`を追加する



## 完成形
<p class="codepen" data-height="400" data-default-tab="result" data-slug-hash="jOQaOzP" data-editable="true" data-user="sp_degu" style="height: 400px; 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/jOQaOzP">
  Tooltip</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>

## アクセシビリティを意識したTooltipの実装方法
では早速、アクセシビリティを意識したTooltipを実装して行きます。

### 1. HTMLを実装する
```sample.html
<div class="tooltip-wrapper">
  <span id="tooltip-target" aria-describedby="tooltip" tabindex="0" class="material-symbols-outlined">
    help
  </span>
  <div role="tooltip" id="tooltip">使い方</div>
</div>
```

TooltipのHTMLでは、以下のことに意識しています。

1. Tooltipとして表示される要素に、`role="tooltip"`を追加する
    - 上記の例だと、`使い方`というTooltipを表示させたいので`使い方`のdivに`role="tooltip"`を記載しています。
1. Tooltipを表示されるトリガーとなる要素に `aria-describedby="..."`を追加する
    - Tooltipとして表示される要素に`id名`を追加し、同じ名前で、トリガーとなる要素に`aria-describedby`を追加します。
    - 上記の例だと、Tooltipとして表示される要素に`id="tooltip"`を記述し、トリガーとなる要素に`aria-describedby="tooltip"`を追加しています。


### 2. CSSを実装する

```sample.css
body {
  background-color: #212529;
  display: grid;
  height: calc(100vh - 40px);
  margin: 0;
  padding: 20px 0;
  place-items: center;
  width: 100vw;
}

.tooltip-wrapper {
  display: flex;
  position: relative;
}

#tooltip-target {
  font-variation-settings:
  'FILL' 0,
  'wght' 700,
  'GRAD' 200,
  'opsz' 40 ;
  color: #ffffff;
  font-size: 40px;
  height: 40px;
  cursor: pointer;
  width: 40px;
}

#tooltip {
  background-color: #ffffff;
  border-radius: 8px;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  padding: 2px 8px; 
  position: absolute;
  visibility: hidden;
  white-space: nowrap;
}

```
TooltipのCSSは、スタイル調整がメインのため、細かな解説は省略します。

1. `.tooltip-wrapper` に `position: relative;` を、`#tooltip` に `position: absolute;` 指定して、`.tooltip-wrapper` を基準にTooltipの場所を決められるようにしています。
2. `visibility: hidden;` を使って、Tooltipを非表示の状態にしておきます。
3. その他は、デザイン部分になります。

### 3. HoverとFocusでtooltipが表示するようにする

```sample.js
const target = document.getElementById("tooltip-target");
const tooltip = document.getElementById("tooltip");

function showTooltip() {
  tooltip.style.visibility = "visible";
}

function hiddenTooltip() {
  tooltip.style.visibility = "hidden";
}

// Mouse Over
target.onmouseover = showTooltip;

// Mouse Leave
target.onmouseleave = hiddenTooltip;

// Focus
target.onfocus = showTooltip;

// Blur
target.onblur = hiddenTooltip;
```

1. Tooltipを表示/非表示させるように `showTooltip()` と `hiddenTooltip()`の関数を作成します。
    + 処理は単純で、表示させる時に `tooltip.style.visibility = "visible";`、非表示させる時に `tooltip.style.visibility = "hidden";`で表示/非表示させています。
2. targetに`onmouseover`・`onfocus`したら、`showTooltip()`をつかい、`onmouseleave`・`onblur`したら、`hiddenTooltip`を使っています。


### 4. Escapeキーを押したら、Tooltipを非表示にさせる

```sample.js
const target = document.getElementById("tooltip-target");
const tooltip = document.getElementById("tooltip");
var isShow = false;

function showTooltip() {
  tooltip.style.visibility = "visible";
  isShow = true;
}

function hiddenTooltip() {
  tooltip.style.visibility = "hidden";
  isShow = false;
}

// Keydown
window.addEventListener("keydown", (event) => {
  if (event.key === "Escape" && isShow) {
    hiddenTooltip();
  }
});

// 省略...
```

1. Tooltipが表示されているかのフラグを見るための`isShow`を定義します。
    + `showTooltip()` の関数では、`isShow`を`true`にしています。
    + `hiddenTooltip()` の関数では、`isShow`を`false`にしています。
2. `keydown`のイベントを作成します。
    + `event.key === "Escape"`かつ、`isShow`がtrueの時に`hiddenTooltip()`が発火するようにします。


### 5. 完成

完成すると↓こんな感じになります。
<p class="codepen" data-height="400" data-default-tab="js,result" data-slug-hash="jOQaOzP" data-editable="true" data-user="sp_degu" style="height: 400px; 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/jOQaOzP">
  Tooltip</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>


## まとめ

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

ぜひこの記事をストックして、Tooltipを実装する時にこの記事・アクセシビリティについて思い出してもらえると嬉しいです。
他のUIのアクセシビリティについても解説していく予定なので、お楽しみにしていてください。

---

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

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

https://twitter.com/degudegu2510