Other fixed-width assets
Images aren’t the only asset that present some problems for responsive sites. Let’s look at two in particular: video and advertising.
Video
Embedding videos in a responsive site is, perhaps surprisingly, a little more complicated than it first appears. If you’re using HTML5 video, it’s simple. You can use the same max-width technique we discussed for making images fluid:
1.
video{2.
max-width: 100%;3.
height: auto;4.
}
Most sites, however, pull their videos from a third party (YouTube or Vimeo, for example) using an iFrame. If you apply the same trick, the width scales but the height retains its original value, breaking the aspect ratio (Figure 4.7).
Figure 4.7. Unfortunately, using max-width: 100% and height: auto on video embeds will result in the video breaking the aspect ratio.
The trick is something Thierry Koblentz called “intrinsic ratios.”5 The basic idea is that the box that contains the video should have the proper aspect ratio of the video (4:3, 16:9, and so on). Then, the video needs to fit the dimensions of the box. That way, when the width of the containing box changes, it maintains the aspect ratio and forces the video to adjust with it.
The first thing to do is create a wrapping element:
1.
<div class="vid-wrapper">2.
<iframe></iframe>3.
</div>
The wrapper serves as the containing box so it needs to maintain the proper aspect ratio. In this situation, the aspect ratio is 16:9. The video itself is positioned absolutely, so the wrapper needs an adequate amount of padding applied to maintain the ratio. To maintain the 16:9 ratio, divide 9 by 16, which gives you 56.25%.
1.
.vid-wrapper{2.
width: 100%;3.
position: relative;4.
padding-bottom: 56.25%';5.
height: 0;6.
}7.
.vid-wrapper iframe{8.
position: absolute;9.
top: 0;10.
left: 0;11.
width: 100%;12.
height: 100%;13.
}
The styles above also position the iFrame absolutely within the wrapper and set the height and width to 100% so it stretches to fill (lines 11–12). The wrapper itself is set to 100% of the article’s width (line 2) so it adjusts as the screen size adjusts.
With these styles in place, the video responds to different screen sizes while maintaining its original aspect ratio.
Enhancing the experience
As always, it’s worth taking a step back and considering how the experience can be enhanced. At the moment, the video is being downloaded on all devices. That might not be the best approach for the base experience. To speed up the core experience, it would be nice to display only a link to the video. Then, for larger screens, the video embed could be included.
To do this, start with a simple link:
<a id="video" href="http://www.youtube.com/watch?v=HwbE3bPvzr4"> Video highlights</a>
You can also add a few simple styles to make sure the text link doesn’t look out of place:
1.
.vid{2.
display: block;3.
padding: .3em;4.
margin-bottom: 1em;5.
background: url(../images/video.png) 5px center no-repeat #e3e0d9;6.
padding-left: 35px;7.
border: 1px solid rgb(175,175,175);8.
color: #333;9.
}
There’s nothing too fancy going on here. We gave the link a little padding and margin to set it apart from the rest of the content, and applied a background with a video icon set to the left (Figure 4.8).
Figure 4.8. With some styles in place, the video link fits nicely in with the rest of the page.
Now, with JavaScript, convert the link to the appropriate embed.
Add the following function to the Utils object in yass.js:
1.
getEmbed : function(url){2.
var output = '';3.
var youtubeUrl = url.match(/watch\?v=([a-zA-Z0-9\-_]+)/);4.
var vimeoUrl = url.match(/^http:\/\/(www\.)?vimeo\.com /(clip\:)?(\d+).*$/);5.
if(youtubeUrl){6.
output = '<div class="vid-wrapper"><iframe src="https:// www.youtube.com/embed/'+youtubeUrl[1]+'?rel=0" frameborder="0" allowfullscreen></iframe></div>';7.
return output;8.
} else if(vimeoUrl){9.
output = '<div class="vid-wrapper"><iframe src="https:// player.vimeo.com/video/'+vimeoUrl[3]+'" frameborder="0"> </iframe></div>';10.
return output;11.
}12.
}
Let’s walk through the function.
The function takes the URL of the video as its only parameter. It then determines if the URL is a YouTube video or a Vimeo video using regular expressions (lines 4–5). Depending on the URL type, it creates the embed markup including the containing element and returns it (lines 5–11).
Armed with the getEmbed function, it’s easy to convert the video link to an embed. Throw the following JavaScript within the matchMedia("(min-width: 37.5em)") test:
1.
//load in the video embed2.
var videoLink = document.getElementById('video');3.
if (videoLink) {4.
var linkHref = videoLink.getAttribute('href');5.
var result = Utils.getEmbed(linkHref);6.
var parent = videoLink.parentNode;7.
parent.innerHTML = result + videoLink.parentNode.innerHTML;8.
parent.removeChild(document.getElementById('video'));9.
}
The first two lines grab the link to the video and the link’s href. On line 5, the link is passed to the getEmbed function we created. Once you have the result, lines 6–8 insert it into the article and remove the text link (Figure 4.9).
Figure 4.9. On large screens (right) the video is embedded but small screens will see a link to the video instead.
Now the video embed is responsive, and is pulled in only when the screen size is greater than 37.5em, ensuring that the base experience won’t need to make the expensive HTTP requests to embed the video.
Advertising
Another fixed asset that presents some difficulties is advertising.
Like it or not, advertising is a key part of many businesses’ revenue stream online. We won’t get into a debate here about advertising-based revenue versus the pay-for-content model; that’s a discussion that gets ugly quickly. The reality of the matter is that for many businesses, ad revenue is essential.
From a purely technical standpoint, advertising in a responsive layout isn’t that difficult to implement. You could use JavaScript to conditionally load an ad unit based on the screen size. Rob Flaherty, a developer in New York City, demonstrated a basic method:6
1.
// Ad config2.
var ads = {3.
leaderboard: {4.
width: 728,5.
height: 90,6.
breakpoint: false,7.
url: '728x90.png'8.
},9.
rectangle: {10.
width: 300,11.
height: 250,12.
breakpoint: 728,13.
url: '300x250.png'14.
},15.
mobile: {16.
width: 300,17.
height: 50,18.
breakpoint: 500 ,19.
url: '300x50.png'20.
}21.
};
This configuration sets up three different ads (leaderboard, rectangle, and mobile). Each ad has a width (lines 4, 10, and 16), height (lines 5, 11, and 17), URL (lines 7, 13, and 19), and breakpoint at which point the ad should load (lines 6, 12, and 18). You could use the matchMedia function to determine which ad should be loaded based on the breakpoint.
Even better, the ad itself could be responsive. It could consist of HTML and CSS that allow it to adjust to different screen sizes. Going this route would eliminate the JavaScript dependency and potentially allow the ad to do some cool things by playing on its interactive nature.
From a technical perspective, neither of these options is particularly difficult. The problem is that creating and displaying an ad has a lot of moving parts.
Most ads are served by third-party networks or the creative pieces are developed externally and then submitted according to the specifications of the site. At the moment, no major ad-serving networks accommodate varying ad sizes based on screen size.
Using an internal ad serving platform is a bit more flexible, but if the creative is developed outside your company, then you’ll need to be willing to do some education. The people creating the ad materials may not be up to speed on what’s going on.
More importantly, ads are currently sold much like they are in print: You pay based on the size and placement of the ad. So how exactly do you do that when the size and placement vary?
One solution is to sell ad groups instead of ads. For example, instead of selling a skyscraper ad, you sell a Premier Group ad (or whatever you want to call it). The Premier Group may consist of a skyscraper for screens above 900px wide, a boom box for screens above 600px but below 900px, and a small banner for screen sizes below that point.
Obviously, this won’t be an easy transition. Creative teams, decision makers, and the salesforce all need to be educated on why this approach makes more sense than buying a defined ad space. It won’t be an easy sell, but with time it should get easier.
The other consideration here is that some companies may want to target only a single form factor. Perhaps their service is something specific to mobile devices, and they decide they’d only like to serve their ads to those smaller screens. That of course throws a little wrinkle into the ad groups, as things start to get broken up.
Ultimately, I’d like to see the discussion of responsive advertising lead to fewer ad spots and a higher cost per ad. Sites whose revenues are ad-based frequently overload their pages with a plethora of ads. This makes the situation more difficult when trying to handle the small-screen experience. Do you hide all those ads, thereby limiting page views for your advertisers, or do you cram them all in there and ruin the experience for your visitors?
Instead of loading up pages with more and more ads, reduce the amount of ads on a page. Instead of ten ad slots at $1,000 per month, offer three at $4,000 each. Make the ad spaces something worth coveting. It benefits advertisers because they have fewer ads competing for attention, and it benefits users because they are greeted with a much better experience.
Unfortunately there’s a chicken and the egg problem: advertising rates are currently a race to the bottom. Ads struggle to get quality click-through rates so the way to compete is to see how far you can lower the cost of entry. Someone has to be bold enough to make that first step.