Detecting when a div's height changes using jQuery

JavascriptJquery

Javascript Problem Overview


I've got a div that contains some content that's being added and removed dynamically, so its height is changing often. I also have a div that is absolutely positioned directly underneath with javascript, so unless I can detect when the height of the div changes, I can't reposition the div below it.

So, how can I detect when the height of that div changes? I assume there's some jQuery event I need to use, but I'm not sure which one to hook into.

Javascript Solutions


Solution 1 - Javascript

Use a resize sensor from the css-element-queries library:

https://github.com/marcj/css-element-queries

new ResizeSensor(jQuery('#myElement'), function() {
    console.log('myelement has been resized');
});

It uses a event based approach and doesn't waste your cpu time. Works in all browsers incl. IE7+.

Solution 2 - Javascript

I wrote a plugin sometime back for attrchange listener which basically adds a listener function on attribute change. Even though I say it as a plugin, actually it is a simple function written as a jQuery plugin.. so if you want.. strip off the plugin specfic code and use the core functions.

Note: This code doesn't use polling

check out this simple demo http://jsfiddle.net/aD49d/

$(function () {
    var prevHeight = $('#test').height();
    $('#test').attrchange({
        callback: function (e) {
            var curHeight = $(this).height();            
            if (prevHeight !== curHeight) {
               $('#logger').text('height changed from ' + prevHeight + ' to ' + curHeight);
                
                prevHeight = curHeight;
            }            
        }
    }).resizable();
});

Plugin page: http://meetselva.github.io/attrchange/

Minified version: (1.68kb)

(function(e){function t(){var e=document.createElement("p");var t=false;if(e.addEventListener)e.addEventListener("DOMAttrModified",function(){t=true},false);else if(e.attachEvent)e.attachEvent("onDOMAttrModified",function(){t=true});else return false;e.setAttribute("id","target");return t}function n(t,n){if(t){var r=this.data("attr-old-value");if(n.attributeName.indexOf("style")>=0){if(!r["style"])r["style"]={};var i=n.attributeName.split(".");n.attributeName=i[0];n.oldValue=r["style"][i[1]];n.newValue=i[1]+":"+this.prop("style")[e.camelCase(i[1])];r["style"][i[1]]=n.newValue}else{n.oldValue=r[n.attributeName];n.newValue=this.attr(n.attributeName);r[n.attributeName]=n.newValue}this.data("attr-old-value",r)}}var r=window.MutationObserver||window.WebKitMutationObserver;e.fn.attrchange=function(i){var s={trackValues:false,callback:e.noop};if(typeof i==="function"){s.callback=i}else{e.extend(s,i)}if(s.trackValues){e(this).each(function(t,n){var r={};for(var i,t=0,s=n.attributes,o=s.length;t<o;t++){i=s.item(t);r[i.nodeName]=i.value}e(this).data("attr-old-value",r)})}if(r){var o={subtree:false,attributes:true,attributeOldValue:s.trackValues};var u=new r(function(t){t.forEach(function(t){var n=t.target;if(s.trackValues){t.newValue=e(n).attr(t.attributeName)}s.callback.call(n,t)})});return this.each(function(){u.observe(this,o)})}else if(t()){return this.on("DOMAttrModified",function(e){if(e.originalEvent)e=e.originalEvent;e.attributeName=e.attrName;e.oldValue=e.prevValue;s.callback.call(this,e)})}else if("onpropertychange"in document.body){return this.on("propertychange",function(t){t.attributeName=window.event.propertyName;n.call(e(this),s.trackValues,t);s.callback.call(this,t)})}return this}})(jQuery)

Solution 3 - Javascript

You can use the DOMSubtreeModified event

$(something).bind('DOMSubtreeModified' ...

But this will fire even if the dimensions don't change, and reassigning the position whenever it fires can take a performance hit. In my experience using this method, checking whether the dimensions have changed is less expensive and so you might consider combining the two.

Or if you are directly altering the div (rather than the div being altered by user input in unpredictable ways, like if it is contentEditable), you can simply fire a custom event whenever you do so.

Downside: IE and Opera don't implement this event.

Solution 4 - Javascript

This is how I recently handled this problem:

$('#your-resizing-div').bind('getheight', function() {
	$('#your-resizing-div').height();
});

function your_function_to_load_content() {
    /*whatever your thing does*/
    $('#your-resizing-div').trigger('getheight');
}

I know I'm a few years late to the party, just think my answer may help some people in the future, without having to download any plugins.

Solution 5 - Javascript

You can use MutationObserver class.

MutationObserver provides developers a way to react to changes in a DOM. It is designed as a replacement for Mutation Events defined in the DOM3 Events specification.

Example (source)

// select the target node
var target = document.querySelector('#some-id');
 
// create an observer instance
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    console.log(mutation.type);
  });    
});
 
// configuration of the observer:
var config = { attributes: true, childList: true, characterData: true };
 
// pass in the target node, as well as the observer options
observer.observe(target, config);
 
// later, you can stop observing
observer.disconnect();

Solution 6 - Javascript

In response to user007:

If the height of your element is changing due to items being appended to it using .append() you shouldn't need to detect the change in height. Simply add the reposition of your second element in the same function where you are appending the new content to your first element.

As in:

Working Example

$('.class1').click(function () {
    $('.class1').append("<div class='newClass'><h1>This is some content</h1></div>");
    $('.class2').css('top', $('.class1').offset().top + $('.class1').outerHeight());
});

Solution 7 - Javascript

You can make a simple setInterval.

function someJsClass()
{
  var _resizeInterval = null;
  var _lastHeight = 0;
  var _lastWidth = 0;
  
  this.Initialize = function(){
    var _resizeInterval = setInterval(_resizeIntervalTick, 200);
  };
  
  this.Stop = function(){
    if(_resizeInterval != null)
      clearInterval(_resizeInterval);
  };
  
  var _resizeIntervalTick = function () {
    if ($(yourDiv).width() != _lastWidth || $(yourDiv).height() != _lastHeight) {
      _lastWidth = $(contentBox).width();
      _lastHeight = $(contentBox).height();
      DoWhatYouWantWhenTheSizeChange();
    }
  };
}

var class = new someJsClass();
class.Initialize();

EDIT:

This is a example with a class. But you can do something easiest.

Solution 8 - Javascript

These days you can also use the Web API ResizeObserver.

Simple example:

const myElement = document.querySelector('#myElement');

const resizeObserver = new ResizeObserver(() => {
    console.log('size of myElement changed');
});

resizeObserver.observe(myElement);

Solution 9 - Javascript

You can use this, but it only supports Firefox and Chrome.

$(element).bind('DOMSubtreeModified', function () {
  var $this = this;
  var updateHeight = function () {
    var Height = $($this).height();
    console.log(Height);
  };
  setTimeout(updateHeight, 2000);
});

Solution 10 - Javascript

Pretty basic but works:

function dynamicHeight() {
    var height = jQuery('').height();
    jQuery('.edito-wrapper').css('height', editoHeight);
}
editoHeightSize();

jQuery(window).resize(function () {
    editoHeightSize();
});

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBob SomersView Question on Stackoverflow
Solution 1 - JavascriptMarc J. SchmidtView Answer on Stackoverflow
Solution 2 - JavascriptSelvakumar ArumugamView Answer on Stackoverflow
Solution 3 - JavascripteyelidlessnessView Answer on Stackoverflow
Solution 4 - JavascriptKyleView Answer on Stackoverflow
Solution 5 - JavascriptEFernandesView Answer on Stackoverflow
Solution 6 - JavascriptapaulView Answer on Stackoverflow
Solution 7 - JavascriptEstefano SalazarView Answer on Stackoverflow
Solution 8 - JavascriptgitaarikView Answer on Stackoverflow
Solution 9 - JavascriptRonald RiveraView Answer on Stackoverflow
Solution 10 - JavascriptZacView Answer on Stackoverflow