これはメモです

それ以上でもそれ以下でもないのです

tabindexの初期値について

divなどの通常フォーカスできない要素にJavaScriptでフォーカスを持たせる場合、tabindex="-1"を指定することがある。 ふと気になってtabindexのデフォルト値が何なのか調べてみた。

console.log(document.createElement('div').tabIndex); // -1
console.log(document.createElement('a').tabIndex); // 0
console.log(document.createElement('button').tabIndex); // 0

abuttonといったフォーカス可能な要素は0, それ以外は-1になるよう。 初期値が-1であれば指定不要では…?

と思ってtabindexを指定せずにフォーカスを当ててみようとしたが失敗。

仕様がどうなっているか確認。HTML Living Standardによると、

The tabIndex IDL attribute must reflect the value of the tabindex content attribute. The default value is 0 if the element is an a, area, button, frame, iframe, input, object, select, textarea, or SVG a element, or is a summary element that is a summary for its parent details. The default value is −1 otherwise. HTML Standard 6.6.3 The tabindex attribute

訳すと以下のような意味になる。

  • tabIndexのIDL属性は、 content属性の値を反映する必要がある。
  • 以下の要素のIDL属性は初期値が0。それ以外は-1
    • a
    • area
    • button
    • frame
    • iframe
    • input
    • object
    • select
    • textarea
    • SVGa
    • detailsの子要素であるsummary

聞き慣れないIDL属性、content属性と言う言葉が出てきた。 ざっくり言うと下記のような意味らしい。

  • IDL属性 … JavaScriptのプロパティ。
  • content属性 … HTMLで設定した属性。

つまり、JSのtabIndexプロパティの初期値は0-1で、HTMLに設定したtabindexの値はJSのプロパティに反映されるということらしい。 そのため、最初に調べたのはtabIndexプロパティであって、tabindex属性とは別。 ではHTMLにtabindexを設定しない場合、属性値は何になるのか。

console.log(document.createElement('div').getAttribute('tabindex')); // null
console.log(document.createElement('div').tabIndex); // -1

nullになった。HTMLに設定されたtabindexはJS側にも反映されるが、未指定の状態では相違が生じるということになる。

まとめると

  • HTML属性値とJSプロパティは同一のものに見えるが、実際はそうではない。
  • フォーカス可能要素以外にフォーカスを持たせる場合は、やはりHTML側でtabindex属性を明示的に指定する必要がある。

余談

また別の話だと思うが、ahrefもHTML属性とJSプロパティとで返す値が異なる。 仕様上、HTMLAnchorElementhref属性は絶対URIをを表すと決められている。

<a href="#hoge"></a>
// 表示ページのURLをhttps://example.comとする
document.querySelector('a').href; // https://example.com#hoge
document.querySelector('a').getAttribute('href'); // #hoge

以上。

参考