YouTube JavaScript Iframe API, fixing random black borders

Recently I was checking out the YouTube API docs, specifically the public iframe JavaScript API. Sometimes the generic iframe embed codes aren’t enough and hence we have lovely API’s that developers can go to town on. While I was experimenting with the YouTube API I came across an interesting visual issue that kept occurring when defining width and height sizes. Random black borders, was this letter-boxing or something else?
Now the most common reason for the whole black borders issue is has mentioned above, letter-boxing. A common term to describe when a video width x height does not fit the aspect ratio its being displayed think 4:3 on widescreen. Big box of doom right? Classic example, you’ve bought a brand new HD TV that outputs at 16:9, you then watch a channel that is broadcasting something at 4:3. UGLY.
A couple of things to check first before you chase your own tail:
- What aspect ratio was the video shot in
- Determine an accurate width x height based on aspect ratio
The issue I was referring to however wasn’t your common letter boxing, instead it is something much more weirder.
First some API code:
Let me be clear, this isn’t a guide on how to use the API, but here’s some of the API code anyway to produce the issue I’m talking about.
<!-- Div that will get replaced by an iframe when JavaScript loads the API in a async method --> <div id="ytplayer"></div>
<script type="text/javascript"> var tag = document.createElement('script'); tag.src = "//www.youtube.com/player_api"; var firstScriptTag = document.getElementsByTagName('script')[0]; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); var player; var vstring = ''; // YouTube Video ID here function onYouTubePlayerAPIReady() { player = new YT.Player('ytplayer', { playerVars: { 'autoplay': 1, 'loop': 1, 'playlist': vstring, 'controls': 0, 'showinfo': 0 }, width: '315', height: '177', videoId: vstring, events: { 'onReady': onPlayerReady } }); } function onPlayerReady(event) { event.target.setVolume(0); event.target.mute(); event.target.playVideo(); event.target.setPlaybackQuality('hd720'); } </script>
This is essentially straight from the YouTube API docs, with the one modification of the appearance of a vstring variable. I add the video string in a variable, as you might potentially repeat in the same function depending on the situation, so why create two static versions? The rest of the code is just parameters and API calls, left in to demonstrate some API usage, as its a real use example in a website.
API Parameters that reveal this problem
playerVars: { 'controls': 0, 'showinfo': 0 }
With the API, various parameters have been passed, the main ones include, hiding the media controls (controls) and playlist information (showinfo). Why? Because when looping, these controls keep re-appearing on each loop before fading out again, considering the objective in most cases is for seamless playback, this will get annoying having such elements keep popping up. Doing this however, reveals the interesting black border issue. Even if you have hidden both media controls and playlist information, there is a 2 pixel gap at the bottom of the video, regardless if the aspect ratio in relation to the defined width or height is correct.
The actual cause of this? Its reserved space for the not being displayed playing bar, you’ll notice a thin red bar (default colour) a.k.a timeline moving slowly across the bottom, in normal circumstances, however it seems in this case that this space is reserved even if said element is hidden. So if your like me you might of been buggering around with various parameters for a while with no success.
The clipping method
The best way to resolve this I found was to clip the video height to work around this. You already have you containing div for where the iframe will dynamically load into, but you can actually create another div around this video container to perform the clip, heres how:
.ytclip { width:315px; height:175px; // -2px off original 16:9 height of video overflow:hidden; }
<div class="ytclip"> <div id="ytplayer"></div> </div>
Here we’ve now clipped the original height of 177px to 175px, you must use a containing div and not actually subtract the height from the ytplayer div, otherwise you’ll still get a 1px border whatever you do. You should also never change the width and height defined in the JavaScript API call to anything other than native sizing for your aspect resolution, always use CSS.
This should resolve the issue and allow you to see the video without any strange boxing or borders. You might want to use this on multiple videos that may be different sizes, in which case you might want to get creative with multiple classes, to easily apply the clipping fix.