I have a Tumblr theme with responsive design enabled, and want to resize video iframes. Here is a sample of how the page's HTML might look like:
/* rest of blog */
<div id="box-content">
/* other posts; may contain more video posts */
<div class="post video">
<iframe src="[REDACTED]"
style="display:block;background-color:transparent;overflow:hidden"
class="embed_iframe tumblr_video_iframe"
scrolling="no" frameborder="0"
data-can-gutter="" data-can-resize=""
data-width="500" data-height="500"
width="500" height="500" allowfullscreen=""
mozallowfullscreen="" webkitallowfullscreen="">
</iframe>
<div class="post-content">
/* post content */
</div>
</div>
/* other posts; may contain more video posts */
</div>
/* rest of blog */
I have this function that (I think; I never really learned JavaScript) stores the original width and height of the iframe, as well as the width of the parent, in variables, and changes the width and height of the iframe.
My intended method was
There is a child iframe element for each of them. Store each of the following in its variable:
a. that iframe's original width (ow), b. that iframe's original height (oh), and c. the parent element's width (cw for container width)
Set the iframe's width to cw.
...and the function that didn't work was:
function resizeVideos() {
var videoPostNodeList = document.getElementsByClassName("video");
for (var i = 0; i < videoPostNodeList.length; i++) {
var videoNode = videoPostNodelist[i].getElementsByTagName("iframe")[0];
var ow = videoNode.offsetWidth;
var oh = videoNode.offsetHeight;
var cw = videoPostNodelist[i].offsetWidth;
videoNode.offsetWidth = cw;
videoNode.offsetHeight = oh * cw / ow;
}
}
resizeVideos();
window.addEventListener("resize", resizeVideos);
The current version of this theme is available at testing-html.tumblr.com, on which I currently have three videos reblogged: one square video, one horizontal widescreen video, and one vertical widescreen video. What amateur mistake did I make with this?
An element's offsetWidth
and offsetHeight
are measurements of what's visible, including the element's borders, padding, scrollbar (if present & rendered) and CSS width.
You do have other options though, like clientWidth
and clientHeight
and scrollWidth
and scrollHeight
(which unfortunately doesn't have a good image on MDN)
Based on your description of what you want, I'd say you should set your ow
and oh
based on the scrollWidth
and scrollHeight
properties instead.
If I understand the situation correctly, your best bet is likely to be setting the elements max-width
and max-height
CSS properties (though you may prefer to directly override width
and height
):
function resizeVideos() {
var videoPostNodeList = document.getElementsByClassName("video");
for (var i = 0; i < videoPostNodeList.length; i++) {
var videoNode = videoPostNodelist[i].getElementsByTagName("iframe")[0];
var ow = videoNode.scrollWidth;
var oh = videoNode.scrollHeight;
var cw = videoPostNodelist[i].offsetWidth;
videoNode.style.maxWidth = cw;
videoNode.style.maxHeight = oh * cw / ow;
}
}
Finally, wait till the content is loaded before you run it (and as you did before, run it on window resize too):
document.addEventListener("DOMContentLoaded", resizeVideos);
window.addEventListener("resize", resizeVideos);
See Determining the dimensions of elements on MDN for more info.