当然の話でした。皆さんは何が間違っているか、わかりますか?
resize/ResizeObserverはどちらもJavaScriptで、表示要素のサイズが変更されたときにキャッチアップする仕組みです。
どっち使えばいいかわかんないけど、とりあえず新しいResizeObserver使っとけばいいっしょ? と思ったあなた、表題の罠にハマるタイプです。
この二つは明確な違いがあります。それが監視対象です。
対象 | 概要 |
---|---|
resize | window を対象にできる |
ResizeObserver | window を対象にできず、HTML要素のみ対象にできる |
え〜、でもdocument.body
を対象にすればResizeObserverでも同じようにできるんじゃね? と思ったあなた、残念できません。正確にいうと、できる場合もあれば、できない場合もあります。
stack-overflowによると、document.body
を対象としたときheight
の変更が監視されていないとか、CSSでheight:100%
にすれば監視できると話しています。要点をわかりやすく言いましょう。そもそもCSSではHTML要素のサイズを固定できてしまうので、サイズ変更が起こらなくなります。(!)
リサイズ監視してもリサイズが起きない
index.html
<style>body { width:800px; height:600px; }</style> <script> window.addEventListener('DOMContentLoaded', (event) => { new ResizeObserver(()=>{console.log('ResizeObserver')}).observe(document.body) }); </script>
<style>
にあるように、body
の幅と高さを固定しています。document.body
の要素リサイズを監視しても、リサイズが起きません。
ためしにブラウザの窓サイズを変えてみましょう。最大化をやめて画面の端をマウスで掴み、ぐにぐにと動かして大きさを変えてみます。しかし一度もログが出ません。body
サイズはCSSにより固定されているのでサイズ変更が起きず、ResizeObserverでリサイズ監視してもキャッチアップされないのです。
(ログをHTML要素として表示するコード)
<style>body { width:800px; height:600px; }</style> <script> window.addEventListener('DOMContentLoaded', (event) => { window.addEventListener('resize', (event)=>{log()}); function log() { const msg = `${window.innerWidth}x${window.innerHeight}` console.log(msg) document.querySelector('textarea').value += msg + '\n' } }); </script> <textarea></textarea>
当たり前じゃん
はい、そうですね。ごめんなさい。
window
はCSSでサイズ固定できないはずなので、そんな罠はありません。window
をresizeイベントで監視すれば、たとえbody
サイズを固定しようとも、ちゃ〜んとキャッチアップしてくれます。
<style>body { width:800px; height:600px; }</style> <script> window.addEventListener('DOMContentLoaded', (event) => { window.addEventListener('resize', (event)=>{console.log('resize')}); }); </script>
クイズの答えです。「ResizeObserverで窓リサイズをキャッチしようとしてハマった」ということでしたが、これの何が間違っていたでしょうか。その答えは、窓リサイズをキャッチするのはResizeObserverでなくresizeイベントであるべき、でした。
結論
窓リサイズ監視するときはwindow
に対してresizeイベントを用いること。
document.body
をResizeObserverで監視しても、CSSでbody { width:800px; height:600px; }
のようにサイズ固定されるなど何らかの条件によってサイズ変更しない場合があり、キャッチアップできないことがある。