背景
offsetTopとclientTopの使い分けについてです。
両者の違いはoffsetTop
がoffsetParent
からの相対値で、clientTop
はブラウザの左上からの相対位置です。
offsetParent
と言われても意味不明ですが、ここではposition: absolute
なHTML要素の一番近い先祖のposition: relative
な要素です。次のようなイメージです。
<div id="offsetParent" style="position: absolute; witdth: 100px; height: 100px"> <div class="offsetChild" style="position: relative; top: 10px; left: 10px; witdth: 100px; height: 100px"></div> <div class="offsetChild" style="position: relative; top: 20px; left: 40px; witdth: 100px; height: 100px"></div> </div>
一つ目のoffsetChild
のoffsetTop
は常に10px
です。
clientTop
は縦スクロールの位置によって変わります。
offsetParent
の左上がちょうど、ブラウザの左上と一致した時、offsetTop
とclientTop
は同じ値になります。
課題
上の例のoffsetChild
にtop
, left
を設定して良い感じの位置に表示するプログラムを書いています。
今までHTML要素の位置を設定するために、offsetTop
としての値しか扱っていませんでした。
変数名やプロパティ名もシンプルにtop
としていました。
ここ最近、First Meaningful Paint の最適化に凝っています。
First Meaningful Paint のためには、これから表示するdiv
が、ブラウザで表示されている領域の中にあるか外にあるかが重要です。
ブラウザでdivが表示されているか判定する - @ledsun blog で、考えたようにこの判定にはclientTop
を使います*1。
ここで困ったのがtop
という名前だとoffsetTop
を意味しているのかclientTop
を意味しているのかわからないことです。
そして悩みはじめた時点では、offsetTop
という既知の最高の名前があることを忘れていました。
解決
リファクタリングしながら3時間半考えて「いままでのtop
が表しているのはoffsetTop
だ」と天啓を得ました。
あとは1時間くらいゴリゴリっと名前を変えるリファクタリングして回って、15分くらいclientTop
を取るAPIを追加して、10分でclientTop
を使った新機能*2を実装しました。
2017年頃は、じっくり考えてから実装するスタイルでした。 いまはリファクタリングしながら考えるスタイルに変わりました。 「道がみつかるまで手を動かせなかった」から「手を動かせば道が見つかる」を経験的に学習したようです。 しかも、リファクタリングした結果、読みやすいソースコードまで手に入るオマケ付きです。