As I’ve found applicability to use the trifecta of JavaScript observers in my projects, I’ve tried to blog about them. So far, I’ve written about MutationObserver and IntersectionObserver. On a recent project, I had the opportunity to use ResizeObserver.
Oftentimes, I re-use a styling technique for the <figure>
element where the figure is relatively positioned, and the <figcaption>
is absolutely positioned on top of the image. It’s a nice, accessible approach for header images.
However, if the caption is very long on narrow viewports, the bounds of the caption exceed the height the image.
I needed a listener that actively compared the height of the caption against the height of the image. If the height of the caption exceeded the height of the image, dynamically set the height of the image to the height of the caption.
// check if ResizeObserver is supported | |
if( 'ResizeObserver' in window ){ | |
var figcaption = document.querySelector( 'figcaption > h1.entry-title' ); | |
var figure = document.querySelector( 'figure > div.post-thumbnail' ); | |
// check if the elements exist | |
if( ( typeof( figcaption ) !== 'undefined' && figcaption !== null ) && | |
( typeof( figure ) !== 'undefined' && figure !== null ) ){ | |
var ro = new ResizeObserver( entries => { | |
for( let entry of entries ){ | |
// get the height, including padding, of .entry-title | |
if( entry.target.tagName === 'H1' ){ | |
var h1 = entry.target; | |
var h1cr = entry.contentRect; | |
var h1height = h1cr.height + h1cr.top; | |
} | |
// get the height, including padding, of .post-thumbnail | |
if( entry.target.tagName === 'DIV' ){ | |
var div = entry.target; | |
var divcr = entry.contentRect; | |
var divheight = divcr.height + divcr.top; | |
} | |
// if .entry-title is taller than .post-thumbnail | |
if( h1height > divheight ){ | |
// set the height of the image to the height of .entry-title | |
div.querySelector( 'img' ).style.height = h1height + 'px'; | |
} | |
} | |
}); | |
ro.observe( figcaption ); | |
ro.observe( figure ); | |
} | |
} |
After a specific breakpoint, there was ample room for a caption regardless of its length. At that point, a stylesheet declaration takes care of setting the height of the image. I had to use !important
to override the inline style set by my ResizeObserver. I try to avoid using !important
at all costs, but it was simpler than complicating the JavaScript in order to unobserve the elements based on viewport width.