https://habrahabr.ru/post/326150/- Разработка веб-сайтов
- JavaScript
Наверно каждый WEB-разработчик когда-либо сталкивался с проблемой отслеживания события resize на странице. И если для window это сделать сможет любой новичок, то для остальных элементов эта задача принесет немало головной боли. Если вы относитесь к этой категории людей, то добро пожаловать под кат.
В интернете есть много статей где эта проблема решается с помощью setInterval или, в лучшем случае, рекурсивного setTimeout, который постоянно через определенные промежутки времени проверяет не изменились ли размеры указанного элемента. Но в большинстве случаев размеры элемента изменяются очень редко, поэтому такой способ является неприемлемым и к тому же может приводить к излишним тратам памяти.
На Хабре я нашел
решение для отслеживания «onresize» на элементе путем добавления внутрь него фрейма. Этот способ рабочий и в большинстве случаев наверняка будет полезен. Но что делать если по какой-то причине не хочется добавлять лишний фрейм внутрь элемента? Я хочу предложить еще пару способов для отслеживания изменения размеров элемента.
Для начала я разобью случаи в которых изменяются размеры элемента на категории:
- Изменение содержимого элемента
- Изменение стилей элемента
Первый способ: DOMSubtreeModified
Чаще всего необходимость отслеживания размера элемента возникает для того, чтобы обновить состояние какого-либо плагина при изменении контента в определенном блоке. Например обновить плагин карусели после того как изменилась высота контента внутри него.
Для этого нет необходимости наблюдать за изменением размеров элемента средствами CSS, а достаточно лишь отследить изменение структуры DOM внутри элемента.
Это можно легко осуществить используя
событие DOMSubtreeModified, которое срабатывает всякий раз когда структура или текст внутри элемента изменяется:
el.addEventListener("DOMSubtreeModified", function (e) {
console.log("Размеры элемента: " + el.clientWidth + " X " + el.clientHeight);
}, false);
→
Поддержка браузерамиВторой способ: transitionend
Для того чтобы отследить изменение размеров через CSS придется добавить следующие стили:
#el, #el * {
/* Свойства изменение которых необходимо отслеживать */
transition-property: width, height, padding, margin;
/* Устанавливаем "незаметную для глаза" длительность перехода */
transition-duration: 1ms;
}
Список свойств, как и длительность перехода можно подобрать под себя. Вполне возможно, что какие-то из этих свойств у элемента уже заданы или нет надобности применять их ко всем вложенным элементам.
Получается, что мы с помощью CSS-селекторов можем гибко указать на каких элементах требуется отслеживать изменение размеров (или любых других анимируемых свойств).
Таким образом у целевого блока и у всех элементов внутри него будет установлена мгновенная трансформация и так, как событие всплывает, то теперь мы можем отследить
событие transitionend, которое сработает, когда CSS transition закончит свое выполнение на любом дочернем элементе:
el.addEventListener("transitionend", function () {
console.log("Размеры элемента: " + el.clientWidth + " X " + el.clientHeight);
}, false);
→
Поддержка браузерами
К сожалению нет свойства transitionstart и transition или transitioninterval, поэтому событие срабатывает только по окончании перехода, так что значение transition-duration следует выбирать небольшое. Но если установить transition-duration равное 0, то событие не будет срабатывать вовсе.
Заключение
Конечно эти способы не смогут помочь в любой ситуации, но думаю в большинстве случаев первого или второго способа (а может и обоих сразу) будет более чем достаточно.
Надеюсь эта статья окажется полезной. Буду рад обоснованной критике, так как это мой первый опыт на Хабре.
→
Демо на JSFiddle
UPD: RubaXa
подсказал про
Resize Observers.
UPD: Обновил
демо, сделав его более наглядным и дополнил описание второго способа.