{"id":18311,"date":"2012-09-17T08:25:50","date_gmt":"2012-09-17T15:25:50","guid":{"rendered":"http:\/\/css-tricks.com\/?p=18311"},"modified":"2015-09-07T10:26:46","modified_gmt":"2015-09-07T17:26:46","slug":"rundown-of-handling-flexible-media","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/rundown-of-handling-flexible-media\/","title":{"rendered":"Rundown of Handling Flexible Media"},"content":{"rendered":"

When you take the responsive web design route, part of the deal is fluid grids. That is, container elements set in percentage widths. Just one example: an <article><\/code> that holds a blog post might be 320px wide on a small screen device and 690px wide on some large screen. Text can be resized and will flow nicely to fill a container. That’s not too hard. But media – images, video players, and audio players – demand a bit more attention (e.g. a video that sticks off the edge of the screen == bad). This post is to round up the methods of handling that. <\/p>\n

<\/p>\n

Flexible Images<\/h3>\n
flexible-images<\/figure>\n

If you’re comfortable with IE 7 and up support. This little beauty will do you fine:<\/p>\n

img {\r\n  max-width: 100%;\r\n\r\n  \/* just in case, to force correct aspect ratio *\/\r\n  height: auto !important;\r\n}<\/code><\/pre>\n

If you are caring about IE 7 support (I hope not, but I understand there are scenarios in which you must), use this to make sure the images survive the scale-down:<\/p>\n

img { \r\n  -ms-interpolation-mode: bicubic; \r\n}<\/code><\/pre>\n

See here<\/a> for more on that.<\/p>\n

If you need to care about IE 6 (again…) this Ethan Marcotte article<\/a> has a JavaScript solution. Kind of a bummer loading extra JavaScript for a browser that is already much slower, but c’est la vie.<\/p>\n

A shift in thinking<\/h4>\n

There was a time in which resizing images was quite the taboo. Browsers sucked at resizing images and bandwidth was being wasted. That attitude is all but gone now mostly because browsers are now pretty good at resizing images and having them look good. In fact, with “retina” displaying becoming a thing, serving too-large-for-container images is kinda good, because scaling them down makes them look all the sharper.<\/p>\n

However the bandwidth thing is still a (big) issue. Which is what makes the responsive images thing such a hot issue right now. Point is: when thinking about flexible images, work in some thinking about responsive images too. You can read more up on the current solutions to that here<\/a>.<\/p>\n

Flexible Video<\/h3>\n

Flexible video is a little more complex than images. If you are using HTML5 <video><\/code> directly<\/em>, the good news is that it holds its aspect ratio just like images do, so the same technique holds:<\/p>\n

video {\r\n  max-width: 100%;\r\n\r\n  \/* just in case, to force correct aspect ratio *\/\r\n  height: auto !important;\r\n}<\/code><\/pre>\n

However, I’m starting to think it’s a pretty bad idea to use HTML5 <video><\/code> directly. The required formats have been shifting around for years now and it’s not over yet. Add to that the fact that 1) hosting video is bandwidth intensive and expensive 2) streaming is another whole complicated beast 3) maintaining appropriate quality across formats and devices and available bandwidth is hard and 4) skinning consistant controls on the player is hard and … well … screw using HTML5 video directly. <\/p>\n

Instead, I highly recommend using a video service like YouTube<\/a> or Vimeo<\/a>. When you embed videos from these services, you embed an <iframe><\/code>. What comes inside the iframe might be HTML5 video, but you don’t have to deal with it directly. <\/p>\n

All that to say: <iframe><\/code>s have an aspect ratio problem. <\/p>\n

Thierry Koblentz solved this issue years ago in his A List Apart article Creating Intrinsic Ratios for Video<\/a>. <\/p>\n

The basic idea is that you create a video wrapper div with zero height and a top padding set in percentages. That percentage will actually be a percentage of the width, making it maintain aspect ratio. Then you absolutely position the video inside, which gives you that elusive ability to maintain aspect ratio. We’d be targeting the iframe for absolute position, as again, video doesn’t need this but iframes do. The basics:<\/p>\n

.video-wrapper {\r\n  height: 0;\r\n  padding-bottom: 56.25%; \/* 16:9 *\/\r\n  position: relative;\r\n}\r\n.video-wrapper iframe {\r\n  position: absolute;\r\n  top: 0; left: 0; right: 0; bottom: 0;\r\n}<\/code><\/pre>\n

Check out the article<\/a> on that for more nuances and details about older browser support. I also cover all of this and include some homebrew JavaScript solutions (with demos) in my .net mag article Create Fluid Width Videos<\/a>. <\/p>\n

Enough complexity, enter simplicity<\/h4>\n

If you’re using jQuery and you’ve had enough of the complication surrounding the issue of flexible width video, I invite you to try FitVids.js<\/a>. I co-authored this little jQuery plugin with Dave Rupert<\/a> to specifically deal with this problem. It uses the exact same concepts explained above, only it does it automatically. That means 1) no non-semantic wrapper in your authored markup 2) aspect ratios that match the individual video (not all videos are the same).<\/p>\n

fitvids<\/figure>\n

FitVids.js works out of the box with all the major video players and is super easy to extend to work with any player.<\/p>\n

Using Sublime Video?<\/h4>\n

I have a tutorial<\/a> on how to make their player fluid width.<\/p>\n

Using MediaElements.js?<\/h4>\n

MediaElements.js<\/a> is a very nice HTML5 video player that alleviates some of the issues I mentioned above with HTML5 video. Namely, it provides a nice consistent player skin and has the ability to fall back to older tech to play videos, like Flash and Silverlight. It’s not a total silver bullet as it doesn’t save you from the platform wars on mobile (which don’t have Flash or Silverlight generally) or help with streaming or quality issues, but it’s still nice.<\/p>\n

There is a lot of fixed pixel calculation stuff going on in MediaElements.js, but I’ve been able to force it to be fluid width in the past with some !important overrides:<\/p>\n

.mejs-container {\r\n  width: 100% !important;\r\n  height: auto !important;\r\n  padding-top: 57%;\r\n}\r\n.mejs-overlay, .mejs-poster {\r\n  width: 100% !important;\r\n  height: 100% !important;\r\n}\r\n.mejs-mediaelement video {\r\n  position: absolute;\r\n  top: 0; left: 0; right: 0; bottom: 0;\r\n  width: 100% !important;\r\n  height: 100% !important;\r\n}<\/code><\/pre>\n

Responsive Video?<\/h4>\n

Remember how responsive images is a hot topic because we’re trying to be responsible and not serve images that are un-needed-ly large? Video has that same problem only compounded by … uhm … as many frames as there are in the entire video (probably a lot). <\/p>\n

One half-janky solution is to serve different video sources depending on browser window width. I have a tutorial on that here<\/a>. <\/p>\n

Another solution is to use media attributes on the video sources and just hope that the support gets better and it doesn’t get removed.<\/p>\n

<video controls> \r\n   <source src=\"video-small.mp4\" type=\"video\/mp4\" media=\"all and (max-width: 480px)\"> \r\n   <source src=\"video-small.webm\" type=\"video\/webm\" media=\"all and (max-width: 480px)\"> \r\n   <source src=\"video.mp4\" type=\"video\/mp4\"> \r\n   <source src=\"video.webm\" type=\"video\/webm\"> \r\n<\/video><\/code><\/pre>\n

The best solution is to use a video service and they’ll handle it for you.<\/p>\n

Flexible Audio<\/h3>\n

You only “see” HTML5 audio if you specifically use the controls attribute on the element.<\/p>\n

<audio controls src=\"audio.ogg\">\r\n  <p>Fallback.<\/p>\r\n<\/audio><\/code><\/pre>\n

The good news is that you just chuck width: 100%; on that bad boy and it’ll be flexy flexy:<\/p>\n

audio {\r\n  width: 100%;\r\n}<\/code><\/pre>\n

WebKit browsers are maxing the width of them out at 800px for some reason. But the player remains centered within the space. Opera and Firefox have no such maximum. They all have slightly different players but all do basically the same thing (play the sound and have play and pause buttons and stuff). <\/p>\n

The only other very popular embedded sound player right now is the SoundCloud<\/a> player and it’s fluid width by default (go team!).<\/p>\n","protected":false},"excerpt":{"rendered":"

When you take the responsive web design route, part of the deal is fluid grids. That is, container elements set in percentage widths. Just one example: an <article><\/article> that holds a blog post might be 320px wide on a small screen device and 690px wide on some large screen. Text can be resized and will […]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"c2c_always_allow_admin_comments":false,"footnotes":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":[]},"categories":[4],"tags":[521],"jetpack_publicize_connections":[],"acf":[],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":311477,"url":"https:\/\/css-tricks.com\/a-primer-on-display-advertising-for-web-designers\/","url_meta":{"origin":18311,"position":0},"title":"A Primer on Display Advertising for Web Designers","date":"June 4, 2020","format":false,"excerpt":"A lot of websites (this one included) rely on advertising as an important revenue source. Those ad placements directly impact the interfaces we build and interact with every day. Building layouts with ads in them is a dance of handling them in fluid environments, and also balancing the need to\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2019\/11\/newspaper-stack.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":319736,"url":"https:\/\/css-tricks.com\/how-to-make-a-media-query-less-card-component\/","url_meta":{"origin":18311,"position":1},"title":"How to Make a Media Query-less responsive Card Component","date":"September 1, 2020","format":false,"excerpt":"Fun fact: it\u2019s possible to create responsive components without any media queries at all. Certainly, if we had container queries, those would be very useful for responsive design at the component level. But we don\u2019t. Still, with or without container queries, we can do things to make our components surprisingly\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/08\/recipe-card-component.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":306139,"url":"https:\/\/css-tricks.com\/a-guide-to-the-responsive-images-syntax-in-html\/","url_meta":{"origin":18311,"position":2},"title":"A Guide to the Responsive Images Syntax in HTML","date":"May 26, 2020","format":false,"excerpt":"This guide is about the HTML syntax for responsive images (and a little bit of CSS for good measure). We'll go over srcset and , plus a whole bunch of things to consider to help you get the best performance and design control from your images.","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/05\/resp-images-thumb.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":342887,"url":"https:\/\/css-tricks.com\/are-we-in-a-new-era-of-web-design-what-do-we-call-it\/","url_meta":{"origin":18311,"position":3},"title":"Are we in a new era of web design? What do we call it?","date":"June 21, 2021","format":false,"excerpt":"Una is calling it the new responsive. A nod to the era we were most certainly in, the era of responsive design. Where responsive design was fluid grids, flexible media, and media queries, the new responsive is those things too, but slotted into a wider scope: user preference queries, viewport\u2026","rel":"","context":"In "Link"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/06\/uAJDDUDLcAsLzBf0a27b.png?fit=1200%2C663&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":306249,"url":"https:\/\/css-tricks.com\/thinking-in-behaviors-not-screen-sizes\/","url_meta":{"origin":18311,"position":4},"title":"Thinking in Behaviors, Not Screen Sizes","date":"April 10, 2020","format":false,"excerpt":"Chase McCoy wrote a nifty post about the \u201cgap problem\u201d when making a grid of items. His argument might be summarized like this: how should we space elements with margins in CSS? He notes that the gap property isn\u2019t quite ready for prime time when it comes to using it\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/04\/ipad-screen-size.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":170999,"url":"https:\/\/css-tricks.com\/ideas-behind-responsive-emails\/","url_meta":{"origin":18311,"position":5},"title":"Ideas Behind Responsive Emails","date":"May 25, 2014","format":false,"excerpt":"Say you've designed an HTML email with 3 columns. Because of limited and weird CSS support in email clients, email design is done with tables. That 3 column design looks great on large-ish screens, but it squishes awkwardly on small screens. Theoretically a media query would save us here, but\u2026","rel":"","context":"In "Article"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"featured_media_src_url":null,"_links":{"self":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/18311"}],"collection":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/comments?post=18311"}],"version-history":[{"count":8,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/18311\/revisions"}],"predecessor-version":[{"id":164997,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/18311\/revisions\/164997"}],"wp:attachment":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media?parent=18311"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/categories?post=18311"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/tags?post=18311"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}