29

For a long time, I've been looking for a way to detect when a DOM element's size or position has changed. It could be because the window resized, or because new child elements were added to the element, or because new elements were added around this element, or because CSS rules have changed, or because the user has changed their browser's font size. There are a huge number of reasons that an element's size or position would change.

I could hook event handlers for many of those events, but I think there are cases that aren't covered. I had hoped to use MutationObservers to just watch the element's offsetWidth or clientWidth, but it looks like those only apply to DOM attributes, not Node properties (or maybe that's just what Webkit implements). So, to be truly bulletproof, it looks like I would need to run a polling loop anyway.

Is this correct? Have I missed something important? Is polling the only bulletproof way to detect when an element's size or position has changed?

Edit

To give a little more context, this isn't tied to any one particular use case. For me, it has come up time and time again. In my current situation, I was hoping to have a canvas that is set, via CSS, to be 100% width and height of its parent. I want a script to adjust the canvas's width and height properties when its offsetWidth or clientWidth changed (this is for WebGL, where the width and height properties affect the framebuffer resolution). In another project, I wanted to have an element expand in height to fill whatever remaining space was in the user's browser window. I have come across this situation time and time again and, inevitably, the solution seems to be:

  1. Listen to window.resize
  2. Hook into any code that you write that might change the DOM (or maybe use Mutation Events or Mutation Observers)
  3. Have a periodic polling operation to clean up any missed cases

(most people stop at 1, and maybe do a little of 2)

I just wanted to make sure I wasn't missing something vital.

Incidentally, in my WebGL situation, listening to window.resize is sufficient (and is somewhat preferable, because then the canvas dimensions and rendering resolution change at the same time).

Daniel Yankowsky
  • 6,956
  • 1
  • 35
  • 39
  • 1
    To the title: no. To the last sentence: yes. What's the bigger problem you're trying to solve? – Matt Ball Dec 02 '12 at 05:46
  • 1
    Mutation events are designed only for the DOM, not any display properties or the like; Webkit does it correctly. I'd assume that firing events when reflowing the document layout would be too critical (performancewise, but also errorprone). – Bergi Dec 02 '12 at 12:38
  • @Matt Ball - sorry for not providing context in the initial question. I've been on SO long enough to know better. – Daniel Yankowsky Dec 02 '12 at 16:42

3 Answers3

9

You might could do it with CSS animations. Check out http://developer.streak.com/2012/11/how-to-detect-dom-changes-in-css.html and similar. I suppose it won't handle all your requirements though, now that I read through it some more.

Pre101
  • 2,370
  • 16
  • 23
3

A co-worker pointed me to a technique that uses the underflow and overflow events. I haven't tried it, and I have no idea what kind of browser support there is (looks like Chrome and FireFox, and it should work in IE by synthesizing the same events that browser would look for, but I have no idea which versions support the technique).

Daniel Yankowsky
  • 6,956
  • 1
  • 35
  • 39
  • 2
    Interestingly the author is the one who also advertised using css animations. Here is his original post: http://www.backalleycoder.com/2012/04/25/i-want-a-damnodeinserted/ – Christophe Jun 14 '13 at 21:05
  • 1
    If you need IE support, then read the author's updated article, [Cross-Browser, Event-based, Element Resize Detection](http://www.backalleycoder.com/2013/03/18/cross-browser-event-based-element-resize-detection/). – thdoan Aug 13 '15 at 04:38
0

As of 2019, you have access to:

David Peicho
  • 453
  • 4
  • 16