11

Our client wants to have a different banner image on smaller screens than on larger screens. Not just shrink/stretch to fit, but actually substitute a different image. The full-size image is fairly complex -- several people, two logos, and some decorative text -- and so for the smaller image they want to crop out some of the people, drop the logos, etc. So they want the biggest, most complex image for desktops, a smaller simpler image for mid-size devices, and then smaller and simpler still for the smallest.

What is the best way to do this?

My first thought is to include all three images, and use @media min/max widths to make two of them invisible at any given size. Like:

@media (max-width: 400px) { .smallimg {display: block} .midimg {display: none} .bigimg {display: none} }
@media (min-width: 401px) and (max-width: 700px)  { .smallimg {display: none} .midimg {display: block} .bigimg {display: none} }
@media (min-width: 701px)  { .smallimg {display: none} .midimg {display: none} .bigimg {display: block} }

This ought to work but it would download all three images every time, which seems rather a waste of bandwidth.

I could change the images from img tags to css background images. Would that be better? Would that avoid downloading all three or would it still do that?

I was thinking of writing some JavaScript to dynamically update the URL in the img tag based on the screen size, but that seems like a bunch of complexity.

I briefly thought of making the logos and text separate images and breaking the actual picture into pieces and then trying to assemble them all as overlapping images. But that sounds like a lot of work to get right, and then I'd have to make sure it looks right at all possible sizes, not so easy to just shrink or stretch, etc. And while it's probably do-able in this particular case, I'd prefer a general solution that I can use in the future.

Anybody done something like this and have some ideas about the best way to do it?

Jay
  • 26,876
  • 10
  • 61
  • 112
  • Why don't you test it? Just set some images as backgrounds and hide them. Then you can check from the browser whether you are actually doing the request for the hidden div or not. – Francisco Presencia Mar 26 '14 at 17:26
  • 2
    @FranciscoPresencia Using background images will not load the images if the block is hidden (see http://stackoverflow.com/questions/12158540/does-displaynone-prevent-an-image-from-loading). – Albert Xing Mar 26 '14 at 17:27
  • @Jay If the smaller images are "crop"s of the largest image you can load the largest image as the background of the banner once and use background size and background positioning for different screen sizes to prevent loading of several images. – Arbel Mar 26 '14 at 17:37
  • Could you change the z-index or opacity of each image? That way they don't have to reload due to 'display: none'. Just a thought. – Kevin Mar 26 '14 at 17:40
  • 1
    http://mobile.smashingmagazine.com/2013/07/22/simple-responsive-images-with-css-backgrounds/ – Stephen Thomas Mar 26 '14 at 17:43
  • @arbel Possibly. But it's not trivial because the cropping has to go in jumps. That is, I'd have to say something like, Under 200 pixels take just the left 50%, 200 - 300 take the left 75%, above 30 take 100%. Then I'd have to overlay the logos and text on top of that. Then everything has to resize as the window grows or shrinks within each range. I'm sure it can be done but it would not be a re-usable solution: slightly different images and I'd have to do it all over again. – Jay Mar 26 '14 at 18:09
  • @jay maybe check http://bassjobsen.weblogs.fm/responsive-banner-ads/ and http://bassjobsen.weblogs.fm/responsive-banner-ads-2/ and http://timkadlec.com/2012/04/media-query-asset-downloading-results/ – Bass Jobsen Mar 26 '14 at 20:09

2 Answers2

4

you may use css background in media queries. The images are only loaded if the CSS requires it to be, so if nothing matches the selector then it won't bother loading the image.

This article will surely help you.

Karan Thakkar
  • 1,492
  • 2
  • 17
  • 24
  • possible duplicate of http://stackoverflow.com/questions/9506069/media-queries-and-background-images – Karan Thakkar Apr 11 '14 at 10:55
  • This does have the catch that if the user prints the web page, then unless they have background image printing turn on -- and by default it's off -- the image will not appear. – Jay Apr 22 '14 at 13:11
  • on which device or browser ? @Jay – Karan Thakkar Apr 23 '14 at 07:06
  • Is this not true of all browsers? I know it's true of IE and I thought it was true of Firefox. I haven't consciously experimented with other browsers or devices. – Jay Apr 23 '14 at 13:43
  • @Jay property `backgroud-image` is supported in all all browsers like FF, Chrome, opera, android, IOS and so on. i guess it has issues when its < IE8 or so. check this http://caniuse.com/#feat=background-img-opts – Karan Thakkar Apr 24 '14 at 07:36
  • 1
    Wait, the key word in my post was "prints". Yes, background-image is supported in all major browsers today. But when the user PRINTS an image, as opposed to displaying it on the screen, the default behavior in at least some browsers is to not print the background image. I presume on the reasoning that a "true" background-image is, well, a background, something decorative, which just tends to clutter up a printed page. – Jay Apr 24 '14 at 14:19
  • @Jay you can use solutions like `-webkit-print-color-adjust: exact;` for backgrounds or `@media print`check this one http://stackoverflow.com/questions/6670151/how-can-i-force-browsers-to-print-background-images-in-css it will surely help. i hope this time i haven't misunderstood :P – Karan Thakkar Apr 25 '14 at 04:31
  • Using
    tag instead of image tag, won't work on smaller samsung devices and iphone devices. The image won't fit in the screen. The image will get cut on the right hand side.
    – AnKr Jul 24 '18 at 11:25
1

I would checkout Zurb Foundation's Interchange for handling responsive images. The best cross browser approach i have found.

http://foundation.zurb.com/docs/components/interchange.html

s_cicero
  • 155
  • 11