I have an iframe of a video inside a div, like so:
I set the DIV\'s size dynami
I have really improved on the answer from @TrueBlueAussie over time, and thought I'd post a more sophisticated answer here for future reference.
Made it a plugin on GitHub here: https://github.com/drewbaker/fitToParent
Here is the jQuery plugin:
jQuery.fn.fitToParent = function (options) {
this.each(function () {
// Cache the resize element
var $el = jQuery(this);
// Get size parent (box to fit element in)
var $box;
if( $el.closest('.size-parent').length ) {
$box = $el.closest('.size-parent');
} else {
$box = $el.parent();
}
// These are the defaults.
var settings = jQuery.extend({
height_offset: 0,
width_offset: 0,
box_height: $box.height(),
box_width: $box.width(),
}, options );
// Setup box and element widths
var width = $el.width();
var height = $el.height();
var parentWidth = settings.box_width - settings.width_offset;
var parentHeight = settings.box_height - settings.height_offset;
// Maintin aspect ratio
var aspect = width / height;
var parentAspect = parentWidth / parentHeight;
// Resize to fit box
if (aspect > parentAspect) {
newWidth = parentWidth;
newHeight = (newWidth / aspect);
} else {
newHeight = parentHeight;
newWidth = newHeight * aspect;
}
// Set new size of element
$el.width(newWidth);
$el.height(newHeight);
});
};
So, assuming you have HTML of this:
<div id="wrapper">
<iframe width="720" height="405" src="//player.vimeo.com/video/19223989"></iframe>
</div>
The most basic way to call the plugin is like this:
jQuery('#wrapper iframe').fitToParent();
But I'll often set #wrapper to be close to window height and width, like this:
// Get window height and width
var winHeight = jQuery(window).height();
var winWidth = jQuery(window).width();
// Set wrapper height/width to that of window
jQuery('#wrapper').height(winHeight).width(winWidth);
// Size Iframe
jQuery('#wrapper iframe').fitToParent({
height_offset: 100, // Put some space around the video
width_offset: 100, // Put some space around the video
});
You can also feed in a custom box size to fit the element in, like this:
// Get window height and width
var winHeight = jQuery(window).height();
var winWidth = jQuery(window).width();
// Size element
jQuery('#wrapper iframe').fitToParent({
height_offset: 100, // Put some space around the video
width_offset: 100, // Put some space around the video
box_height: winHeight, // Force use of this box size
box_width: winWidth // Force use of this box size
});
I've also added the ability to set a CSS class of "size-parent" to a parent element, and it will then use that parent element for the box size. A full example of that:
// HTML like this
<div id="wrapper" class="size-parent">
<div class="media">
<iframe width="720" height="405" src="//player.vimeo.com/video/19223989"></iframe>
</div>
</div>
// jQuery like this
jQuery('.media iframe').fitToParent();
If you don't set a .size-parent, it will fallback to the element parent. If you set the box_height/box_width parameter, then those override everything obviously.
Now, to show how powerful this can be, try this for a vertically centered, horizontal centered aspect ratio correct iFrame!
// CSS like this
#wrapper {
text-align: center;
display: table-cell;
vertical-align: middle;
}
#wrapper iframe {
display: inline-block;
}
// HTML like this
<div id="wrapper" class="size-wrapper">
<iframe width="720" height="405" src="//player.vimeo.com/video/19223989"></iframe>
</div>
// jQuery like this
// Get window height and width
var winHeight = jQuery(window).height();
var winWidth = jQuery(window).width();
// Size wrapper
jQuery('#wrapper').height( winHeight ).width( winWidth );
// Size element
jQuery('#wrapper iframe').fitToParent({
height_offset: 200, // Put some space around the video
width_offset: 200, // Put some space around the video
});
// Fit iFrame to wrapper
jQuery('#wrapper iframe').fitToParent();
In real life, I wrap the jQuery in a function, and then call that function on window resize for true responsive iFrames!
here:
http://jsfiddle.net/fFTS8/
<div id="test" style="width:300px;height:200px;background:red;"></div>
<script src="js/vendor/jquery-1.10.2.min.js"></script>
<script type="text/javascript">
jQuery.fn.fitToParent = function()
{
var that = this;
function rezise() {
that.each(function()
{
var a = $(this).width();
var b = $(this).height();
var c = $(this).parent().width();
var d = $(this).parent().height();
var ab = a/b;
var cd = c/b;
var e, f = 0; // e - newWidth, f - newHeight
if(ab > cd) {
e = c;
f = c*b/a;
} else {
e = a*d/b;
f = d;
}
$(this).width(e);
$(this).height(f);
});
}
$(window).resize(function() {
rezise();
});
};
$('#test').fitToParent();
</script>
Three issues noted:
You have an error (trailing quote) in your example:
:newWidth'
You need to set the iframe actual height and width attributes and not the style. Styling an iframe size has no effect:
$(this).width(newWidth);
$(this).height(newHeight);
the calculation for aspect ratio was wrong (needs to compare ratios to see which way they overlap). Without this not all overlap cases are catered for.
var aspect = width/height;
var parentAspect = parentWidth/parentHeight;
if (aspect > parentAspect)
{
newWidth = parentWidth;
newHeight = newWidth / aspect;
}
else
{
newHeight = parentHeight;
newWidth = newHeight * aspect;
}
I also cleaned up the code a little to speed up element access. Each call to jQuery(this) costs cycles.
The jsfiddle now has examples of the 4 different scenarios of overlap and each retains the proportions of the iframe. I also added the window resize you mentioned and made the first div resize dynamically with it to demonstrate.