How to know when an DOM element moves or is resized
Asked Answered
W

4

32

I'd like to know if there is a DOM event to listen for that tells me when a DOM element moves is repositioned or is resized on the page. I am not talking about an elements being drag/dropped. An example is if I have a list of three items on a page, and I use JS to remove one of the top two list items from the page (or hide it or whatever), I'd like to attach a handler to run when the third list item gets moved up in the page.

I am using jQuery, so plain javascript or jQuery answers are acceptable.

Maybe there are no move/position/resize events at the element level, so if there is a page/doc level event that will tell me that the page was repainted and I can check if I need to call a function again?

Background

I put a transparent div over an element while a webservice call is made to delete that element. Since I need to absolutely position that overlay div, I want it to track the element that it covers initially. In effect anchoring it to the base element.

Wiliness answered 9/8, 2010 at 22:37 Comment(0)
N
13

You can't get a callback for element movement/resizing in general; you would have to keep constantly checking the dimensions in an interval poller, which would make it a bit less responsive. You could improve this by calling the checker on a window resize event too (and scroll if overflow or fixed positioning is involved. You could also add DOM Mutation Event listeners to get informed when elements are removed from the document tree, but this doesn't work in all browsers.

Can't you do an overlay with plain CSS? eg. put position: relative on the element to be obscured, then add the overlay inside it, with the following?

position: absolute;
z-index: 10;
left: 0;
top: 0;
width: 100%;
height: 100%;
opacity: 0.5;
Nynorsk answered 9/8, 2010 at 23:3 Comment(2)
I'll try your suggestion about putting the overlay in the element. Also, just watching window.resize and window.scroll might work... I'd just recalc all of my overlays.Wiliness
Doesn't seem to work. My base element (the element to BE obscured) is a table row (tr). If I set its position = relative, and append my overlay element ($overlay.appendTo($tr), does that look right?), with a position = absolute, the overlay fills the whole screen.Wiliness
T
16

I don't think this solution would be relevant after so long, but there's an excellent cross-browser solution based on the overflow and underflow events presented here

To enable our resize listening magic, we inject an object element into the target element, set a list of special styles to hide it from view, and monitor it for resize – it acts as a trigger for alerting us when the target element parent is resized.

The <object> element's content has a native resize event, just like a window.

Tank answered 23/5, 2013 at 13:13 Comment(2)
While this answer is over a year old and the link is helpful it would be better if you post the essential parts of the answer here, on this site, or your post risks being deleted See the FAQ where it mentions answers that are 'barely more than a link'. You may still include the link if you wish, but only as a 'reference'. The answer should stand on its own without needing the link.Vanillin
The method described in the article breaks if you try to remove the listener from an element that already removed from the DOM (contentDocument is null at line 60). A simple null check should help, I think.Gustafson
N
13

You can't get a callback for element movement/resizing in general; you would have to keep constantly checking the dimensions in an interval poller, which would make it a bit less responsive. You could improve this by calling the checker on a window resize event too (and scroll if overflow or fixed positioning is involved. You could also add DOM Mutation Event listeners to get informed when elements are removed from the document tree, but this doesn't work in all browsers.

Can't you do an overlay with plain CSS? eg. put position: relative on the element to be obscured, then add the overlay inside it, with the following?

position: absolute;
z-index: 10;
left: 0;
top: 0;
width: 100%;
height: 100%;
opacity: 0.5;
Nynorsk answered 9/8, 2010 at 23:3 Comment(2)
I'll try your suggestion about putting the overlay in the element. Also, just watching window.resize and window.scroll might work... I'd just recalc all of my overlays.Wiliness
Doesn't seem to work. My base element (the element to BE obscured) is a table row (tr). If I set its position = relative, and append my overlay element ($overlay.appendTo($tr), does that look right?), with a position = absolute, the overlay fills the whole screen.Wiliness
O
3

There's a (Ben Alman) plugin for that.TM

This is a good plugin, although I suggest using it sparingly (i.e., not on too many elements), so as to keep the amount of polling down.

Ooze answered 9/8, 2010 at 22:45 Comment(0)
N
2

I am surprised that resizeobserver is not mentioned in the answers in this thread yet.

ResizeObserver helps very much with detecting resize https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/ResizeObserver.

However, detecting moving is another story, and I don't have a good answer to that. ResizeObserver returns an element with contentRect which you might expect to contain something like getBoundingClientRect with position on the page but it is different from that, and is actually something that could be deprecated https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry/contentRect

Nyctaginaceous answered 1/12, 2023 at 4:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.