Detect size change of elements using transitions

While working on the Launchpad Portal, we needed to detect when some elements had their size changed (user had the option to change their width or height). However there is not native resize event triggered so we had to come up with another solution.

Searching around a bit, the most common way for something like this, would be setting a timeout and every few milliseconds check is the values have changed or if they are the save. However, as an experiment I came up with a more elegant way.

The concept is based on the fact that css transitions actually trigger events when they finish. Even by reading those few words, most of you must have already understood where this is heading: we will create a transition on width and on height with very low duration and just listen to the transition end effect to find out when the size has changed.

To illustrate this, we will have a very simple example: A box and two buttons. Clicking the buttons, increases the width and height of the button by a few pixels. Here is the initial code:
Markup

<div class="box"></div>
<button class="incWidth">Increase Width</button>
<button class="incHeight">Increase Height</button>

CSS

.box {
   width: 100px;
   height: 100px;
   background: red;
}

Javascript

$('.incWidth').on("click", function () {
   var $box = $('.box'), width = $box.width();
   if (width < 600) {
      $box.width(width+50);
   }
});
$('.incHeight').on("click", function () {
   var $box = $('.box'), height = $box.height();
   if (height < 600) {
      $box.height(height+50);
   }
});

First thing first, lets add the transition on our CSS. It will look like this:

.box {
   width: 100px;
   height: 100px;
   background: red;

   -moz-transition:width 0.01s, height 0.01s;
   -webkit-transition:width 0.01s, height 0.01s;
   -o-transition:width 0.01s, height 0.01s;
   transition:width 0.01s, height 0.01s;
}

As we can see, we have set a minimal duration of 0.01s so that the effect happens instantly. If we try a value of 0s, the transitionEnd event will never happen.

Finally lets add the javascript part as well

   $(".box").on("webkitTransitionEnd transitionend oTransitionEnd", function () {
      alert("Size Changed!");
   });

Since the event is named differently across different browsers, we use all 3 names, but each time only one will be triggered:
webkitTransitionEnd for Chrome and Safari
transitionend for Firefox and IE
oTransitionEnd for Opera

But what happens if I want to know whether the height has changed, or the width? And what if there are other transitions for this element as well? Well, lucky for us, in the event object, there is a property named propertyName which holds that information. Since we are using jQuery for the example, we will look for it inside the originalEvent. Our js will look like this:

$(".box").on("webkitTransitionEnd transitionend oTransitionEnd", function (event) {
  if (event.originalEvent.propertyName == "width") {
    alert("width changed!");
  }
  if (event.originalEvent.propertyName == "height") {
    alert("height changed!");
  }
});

So, is this method perfect? Of course not! It is only possible on browsers that support transitions, so you need to provide a fallback for IE9 and lower. But it is still a really nice trick you can use, to avoid using those ugly timeouts.

Here is a DEMO illustrating the technique.

2 Responses to Detect size change of elements using transitions
  1. [...] Part of that functionality can be covered using the transitionend event, much like I describe in this ar... prevent-default.com/responsive-x-tags
  2. Adrian88 Reply

    I see a lot of interesting articles here. Your content can go viral easily, you need some initial traffic
    only. How to get initial traffic?? Search for: bucksmagnet’s method

Leave a Reply

Your email address will not be published. Please enter your name, email and a comment.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>