Detect Document Height Change
You can use an absolute
positioned iframe
with zero width inside the element you want to monitor for height changes, and listen to resize
events on its contentWindow
. For example:
HTML
<body>
Your content...
<iframe class="height-change-listener" tabindex="-1"></iframe>
</body>
CSS
body {
position: relative;
}
.height-change-listener {
position: absolute;
top: 0;
bottom: 0;
left: 0;
height: 100%;
width: 0;
border: 0;
background-color: transparent;
}
JavaScript (using jQuery but could be adapted to pure JS)
$('.height-change-listener').each(function() {
$(this.contentWindow).resize(function() {
// Do something more useful
console.log('doc height is ' + $(document).height());
});
});
If for whatever reason you have height:100%
set on body
you'll need find (or add) another container element to implement this on. If you want to add the iframe
dynamically you'll probably need to use the <iframe>.load
event to attach the contentWindow.resize
listener. If you want this to work in IE7 as well as browsers, you'll need to add the *zoom:1
hack to the container element and also listen to the 'proprietary' resize
event on the <iframe>
element itself (which will duplicate contentWindow.resize
in IE8-10).
Here's a fiddle...
Update (Oct 2020):
resizeObserver is a wonderful API (support table)
// create an Observer instance
const resizeObserver = new ResizeObserver(entries =>
console.log('Body height changed:', entries[0].target.clientHeight)
)
// start observing a DOM node
resizeObserver.observe(document.body)
// click anywhere to rnadomize height
window.addEventListener('click', () =>
document.body.style.height = Math.floor((Math.random() * 5000) + 1) + 'px'
)
click anywhere to change the height
Old answer:
Although a "hack", this simple function continuously "listens" (through setTimeout) to changes in an element's height and fire a callback when a change was detected.
It's important to take into account an element's height might change regardless of any action taken by a user (resize, click, etc.) and so, since it is impossible to know what can cause a height change, all that can be done to absolutely guarantee 100% detection is to place an interval height checker :
function onElementHeightChange(elm, callback) {
var lastHeight = elm.clientHeight, newHeight;
(function run() {
newHeight = elm.clientHeight;
if (lastHeight != newHeight)
callback(newHeight)
lastHeight = newHeight
if (elm.onElementHeightChangeTimer)
clearTimeout(elm.onElementHeightChangeTimer)
elm.onElementHeightChangeTimer = setTimeout(run, 200)
})()
}
// to clear the timer use:
// clearTimeout(document.body.onElementHeightChangeTimer);
// DEMO:
document.write("click anywhere to change the height")
onElementHeightChange(document.body, function(h) {
console.log('Body height changed:', h)
})
window.addEventListener('click', function() {
document.body.style.height = Math.floor((Math.random() * 5000) + 1) + 'px'
})
Just my two cents. If by any chance you're using angular then this would do the job:
$scope.$watch(function(){
return document.height();
},function onHeightChange(newValue, oldValue){
...
});