Fluid Width YouTube Videos

Published by Chris Coyier

This article was originally written on September 2, 2010 and is now being updated to be mo' better. It now handles YouTube videos of different aspect ratios, the new iframe embed method, and with more efficient scripts.

I expanded this idea to cover ALL video.

And now a jQuery plugin called FitVids.js that handles the vast majority of videos.

The code that YouTube gives you to embed a video is now a very simple iframe. Here's an example:

<iframe width="1280" height="750" src="//www.youtube.com/embed/fXm9EwzSjO4?rel=0&amp;hd=1" frameborder="0" allowfullscreen></iframe>

iFrames, including the example YouTube code above, contain external content which cannot really be measured from the parent page. The width and height settings are necessary to define the size of the iframe, as the content inside will not help shape it (like an image would). But setting a static width and height on an element poses a problem for any type of fluid/flexible design. If the parent area shrinks in width to be narrower than the video, the video will break out, not shrink to fit.

Web Designer Wall recently published an article on how to deal with fluid width video. The idea originally came from Thierry Koblentz who wrote about it on his site and A List Apart.

I love the ideas presented there. They are pure CSS (yay), clever, and do their job super well. But the solution they have for YouTube videos has two inherit shortcomings:

  1. The aspect ratio for the videos is pre-defined. The clever padding-bottom: 56.25% thing makes for an aspect ratio of 16:9 which is great for some videos but certainly not all.
  2. You have to use additional markup. Each video needs to be wrapped in another HTML element. I wouldn't call it non-semantic since it may make sense to use a <figure> or something but it's certainly more work.

If you don't care about either of those things, by all means use that, it's a much cleaner solution. If that does matter, we're going to need to employ some JavaScript.

Doing it with jQuery

The cool part about this JavaScript solution is that you just copy-and-paste YouTube embed code onto your page and don't think about it. Whatever aspect ratio you want to set it to is fine. And no extra markup.

The basics are:

  1. Figure out and save the aspect ratio for all videos on the page.
  2. When the window is resized, figure out the new width of the content area and resize all videos to match that width with their original aspect ratio.

Here's the full script with comments:

// By Chris Coyier & tweaked by Mathias Bynens

$(function() {

	// Find all YouTube videos
	var $allVideos = $("iframe[src^='http://www.youtube.com']"),

	    // The element that is fluid width
	    $fluidEl = $("body");

	// Figure out and save aspect ratio for each video
	$allVideos.each(function() {

		$(this)
			.data('aspectRatio', this.height / this.width)
			
			// and remove the hard coded width/height
			.removeAttr('height')
			.removeAttr('width');

	});

	// When the window is resized
	// (You'll probably want to debounce this)
	$(window).resize(function() {

		var newWidth = $fluidEl.width();
		
		// Resize all videos according to their own aspect ratio
		$allVideos.each(function() {

			var $el = $(this);
			$el
				.width(newWidth)
				.height(newWidth * $el.data('aspectRatio'));

		});

	// Kick off one resize to fix all videos on page load
	}).resize();

});

To use this on your own site the only thing you'd need to change is the line $fluidEl = $("body");. You'd change the selector ("body"), to whatever element on your page is the fluid width parent of the content. Perhaps that's "#main-content" or something, if the element was <section id="main-content"></section>.

A quick word on window.resize: Anytime you see functions running on the window resize event, you should have some alarm bells go off in your head. Browsers fire that particular event with different frequency. WebKit can fire it eleventybillion times during a quick little resizing, so if you do much heavy computational stuff you can see some adverse page performance. Here's a plugin from Paul Irish on "debouncing" resize to deal with that problem, which I heavily recommend.

View Demo   Download Files

I'm going to leave the "old version" inside the download too (before this article was updated) as it handles the "old" types of YouTube embeds (object/embed elements).