- PVSM.RU - https://www.pvsm.ru -

Отслеживаем ресайзинг элемента без setTimeout и фреймов

Наверно каждый WEB-разработчик когда-либо сталкивался с проблемой отслеживания события resize на странице. И если для window это сделать сможет любой новичок, то для остальных элементов эта задача принесет немало головной боли. Если вы относитесь к этой категории людей, то добро пожаловать под кат.

В интернете есть много статей где эта проблема решается с помощью setInterval или, в лучшем случае, рекурсивного setTimeout, который постоянно через определенные промежутки времени проверяет не изменились ли размеры указанного элемента. Но в большинстве случаев размеры элемента изменяются очень редко, поэтому такой способ является неприемлемым и к тому же может приводить к излишним тратам памяти.

На Хабре я нашел решение для отслеживания «onresize» на элементе путем добавления внутрь него фрейма [1]. Этот способ рабочий и в большинстве случаев наверняка будет полезен. Но что делать если по какой-то причине не хочется добавлять лишний фрейм внутрь элемента? Я хочу предложить еще пару способов для отслеживания изменения размеров элемента.

Для начала я разобью случаи в которых изменяются размеры элемента на категории:

  • Изменение содержимого элемента
  • Изменение стилей элемента

Первый способ: DOMSubtreeModified

Чаще всего необходимость отслеживания размера элемента возникает для того, чтобы обновить состояние какого-либо плагина при изменении контента в определенном блоке. Например обновить плагин карусели после того как изменилась высота контента внутри него.

Для этого нет необходимости наблюдать за изменением размеров элемента средствами CSS, а достаточно лишь отследить изменение структуры DOM внутри элемента.

Это можно легко осуществить используя событие DOMSubtreeModified [2], которое срабатывает всякий раз когда структура или текст внутри элемента изменяется:

el.addEventListener("DOMSubtreeModified", function (e) {
  console.log("Размеры элемента: " + el.clientWidth + " X " + el.clientHeight);
}, false);

Поддержка браузерами [3]

Второй способ: transitionend

Для того чтобы отследить изменение размеров через CSS придется добавить целевому элементу следующие стили:

#el {
  /* Свойства изменение которых необходимо отслеживать */
  transition-property: width, height, padding;

  /* Устанавливаем "незаметную для глаза" длительность перехода */
  transition-duration: 1ms;
}

Список свойств, как и длительность перехода можно подобрать под себя. Вполне возможно, что какие-то из этих свойств у элемента уже заданы.

Теперь мы можем отследить событие transitionend [4], которое срабатывает, когда CSS transition закончил свое выполнение:

el.addEventListener("transitionend", function () {
  console.log("Размеры элемента: " + el.clientWidth + " X " + el.clientHeight);
}, false);

Поддержка браузерами [5]

К сожалению нет свойства transitionstart и transition или transitioninterval, поэтому событие срабатывает только по окончании перехода, так что значение transition-duration следует выбирать небольшое. Но если установить transition-duration равное 0, то событие не будет срабатывать вовсе.

Заключение

Конечно эти способы не смогут помочь в любой ситуации, но думаю в большинстве случаев первого или второго способа (а может и обоих сразу) будет более чем достаточно.

Надеюсь эта статья окажется полезной. Буду рад обоснованной критике, так как это мой первый опыт на Хабре.

Пример на JSFiddle [6]

Автор: XAHTEP26

Источник [7]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/252321

Ссылки в тексте:

[1] решение для отслеживания «onresize» на элементе путем добавления внутрь него фрейма: https://habrahabr.ru/post/166321/

[2] событие DOMSubtreeModified: https://developer.mozilla.org/en-US/docs/Web/Events/DOMSubtreeModified

[3] Поддержка браузерами: http://caniuse.com/#search=DOMSubtreeModified

[4] событие transitionend: https://developer.mozilla.org/ru/docs/Web/Events/transitionend

[5] Поддержка браузерами: http://caniuse.com/#search=transitionend

[6] Пример на JSFiddle: https://jsfiddle.net/68y2b53w/5/

[7] Источник: https://habrahabr.ru/post/326150/?utm_source=habrahabr&utm_medium=rss&utm_campaign=sandbox