(不正だけど)nameとidが被ったアンカー(#value)がどうなるか

# <i class="fa fa-cubes" aria-hidden="true"></i> 概要

`URL#アンカー名`
のアンカー名は`id`属性と、~~後方互換として~~`a`要素の`name`属性が使える場合がある。

では、ある要素の`id`属性と`a`要素の`name`属性が被った場合、
`URL#アンカー名`
はどちらへ飛ぶのか？

# <i class="fa fa-graduation-cap" aria-hidden="true"></i> 結論

ブラウザによって異なる。

|                      | nameが先 | idが先 | nameのみ |
|----------------------|----------|--------|----------|
| Firefox46            | id       | id     | name     |
| Chrome50.0.2661.94 m | id       | id     | name     |
| IE11                 | name     | id     | name     |

IEのみ先に出たものを採用するような結果となった。

当然ながら`id`と`name`は被らないようにしよう。
もしアンカーリンクが意図しない場所へ飛び、うまく再現しない、特定のブラウザのみで起こるなどの場合は、`a`要素の`name`属性を疑ってみる。


# <i class="fa fa-pencil" aria-hidden="true"></i> あらすじ

HTMLにはページ内リンクとして、特定の箇所にジャンプする機能がある。

`URL#アンカー名`
へ遷移することで、目的のアンカー要素がある場所へスクロールされた状態でそのページが表示される。

アンカーはユニークでなくてはならないので、`id`属性を使う。
なので、どんな要素でも`id`をつければジャンプできるようになる。

…というのが無勉強時の認識だった。
`id`属性登場前、つまりHTML4以前では、このアンカーは`a`要素の`name`属性が担当していた。
~~そして現在でも後方互換ということで、`a`要素の`name`属性でのジャンプが可能なようだ。~~

* `URL#アンカー名`は`id`か`a`要素の`name`を指す
* `id`と`name`は共通の名前空間を使用する
* `id`と`name`が重複することは仕様上正しくない

ということがわかった。
しかし人は間違いを犯すもので、このルールを知らずに`id`と`a`要素の`name`が被り、同名のアンカーが発生した場合、ブラウザはどちらのアンカーを使用するのかが気になった。

# <i class="fa fa-list" aria-hidden="true"></i> 仕様確認

## アンカーの経緯

以前は`a`要素の`name`属性を使っていたが、HTML4から`id`属性が追加された。

特に目的地の`a`要素は空にして、視覚上表示されない終点アンカーとして使われていたそうだ。

公式な仕様勧告ではないですが、
[アンカーの最適化｜最適化｜Web標準]


>a要素に name属性を指定する目的地アンカー（終点アンカー）は、従来の HTML によく用いられる手法ですが

,
>従来はウェブページ内の特定箇所を参照する方法は a要素の name属性による目的地アンカーのみに限られていましたが、id属性は他の要素に指定してもウェブページ内の特定箇所をリンク先として参照させることが可能です。

,
>Web標準技術の視点において、過去の規格において有効であった name属性を使用するのではなく、将来的にも通用する id属性を採用するのは至極当然のことでしょう。


## HTML4.01仕様書

`id`属性が追加されたHTML4の仕様書にアンカーに関する記述が見つけられた。
HTML5の勧告には見つけられないか、日本語訳されていないようだ。
仕様策定団体について詳しくないので、公式文書(それも私家訳)の検索にはかなり粗があることを先に述べておく。

* 参照元 - [About the HTML 4.01 specification Japanese translation]

[Links in HTML documents (ja)]

>12.1.1 リンク先リソースの訪問
HTML文書中の終点側アンカーは、A要素( name属性で命名される)によっても、また他の要素(id で命名される)によっても、指定できる。 

`a`要素の`name`属性は廃止されたわけではないようだ。

[Links in HTML documents (ja)#anchors-with-id]
`id`と`name`アンカーについて書かれている。

>id属性とname属性は、同じ 名前空間を共有する。 これはつまり、同一文書では、両属性が、あるアンカーに同じ名前を定めることができないということを意味する。 次の要素においては、両属性で、文書中で固有となる識別子を指定することが許される。 A、APPLET、FORM、FRAME、 IFRAME、IMG、及びMAP要素である。 単一要素中で両属性が用いられる場合、各々の値は同一でなければならない。 

`id`と`name`の名前空間の共有がポイントだ。また、
>両属性で、文書中で固有となる識別子を指定することが許される。

が意味が読み取れなかった。

>
不正な例:
次の例は、同一文書中で、各属性が同じ名前を重ねて宣言しているので不正なHTMLとなっている。
>
```
<A href="#a1">…</A>
…
<H1 id="a1">
…中略…
<A name="a1"></A>
```

この不正なHTMLをブラウザがどう解釈するかというのが今回の検証だ。

>id属性を使うか、name属性を使うか? 著者は、アンカー名にid属性を使うか name属性を使うかを決定する際に、次の内容を吟味する必要がある。
>
*   id属性は、アンカー名である以上の役割を果たす。例えば、スタイルシート選択子、プログラム処理の識別子など。
*    古いユーザエージェントの中には、id属性によるアンカーをサポートしないものもある。
*    name属性の方が、命名の自由度が高い。実体を利用できる。

流石に最近のブラウザでは`id`属性に対応しているだろうが。
ここでも`name`属性も否定的には書かれていない。

# 検証コード

https://jsfiddle.net/u9qyjngb/3/

```html
<body>

<div>
  <a href="#jump1">jump1 name id   順で飛びます</a>
  <a href="#jump2">jump2 id   name 順で飛びます</a>
  <a href="#jump3">jump3 name だけで飛びます</a>
</div>

<a name="jump1">nameに飛びます(jump1)</a>
<a id="jump1">idに飛びます(jump1)</a>

<a id="jump2">idに飛びます(jump2)</a>
<a name="jump2">nameに飛びます(jump2)</a>

<a name="jump3">nameに飛びます(jump3)</a>

</body>
```

```css
a {
  display:block;
}

body>a {
  margin-top: 1000px;
}
```

動作は結果を参照。

# <i class="fa fa-sitemap" aria-hidden="true"></i> その他参考

* [HTML5日本語訳]
* [`<a href="#top">`がHTML5で正式仕様になってた件 - Qiita]

[`<a href="#top">`がHTML5で正式仕様になってた件 - Qiita]:http://qiita.com/ginpei/items/129969dda33856268057
[HTML5日本語訳]:http://momdo.github.io/html5/Overview.html
[Links in HTML documents (ja)#anchors-with-id]:http://www.asahi-net.or.jp/~sd5a-ucd/rec-html401j/struct/links.html#anchors-with-id
[Links in HTML documents (ja)]:http://www.asahi-net.or.jp/~sd5a-ucd/rec-html401j/struct/links.html
[About the HTML 4.01 specification Japanese translation]:http://www.asahi-net.or.jp/~sd5a-ucd/rec-html401j/index.html
[アンカーの最適化｜最適化｜Web標準]:https://w3g.jp/webstandards/optimize/anchor