やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

ResizeObserverで窓リサイズをキャッチしようとしてハマった

 当然の話でした。皆さんは何が間違っているか、わかりますか?

 resizeResizeObserverはどちらもJavaScriptで、表示要素のサイズが変更されたときにキャッチアップする仕組みです。

 どっち使えばいいかわかんないけど、とりあえず新しいResizeObserver使っとけばいいっしょ? と思ったあなた、表題の罠にハマるタイプです。

 この二つは明確な違いがあります。それが監視対象です。

対象 概要
resize windowを対象にできる
ResizeObserver windowを対象にできず、HTML要素のみ対象にできる

 え〜、でもdocument.bodyを対象にすればResizeObserverでも同じようにできるんじゃね? と思ったあなた、残念できません。正確にいうと、できる場合もあれば、できない場合もあります。

 stack-overflowによると、document.bodyを対象としたときheightの変更が監視されていないとか、CSSheight: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>

当たり前じゃん

 はい、そうですね。ごめんなさい。

 windowCSSでサイズ固定できないはずなので、そんな罠はありません。windowresizeイベントで監視すれば、たとえ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.bodyResizeObserverで監視しても、CSSbody { width:800px; height:600px; }のようにサイズ固定されるなど何らかの条件によってサイズ変更しない場合があり、キャッチアップできないことがある。