Scalable Video
It's easy to scale <img>
and <video>
elements with window width. The "max-height:
100% trick" makes this task straightforward:
img.scalable, video.scalable { max-width: 100%; }
Width (%):
It's not really a trick - it uses features that have been around in HTML
more or less forever. If you give an image height
and width
attributes,
it will scale to that size, even if that distorts the aspect ratio. However,
if you give it only one of the two values, the other will scale to match,
keeping the original aspect ratio. This behavior carries over to measurements
provided via CSS rather than as tag attributes.
When you use max-width: 100%
, and the container element becomes narrower
than the image's or video's natural size, it becomes a similar constraint
on the width, and the height scales to match. (One thing that this means
is that you're not necessarily limited to using 100%. You can set max-width
to whatever percentage you wish.)
But, when the video is embedded in an <iframe>
element,
in particular an iframe that is from a different server, things become more
difficult. You can't get inside a foreign iframe to stylize it's elements,
and iframes don't have a concept of a natural aspect ratio.
Yet another issue is that the space needed by a video won't actually have a constant aspect ratio if it has controls - the controls have a fixed height regardless of the width.
I have seen solutions that rely on padding-bottom
using a percentage,
taking advantage of the fact that vertical padding and margins expressed
in percentages are percentages of the element's width, not its height.
My experience has been that this usually requires a bit of tinkering to
get right, and adds some not-so-intuitive markup. I would like to propose
what I believe is a simpler and more robust approach. While it does add
some markup, I think that it's easier to understand what it does.
The video embedded here uses a that approach. Rather than mess around trying to break my template styles in order that the column be resizable, I added a text box that you can use to enter a width (in percent of the column width) for the video iframe. If you want to see a more dynamic, window-width-based version, see the Scalable Iframe Video page at my site.
Mocking the Video
Not, I'm not going to make fun of it - I'm going to create a mockup using transparent GIF images. The total space occupied by the video will usually consist of two pieces: the video itself, which has a fixed aspect ratio, and a controller, which will have a fixed height. The combination of those elements will therefore not have a fixed aspect ratio.
But, we can build a div using two transparent images with the expected
sizes. In the model I tested, the video has a 4/3 aspect ratio, so I used
a 420 * 315 pixel image as a mock. I also used a 420 * 36 pixel image to
mock the controls. The key aspect of the associated CSS is that the mock
image for the video itself has max-width: 100%
and no height
specification, but the controls image has the height fixed at 36px.
I put both of these in in a container div which in turn sits in a larger, outer container div, along with the iframe for the video.
The combined height of the two mock images determines the height of their immediate container. The width of that container, however, is determined by its parent.
The parent that contains the assembled mock div and the iframe has
position:relative;
, in order to serve as an offset parent to its children. The mock
div is unpositioned, so that it sits at 0,0 by default, and also serves
to determine the height of the container. The iframe, however is absolutely
positioned at 0,0, and has height and width of 100%, which is what makes
it assume the aspect ratio of the container.
<div class="vidFrame"> <div class="vid-box"> <img src="vid-mock-3x4.gif" class="vid-mock"> <img src="vid-controls.gif" class="vid-controls"> </div> <iframe width="420" height="315" src="http://www.youtube.com/embed/0WyhMV81dro" frameborder="0" allowfullscreen></iframe> </div>
.vid-box { width: 420px; overflow: hidden; max-width: 100%; } .vid-box img { display: block; width: 100%; } .vid-mock { max-width: 100%; } .vid-controls { height: 36px; max-width: 100%; } .vidFrame { position: relative; width: 420px; max-width: 100%; } .vidFrame iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }