Sunday, March 16, 2014

Make Getty Embeds Responsive

In my post What to Consider before Using Free Getty Images one of the many caveats I outlined was the lack of responsive support in Getty's iframe code. Of all the issues I raised, this one is actually pretty easy to get around.

Background

While the other points still preclude me from readily using Getty image embeds, I recognize its value to clients and want to be able to allow them to use these images without fear of breaking the responsive sites we've coded. I also wanted a solution that won't require my clients to do any extra work, such as embedding HTML wrappers, adding classes or IDs, inline script, or generally mucking about in code.

If you've read at least a few of my last 15 years of writing, you might know I have a general aversion to scripted solutions and generally start trying with a CSS solution. At first glance, there is an example dating back five years at A List Apart that I thought might work, Creating Intrinsic Ratios for Video.

Another post tackled other embeds (Vimeo, Slideshare) in 2011 using the same technique expanded just a bit. Five years on and a new article popped up (just a couple weeks ago, Making Embedded Content Work In Responsive Design) that is targeting more third-party embeds (calendars, Google Maps), but leans on the A List Apart technique — and by leans on I mean just uses it outright but for more services.

The A List Apart solution and its variations don't work for two reasons: 1) they violate my requirement of not making my authors create HTML and 2) they rely on knowing the ratios. Every Getty image can have its own aspect ratio that I can't expect my authors to calculate.

The Getty embed has another factor not accounted for in these other solutions — regardless of the image aspect ratio, there is always a credit box below the image at a seemingly fixed height. This bar will always occupy that height, so scaling the image's height based directly on its width ends up leaving an ugly vertical white bar on the right of the image. This precludes any simple ratio as a solution.

My Solution

I made a demo to show my solution (does not open in a new window).

I decided the best approach was to write a JavaScript function that accounted for the height of the image credit as it calculated the image ratio. Then it would apply width and height styles that would scale the embed without leaving the ugly white gap on the right (barring rounding errors, which are evident in the portrait images).

I opted for JavaScript instead of a block of jQuery because I knew this would be maybe a dozen lines of code in total, and requiring an additional 29-82KB (depending on your minification and zippage) for the jQuery library is, well, absurd. Also, I am not a fan of dependencies, particularly when most developers rely on hosted libraries.

I did some screen captures of Getty image embeds and identified the image credit bar is 69 pixels tall. That number may (will) change in the future. You may want to populate that variable from your chosen CMS so you don't have to do a full testing and deployment pass just to update one variable in your JavaScript functions file or page template (across all your sites) when Getty inevitably changes it.

The Getty iframe has no unique ID or class to make it easy to identify on the page, nor any other unique attributes, with the exception of the src attribute. So I loop through all iframes on the page and only grab those with the Getty URL.

I then get the iframe's width and height attributes, subtracting 69 from the latter, and calculate the ratio. From there I scale the iframe to 100% width and then get its new pixel width to feed to the ratio to calculate what its new height should be, finally adding 69 to it.

In my example page, I call the function at the bottom of the page and also in an onload in the body. There are better ways to do this, but given all the variations that are already out there (and that you may already employ), I leave it to you to figure out the best approach to handle for users who resize windows or rotate their phone/tablet.

What is compelling to me about this solution is that my clients (site authors) don't need to worry about adding or modifying any HTML on the page (most don't know HTML anyway), let alone CSS or script. When they paste the embed code, it should just work.

The Code


function responsiveGetty() {

  try {
    // Get all the iframes on the page.
    var iframes = document.getElementsByTagName('iframe');

    // Height in pixels of the Getty credits/share bar at the time of this writing.
    var crHeight = 69;

    for(var i = 0; i < iframes.length; ++i) {

      // Check to see if it's a Getty embed using the only attribute that's unique, the src.
      if(iframes[i].src.indexOf("//embed.gettyimages.com") != -1) {

        eachIframe = iframes[i];

        // Get the current ratio after excluding the credit bar.
        picHeight = eachIframe.height - crHeight;
        picRatio =  picHeight / eachIframe.width;

        // Set the iframe to fill the container width.
        eachIframe.style.width = "100%";

        // Set the iframe height to correspond to the ratio, adding back the credit bar height.
        eachIframe.style.height = ((picRatio * eachIframe.offsetWidth) + crHeight) + "px";
      }
    }
  } catch(e) {}
}

responsiveGetty();

Feedback

There are probably ways to optimize my code or factors I did not consider. If you see something wrong or that could be improved, leave a comment.

No comments:

Post a Comment