DOMDOMタイムス#3: document.elementsFromPointでinline要素が引っかからないとき
少し忙しいので軽めの内容をメモして終わりにします👶
document.elementsFromPoint
やdocument.elementFromPoint
を使ったら少しハマったことをメモ。
結論
複数行にまたがっているinline要素の行間の座標でdocument.elementsFromPoint
やdocument.elementFromPoint
をやっても、inline要素は返り値の配列には入ってこない
詳細
-
document.elementsFromPoint
やdocument.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.elementsFromPoint
やdocument.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
Discussion