[javascript] Resize on div element

jQuery has the resize() - event, but it just work with window.

jQuery(window).resize(function() { /* What ever */ });

This works fine! But when I want to add the event to a div element it doesn't work.

E.g.

jQuery('div').resize(function() { /* What ever */ });

I want to start an callback when the size of a div-element has changed. I don't want to start a resizable - event – just a event to check if the size of a div - element has changed.

Is there any solution to do this?

This question is related to javascript jquery

The answer is


Only window is supported yes but you could use a plugin for it: http://benalman.com/projects/jquery-resize-plugin/


For a google maps integration I was looking for a way to detect when a div has changed in size. Since google maps always require proper dimensions e.g. width and height in order to render properly.

The solution I came up with is a delegation of an event, in my case a tab click. This could be a window resize of course, the idea remains the same:

if (parent.is(':visible')) {
    w = parent.outerWidth(false);
    h = w * mapRatio /*9/16*/;
    this.map.css({ width: w, height: h });
} else {
    this.map.closest('.tab').one('click', function() {
        this.activate();
    }.bind(this));
}

this.map in this case is my map div. Since my parent is invisible on load, the computed width and height are 0 or don't match. By using .bind(this) I can delegate the script execution (this.activate) to an event (click).

Now I'm confident the same applies for resize events.

$(window).one('resize', function() {
    this.div.css({ /*whatever*/ });
}.bind(this));

Hope it helps anyone!


// this is a Jquery plugin function that fires an event when the size of an element is changed
// usage: $().sizeChanged(function(){})

(function ($) {

$.fn.sizeChanged = function (handleFunction) {
    var element = this;
    var lastWidth = element.width();
    var lastHeight = element.height();

    setInterval(function () {
        if (lastWidth === element.width()&&lastHeight === element.height())
            return;
        if (typeof (handleFunction) == 'function') {
            handleFunction({ width: lastWidth, height: lastHeight },
                           { width: element.width(), height: element.height() });
            lastWidth = element.width();
            lastHeight = element.height();
        }
    }, 100);


    return element;
};

}(jQuery));

There is a really nice, easy to use, lightweight (uses native browser events for detection) plugin for both basic JavaScript and for jQuery that was released this year. It performs perfectly:

https://github.com/sdecima/javascript-detect-element-resize


Just try this func (it may work not only for divs):

function resized(elem, func = function(){}, args = []){
    elem = jQuery(elem);
    func = func.bind(elem);
    var h = -1, w = -1;
    setInterval(function(){
        if (elem.height() != h || elem.width() != w){
            h = elem.height();
            w = elem.width();
            func.apply(null, args);
        }
    }, 100);
}

You can use it like this

resized(/*element*/ '.advs-columns-main > div > div', /*callback*/ function(a){
    console.log(a);
    console.log(this); //for accessing the jQuery element you passed
}, /*callback arguments in array*/ ['I\'m the first arg named "a"!']);

UPDATE: You can also use more progressive watcher (it can work for any objects, not only DOM elements):

function changed(elem, propsToBeChanged, func = function(){}, args = [], interval = 100){
        func = func.bind(elem);
        var currentVal = {call: {}, std: {}};
        $.each(propsToBeChanged, (property, needCall)=>{
            needCall = needCall ? 'call' : 'std';
            currentVal[needCall][property] = new Boolean(); // is a minimal and unique value, its equivalent comparsion with each other will always return false
        });
        setInterval(function(){
            $.each(propsToBeChanged, (property, needCall)=>{
                try{
                    var currVal = needCall ? elem[property]() : elem[property];
                } catch (e){ // elem[property] is not a function anymore
                    var currVal = elem[property];
                    needCall = false;
                    propsToBeChanged[property] = false;
                }
                needCall = needCall ? 'call' : 'std';
                if (currVal !== currentVal[needCall][property]){
                    currentVal[needCall][property] = currVal;
                    func.apply(null, args);
                }
            });
        }, interval);
    }

Just try it:

var b = '2',
    a = {foo: 'bar', ext: ()=>{return b}};
changed(a, {
// prop name || do eval like a function?
    foo:        false,
    ext:        true
}, ()=>{console.log('changed')})

It will log 'changed' every time when you change b, a.foo or a.ext directly


DIV does not fire a resize event, so you won't be able to do exactly what you've coded, but you could look into monitoring DOM properties.

If you are actually working with something like resizables, and that is the only way for a div to change in size, then your resize plugin will probably be implementing a callback of its own.


If you just want to resize the div itself you need to specify that in css style. You need to add overflow and resize property.

Below is my code snippet

#div1 {
        width: 90%;
        height: 350px;
        padding: 10px;
        border: 1px solid #aaaaaa;
        overflow: auto;
        resize: both;
    }

<div id="div1">

</div>

I've created jquery plugin jquery.resize it use resizeObserver if supported or solution based on marcj/css-element-queries scroll event, no setTimeout/setInterval.

You use just

 jQuery('div').on('resize', function() { /* What ever */ });

or as resizer plugin

jQuery('div').resizer(function() { /* What ever */ });

I've created this for jQuery Terminal and extracted into separated repo and npm package, but in a mean time I switched to hidden iframe because I had problems with resize if element was inside iframe. I may update the plugin accordingly. You can look at iframe based resizer plugin in jQuery Terminal source code.

EDIT: new version use iframe and resize on it's window object because the previous solutions was not working when page was inside iframe.

EDIT2: Because the fallback use iframe you can't use it with form controls or images, you need to add it to the wrapper element.

EDIT3:: there is better solution using resizeObserver polyfill that use mutation observer (if resizeObserver is not supported) and work even in IE. It also have TypeScript typings.


I was only interested for a trigger when a width of an element was changed (I don' care about height), so I created a jquery event that does exactly that, using an invisible iframe element.

$.event.special.widthChanged = {
  remove: function() {
      $(this).children('iframe.width-changed').remove();
  },
  add: function () {
      var elm = $(this);
      var iframe = elm.children('iframe.width-changed');
      if (!iframe.length) {
          iframe = $('<iframe/>').addClass('width-changed').prependTo(this);
      }
      var oldWidth = elm.width();
      function elmResized() {
          var width = elm.width();
          if (oldWidth != width) {
              elm.trigger('widthChanged', [width, oldWidth]);
              oldWidth = width;
          }
      }

      var timer = 0;
      var ielm = iframe[0];
      (ielm.contentWindow || ielm).onresize = function() {
          clearTimeout(timer);
          timer = setTimeout(elmResized, 20);
      };
  }
}

It requires the following css :

iframe.width-changed {
    width: 100%;
    display: block;
    border: 0;
    height: 0;
    margin: 0;
}

You can see it in action here widthChanged fiddle


You can change your text or Content or Attribute depend on Screen size: HTML:

<p class="change">Frequently Asked Questions (FAQ)</p>
<p class="change">Frequently Asked Questions </p>

Javascript:

<script>
const changeText = document.querySelector('.change');
function resize() {
  if((window.innerWidth<500)&&(changeText.textContent="Frequently Asked Questions (FAQ)")){
    changeText.textContent="FAQ";
  } else {
    changeText.textContent="Frequently Asked Questions (FAQ)";
  }
}
window.onresize = resize;
</script>

what about this:

divH = divW = 0;
jQuery(document).ready(function(){
    divW = jQuery("div").width();
    divH = jQuery("div").height();
});
function checkResize(){
    var w = jQuery("div").width();
    var h = jQuery("div").height();
    if (w != divW || h != divH) {
        /*what ever*/
        divH = h;
        divW = w;
    }
}
jQuery(window).resize(checkResize);
var timer = setInterval(checkResize, 1000);

BTW I suggest you to add an id to the div and change the $("div") to $("#yourid"), it's gonna be faster, and it won't break when later you add other divs