なんとなくで書かないで！HTML5を書く時に気にしてみたいタグごとのお約束

## はじめに

この記事は [クラウドワークスアドベントカレンダー2019](https://qiita.com/advent-calendar/2019/crowdworks) 16日目の記事です。

こんにちは！本日25回目の誕生日を迎えたアクセシビリティ向上隊長 [みーた](https://twitter.com/earlgrayMK)です。
昨日は同じチームの[@yamanoku](https://twitter.com/yamanoku)さんによる「[みんなに知ってもらいたいデザインシステムのこと](https://note.com/yamanoku/n/n8acc38df2902)」でした。
文中で紹介されていた「悲劇的なデザイン」は私もオススメします:)

私は今回、普段みなさんがHTMLを書く時に、よく使うタグごとで**ちょっと気をつけてみてもらいたい！と思う点**をまとめてみました。
初学者ではありますが、正しくHTMLを理解してもらいたいって気持ちがあるので、マサカリは怖くない程度に投げていただいて、みんなで知識を共有していきたいです。

## 👻 真冬の怪談
突然ですがちょっと怖い話を...

先日、とある画面を改修しようと思って、今どんな感じにスタイル当たってるんだろうと本番環境を見てみたんですよ。
カードタイプの情報が並んでるUIだったんですけどね。
Chrome DevToolsでコードを見てみたら...

<img width="460" alt="正しいHTML構造ではないコードのスクリーンショット1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42808/24427112-5018-f60f-83f6-d8ade35946a4.png">

**ぎぃやぁぁぁああぁぁぁぁぁぁあぁぁぁ😱😱😱**
別日、他の画面にも。

<img width="229" alt="正しいHTML構造ではないコードのスクリーンショット2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42808/d4c02d09-9b53-625f-eccb-0b4e9d8abc25.png">

**あびぃやぁぁぁあぁぁああぁぁぁあぁぁぁ🤪🤪**

鳥肌立ちまくりでした。
おわかりいただけただろうか...？

- `<ul>`直下に`<li>`以外のタグがいる
- `<section>`内にhタグがいない

セマンティックなHTML構造を意識したい身としては見たくない形です。

とはいえ、全員がこの違和感に気付かないのも現状です。
HTMLも意外とルールが多いので分かりづらいですよね。

でもセマンティックにHTML構造が書けると

- マシンリーダブルになり正しい情報を伝えることが出来る
    - SEOにも強いデータとなる
    - スクリーンリーダーで正しく読ませることが出来る
- CSSが万一当たらないときでも、ブラウザ毎に定義されているuser agent stylesheetが当たるため読みやすい
- きちんと構造化されたHTMLは機械だけでなく人間が読んでも分かりやすいのでメンテナンスしやすい

などの利点があります。
セマンティックなことの重要性はGoogle Developersの[セマンティクスとコンテンツのナビゲーション](https://developers.google.com/web/fundamentals/accessibility/semantics-builtin/navigating-content?hl=ja)なども合わせてご覧ください。

>"The power of the Web is in its universality. Access by everyone regardless of disability is an essential aspect."
「Webの力は、その普遍性にあります。障害に関係なく、誰でもアクセスできることが不可欠です。」
-- Tim Berners-Lee
*[World Wide Web Consortium Launches International Program Office for Web Accessibility Initiative](https://www.w3.org/Press/IPO-announce)*


## HTMLタグの基礎知識
この記事は[MDN web docs](https://developer.mozilla.org/ja/docs/Web/HTML/Reference)さんを参考に書いていきますので、ご了承ください。

まずHTMLの各種タグには

- コンテンツカテゴリ
- 許可されている内容
- タグの省略
- 許可されている親要素 
- 許可されている ARIA ロール
- DOM インターフェイス 

というものが決まっています。
その中でも気をつけたいのが**「許可されている内容(子要素)」**です。

例えば`<ul>`であれば
>許可されている内容
 0個以上の `<li>` 要素。その子孫としてさらに `<ol>` 要素や `<ul>` 要素を配置することも可能 
 *[\<ul>: 順序なしリスト要素](https://developer.mozilla.org/ja/docs/Web/HTML/Element/ul)*

と、**タグの種類によって子要素に指定できるタグが決まっています。**
これが崩れると[アクセシビリティツリー](https://developers.google.com/web/fundamentals/accessibility/semantics-builtin/the-accessibility-tree?hl=ja)などに影響が出るため、セマンティックな状態が壊れ、正しい情報をすべての人に届けられなくなってしまいます。

他にも各種タグには「これを書いておくといい」とか「こういう風に書いちゃダメ」というポイントがありますので、見ていきましょう。

## aタグ
誰もが一度は書いたことのあるハイパーリンクを生成するためのタグ。
よく見かけるBadパターンはこちら

```html:Bad
<!-- jsのonclickをaタグにつける -->
<a href="#" onclick="alert('fugafuga')">hogehoge</a>

<!-- aタグの中にaタグ -->
<a>
  <div>piyopiyo</div>
  <a href="https://hogehoge">hogehoge</a>
</a>
```

### 🙅 jsのonclickをaタグにつける
リンクは適切な URL を使用して**移動するためだけに使用するべき**とされています。
クリックした時になにかjsを発火させたいときは `<button>` を使うことを推奨します。
これ、どのサイトもめちゃくちゃ多いので滅ぼしたい！！！

>これらの値はリンクをコピーまたはドラッグしたり、新しいやウィンドウでリンクを開いたり、ブックマークしたり、 JavaScript が読み込み中、エラー状態、無効状態の場合などに予期しない動作を引き起こします。また、 (読み上げソフトなどの) 支援技術に対して誤った意味を伝えます。
>*[\<a>: アンカー要素 アクセシビリティの考慮事項](https://developer.mozilla.org/ja/docs/Web/HTML/Element/a#Accessibility_concerns)*

### 🙅 aタグの中にaタグ
よくカードUIとかで外枠もクリックできて、その中に別のリンクもある...みたいなのもありますよね。
![リンク範囲を説明した手書きの図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42808/810e33ca-0fb2-b854-723f-b03c32424697.jpeg)

でもaタグは親にaタグを持つことを**仕様として禁止されています**。
>許可されている親要素
記述コンテンツを受け入れるすべての要素、フローコンテンツ を受け入れるすべての要素。ただし `<a>` 要素を除く (対称性の論理原則によれば、親要素としての `<a>` タグは対話型コンテンツを持つことができませんので、`<a>` のコンテンツが `<a>` を親として持つこともできません)。
>*[\<a>: アンカー要素 プロパティ](https://developer.mozilla.org/ja/docs/Web/HTML/Element/a#Properties)*

こういうときはjsを使って補完する必要があります。
参考になる書き方： [aタグの中にaタグを書きたい時のtips](https://qiita.com/fukamiiiiinmin/items/7412b21c6df5de31cab1)

また、そもそもの文書構造を見直したり、可能であればデザイン変更も検討してみるのも手だと思います:)

## imgタグ
これもよく出没する画像を表示するためのタグ。
よく見かけるBadパターンはこちら

```html:Bad
<!-- altが入ってない, titleで代用しようとする -->
<img src="https://hogehoge/img/123.png" title="画像のタイトル">
```

### 🙅 altが入ってない, titleで代用しようとする
alt属性は簡単に言うと「マシンリーダブル」、title属性は「ヒューマンリーダブル」なものであると考えてしまってもいいかなと思っているので(持論)、意味合いが違ってきます。
alt属性で説明が書けるとスクリーンリーダーで読んでくれたり、電波が悪い時など画像が読み込めない場合代わりに表示してくれるテキストになるため、正しい情報を届けたい場合**必須の要素となります**。
意味を持たせたくないデザインのための画像の場合は`alt=""`で空要素を入れるのも可能です。
詳しい説明：[\<img>: 埋め込み画像要素 アクセシビリティの考慮事項](https://developer.mozilla.org/ja/docs/Web/HTML/Element/img#Accessibility_concerns)

## ul・olタグ
順序なし・ありのリストのタグ。
よく見かけるBadパターンはこちら

```html:Bad
<!-- ul・olの直下にli以外をいれる -->
<ul>
  <div>
    <li>hogehoge</li>
  </div>
  <li>fugafuga</li>
  <li>piyopiyo</li>
</ul>
```

### 🙅 ul・olの直下にli以外をいれる
これは先述でお伝えしたようにタグの使い方として間違っています。
正しくは
>許可されている内容
 0個以上の `<li>` 要素。その子孫としてさらに `<ol>` 要素や `<ul>` 要素を配置することも可能 
 *[\<ul>: 順序なしリスト要素](https://developer.mozilla.org/ja/docs/Web/HTML/Element/ul)*

なので、例えばデザインを変えたいのであれば`<div>`は`<li>`の直下で見せ方を変えるべきです。


## sectionタグ
HTML文書の中で単独のセクションを表すタグ。構造化タグとも言われています。
よく見かけるBadパターンはこちら

```html:Bad
<!-- section内に見出し要素h1-h6が無い -->
<section>
  <p>コンテンツ内容</p>
</section>
```

### 🙅 section内に見出し要素h1-h6が無い
構造化タグの`<section>`は識別可能であるべきなのでそのための見出しがないと正しく構造化出来ません。
デザイン的レイアウトのためにはコンテンツ分割要素の`<div>`を使用しましょう。
レイアウトはマシンリーダブルにする場合文章構造として不要なものと判断させる方がいいです。
参考になる書き方： [HTML5のお勉強　articleとsectionとか](https://qiita.com/piotzkhider/items/faffbc4a107e7e495998)

## まとめ
ここで紹介したタグたちは数多のHTMLタグの一部であり、それぞれが気をつける点を持っています。
もっと他のタグも知りたいと思えた方はこちらの[HTML 要素リファレンス](https://developer.mozilla.org/ja/docs/Web/HTML/Element)からご覧ください。

自分の書いてるHTMLが正しいのか不安！という方は[W3Cが提供しているバリデーター](https://validator.w3.org/#validate_by_input)を使って確認してみてもいいかもしれません。

なんだかんだ長くなりましたがここまで読んでくれた方ありがとうございます！
明日（12/17）の担当はスクラムマスターの[ざっきーdev](https://twitter.com/zakky_dev)さんです！


## 2019/12/17 追記
たくさんの人に見ていただけて大変ありがたく、いいねも嬉しいです:)
いろいろコメントやDMで共感の意見やこうした方がいいなどの意見もいただいています。
例えば「アクセシビリティ対応するならaria-labelなどを付けるべきじゃないのか」とか「付け焼き刃でやるならいっそ全くやらない方がマシ。全部divとspanでいい」など...
たしかにアクセシビリティ感を強めて書いてしまったことに関しては謝罪させていただきます。

ですが、もっと良い書き方あるよとおっしゃるのも分かりますが、そもそも使い方として間違ってるものをこの世に放出しておいてHTMLをナメてらっしゃるエンジニアには Don't を伝えられれば良いと思っています。
Do は興味があったらドキュメント読んだりバリデーター使って確認してみてください😌
アクセシビリティ向上のテクニックは出来る人だけ正しく行なってください。
なのでこの記事からも Good のコードは削除しました。

やり方はたくさんありますが、**ルールとしてダメなものだけは気にしていける**エンジニアが増えるのを願っております。