🐓

DOMDOMタイムス#3: document.elementsFromPointでinline要素が引っかからないとき

2023/06/26に公開

少し忙しいので軽めの内容をメモして終わりにします👶
document.elementsFromPointdocument.elementFromPointを使ったら少しハマったことをメモ。

結論

複数行にまたがっているinline要素の行間の座標でdocument.elementsFromPointdocument.elementFromPointをやっても、inline要素は返り値の配列には入ってこない

詳細

  • document.elementsFromPointdocument.elementFromPointは、「与えられた座標上にある」要素を返す関数

  • 「与えられた座標上にある」という言葉の意味は、厳密には「与えられた座標上にboxがある」という意味。これはtransformも考慮して計算される。このへんはCSSOM仕様を読めば分かる

If there is a layout box in the viewport that would be a target for hit testing at coordinates x,y, when applying the transforms that apply to the descendants of the viewport, return the associated element and terminate these steps.
https://www.w3.org/TR/cssom-view-1/#extensions-to-the-document-interface

  • 複数行にまたがるinline要素のboxはfragmentationされる。つまりgetClientRects()をやると複数の矩形領域が返ってくるような状態になる(余談: getBoundingClientRect()はそれら全てを包含する最小矩形領域を返すのが仕様)

  • したがって、複数行にまたがっているinline要素の行間の座標でdocument.elementsFromPointdocument.elementFromPointをやっても、inline要素は拾われない

  • クリックした場所に重なっている要素を取得して何かするスクリプトを書くときは注意したいネ👶

分かっていないこと(知っている方がいたら教えてほしいこと)

  • block要素もcolumn-countとかでいわゆる段組みにするとfragmentationが起きるっぽいんだけど、document.elementsFromPointでちょうど段組みの間の座標を指定したら、返り値に含まれてきた。むむむ……

In the course of layout, boxes and text sequences can be broken into multiple fragments. This happens, for example, when an inline box and/or text sequence is broken across lines, or when a block box is broken across pages or columns, in a process called fragmentation.
https://drafts.csswg.org/css-display-4/#box

GitHubで編集を提案

Discussion