Discussing alternatives for various sizes of the same image & introducing src property in CSS as an option

Today I was just about to write a blog post about images and serving different sizes depending on the device accessing it. Then the Adaptive images post came up on the public-html@w3.org mailing list. So let’s look at that and add my thoughts.

The problem

When we develop a web site we need to cater to a great amount of varying resolutions, and one major problem is serving images with an appropriate size (i.e. width and height – file size is a discussion for another day). We have CSS3 Media Queries helping us detect available width, like this:

.navigation {
  float: left;
  width: 300px;
}

.main-content {
  float: right;
  width: 500px;
}

@media screen and (min-width: 1000px) {
  .navigation {
    width: 350px;
  }

  .main-content {
    float: right;
    width: 650px;
  }
}

But there is unfortunately no way to load different images based on this approach.

Suggestions in the mailing list

These are two of the suggestions brought up for doing this in the HTML code, and both seem interesting:

New @srclist attribute point to list of sources

    <img src=default.jpg srclist=alternativeSizes alt="Picture of
    Unicorn">
    <sourcelist id=alternativeSizes>
    <source src="big.jpg" media="min-width: 600px" width="600"
    height="400">
    <source src="small.jpg" media="max-width: 600px" width="320"
    height="320">
    </sourcelist>

    (<sourcelist> could maybe be replaced by another existing element?
    <map>? <datalist>? SVG's <switch>?)

New image format that points to alternative resolutions

    <img src="image.list" alt="Picture of Unicorn>

    image.list:
    Content-Type: image/list

    URI: big.jpg
    media: (min-width: 600px)

    URI: small.jpg
    media: (max-width: 600px)

Alternative take, src attribute in CSS: Content or presentation?

Looking at the above examples, though (especially the first one), that’s a lot of code that has to be written. The downside of the second one is that it will be listed in a completely separate (and new kind of) file.

This led me to thinking whether various sizes of the same image is really content or presentation? And if it’s regarded as vital content, could we rely on CSS to do it anyway and have alternate text as a sufficient fallback?

My suggestion would be to have a src attribute in CSS, to combine with CSS Media Queries, and this could apply to image elements as well as video, audio and others. Then we would be able to do something like this:

.my-image {
    src: url(images/really-small.png);
}

@media screen and (min-width: 1000px) {
    .my-image {
        src: url(images/decent-size.png);
    }
}

Thoughts on this?

Looking at the suggestions in the mailing list with srclist attribute or new image (list) format, or the alternative approach with a src attribute in CSS to combine with CSS Media Queries, what do you think about them?

Pros and cons, what’s your take?

Posted in CSS,Developing,HTML5/HTML/XHTML,Technology |

44 Comments

  • Devon Young says:

    I don’t like the idea ’cause I think 99% of developers would start defining content images in style sheets, when we all agree they should be in the content.

  • Robert Nyman says:

    Devon,

    That’s the interesting discussion here, though. Since we also have a content property in CSS – even if we like it or not – I think it’s inevitable that some content will be coming from the CSS code.

    Overall, I think images in the CSS could be fine.

  • fvsch says:

    First, I’d like to point out that we should be looking at HTTP and server-side content negotiation. Sending different responses (different sizes of an image) for a given resource is trivial, and we’re not doing enough of that. Perhaps we should discuss what viewport/device information browsers could in the request’s headers? One option would be to add a HTML attribute (for instance “multiple”) that tells the browser that there are several options for that resource and that it should send relevant information in the request’s headers.
    (The image.list idea is striking because it’s implementing client-side and with 2 HTTP requests what could be done server-side with no extra request.)

    That being said, I like your idea. For UI images, it makes a lot of sense, since those images generally convey simple information (“Subscribe to RSS”, “Home”, “Next page”, etc.) and are simply a graphical representation of that information with the text written in the image or represented as a symbol. Just writing and specifying the image to use — or no image at all if we want to display and style the text itself — would be great.
    For image content though, it wouldn’t work. If you’re a big website with thousands of user profile pictures, you can’t define them all in the stylesheets. I would use a HTTP solution for that.

    Now, if we push your idea a bit further, we have the `content` property in CSS. Could we use it to replace any element’s content with a graphical representation? (The CSS3 Generated and Replaced Content is old, broken and abandoned so I have no idea if something like that was considered.)
    <a href="/" id="home-button">Let’s go home</a>

    #home-button {content: url(/images/home-button-small.png);}
    @media screen and (min-width: 1000px) {
    #home-button {content: url(/images/home-button-big.png);}
    }

  • I wrote up a (potential) future CSS3 technique addressing this: Responsive images using CSS3. It’s similar to your proposal but uses the existing content property.

    If you want to specify the new image path in the CSS, then you can already use the technique in Opera. However, it would be more practical for the alternative images paths to be included in the HTML somehow, e.g., via data-* attributes, and then use the extension to the attr() function. But a specific solution would be even better.

    However, there is still the problem of the original source image being downloaded as well as the alternative versions. I don’t see how any of the proposals from the Mailing List would get around this issue either.

    Not an obvious, backwards compatible solution to this problem if you don’t want to use server-side interceptions, etc. Great to see some work on how this could be done.

  • I wonder if you could even extend the img element to work more like video, and rely on browsers simply ignoring the closing tag (quick test in modern browsers shows it work). Would work similarly to the sourcelist idea but be quite a bit simpler.
    <img src="small.jpg" alt="">
    <source src="big.jpg" media="min-width:600px" width="600" height="400">
    </img>

  • Robert Nyman says:

    fvsch,

    Using HTTP and server-side content negotiation could definitely help and be a viable solution. I guess my view is based on a lot of scenarios where the people controlling the servers and what’s delivered is not front-end nor back-end developers, but sys admins and the likes – and overall, doing continuous maintenance there is probably not a good thing.

    Using content in future implementations could work, perhaps. But my feeling about that is that it’s more about actual content than setting attribute values.

    The multiple attribute approach is interesting!

    Nicolas,

    Thanks, and sorry for missing that post. I like that idea and contemplated the attr() approach too. My feeling, though, is that HTML code would be scattered with defining paths to 3-5 images for each image in a page, resulting in lots of extra code and maintenance.

    It definitely has the upside of being backwards compatible, though. If it’s even a possibility, perhaps web browsers should compare HTML and CSS code to avoid that extra request/download?

    The idea of source elements, like video, is interesting and consistent. Again, just afraid of lots of image paths in the HTML code, though…

  • I am too for HTTP and server-side content negotiation, it is already here and works great for deciding which language we want to see and stuff. Why not use it to decide which image we want to use?

  • Robert Nyman says:

    Jeena,

    As I mentioned above, there are many places where developers don’t have that kind of control over the servers (and why not is a different discussion).

    I just fear that it would make maintenance much worse and also ending up with people not working with the font end controlling media displayed there.

  • Kroc Camen says:

    YES. The CSS choice is the only one that scales. Your HTML, like diamonds, should be forever. When new devices come along or you’re updating an old site, it’s way easier to maintain the CSS than it is the HTML. What if all the HTML is in a database spread across millions of fields?

    The idea of embedding multiple size-information in HTML is terrible. What is that going to look like in 10 years time?

    CSS is the only way.

  • Robert Nyman says:

    Kroc,

    Glad you agree! And yes, HTML will be around for some time, and if not necessary, we don’t want to leave traces of device-specific code in there.

  • fvsch says:

    Nicolas, it wouldn’t work because HTML parsers need to know if an element is EMPTY or may have content (and a closing tag). Web browsers will read your code as:
    <img src="small.jpg" alt="">
    <source src="big.jpg" media="min-width:600px" width="600" height="400">

    where the two elements are siblings (rather than img being the parent of source). So they can’t reliably use the source element as metadata for the img element, unless they start hunting for next siblings, which would create an awful lot of implementation issues really.

    To make this idea work, you would need a different element name, say image or picture. Now, I would like to have such an element for the ability to use source and to embed rich HTML content as fallback/alternative content, but I doubt it will happen… and it’s not backwards compatible anyway. Also, for the audio and video elements the HTML5 spec says that embedded content (outside of source) is fallback content for old user agents, and not alternative content, so it’s not worth the hassle of introducing a new element I guess.

    On a side note, I’ve read today that some browser (Firefox or Chrome, not sure) recently implemented a JS API to test media queries. I need to dig out the relevant spec fragment or technical blog post.
    An extreme client-side solution would not define any source, putting everything in data-attributes, and using JS to test media queries and assign the right src.

    @Kroc Camen:

    The CSS choice is the only one that scales.

    Not really. If you have 5 million users and they each have a profile picture, which you want to provide in 3 sizes… do you write a CSS stylesheet that’s 15 million lines? That would be fun. ;)

    A CSS solution would work for UI images, because they’re limited in number. A HTTP solution would work for large scale stuff, including Flickr or 500px.com content for instance. So we probably need both (or some HTML/JS trickery instead, perhaps).

  • @fvsch There is still active work being done on generated and replaced content specs – http://dev.w3.org/csswg/css3-content/

    @robert The content approach works with or without specifying alternative paths in the HTML. This will work in Opera, today, and is still backwards compatible because it doesn’t affect the original source.

    @media screen and (min-width: 600px) {
    .my-image {
    content: url(images/decent-size.png);
    }
    }

    In addition to the problem of having 2 HTTP requests, if you right-click to copy or view the image it will show the source image and not the CSS-based replacement image. So, still pretty rough around the edges.

  • Robert Nyman says:

    fvsch,

    Hmmm. Yeah, if it works like that as siblings, it’s definitely a downside.
    With JS API I guess you’re thinking of window.matchMedia().

    Regarding profile pictures and such it could still be CSS, but just included with a style element in that document, in the head section, for instance.

    Nicolas,

    Ah, right, ok. Well, if the HTTP requests and rendered image at interaction things would be worked out, that could very well work (even though I’m not sure content is the fitting property name)!

  • Jos Hirth says:

    If we look at existing approaches (creating some kind of profile and syncing it between client + server or just using simple scaling), the obvious issue is that there isn’t a way to specify the aspect ratio.

    E.g. if the image is 640×480 and you set the width to 320px, then the image’s dimensions will be 320×240. However, the height is unknown until the headers arrived.

    If we could mention beforehand that the image’s aspect ratio is 640:480 (or 4:3 – same thing), the UA could figure out the size right away and there wouldn’t be a reflow + redraw necessary.

    This would be very handy for SVGs, too.

    Other than that we don’t really need anything completely new for this. CSS3’s generated content, data attributes, and CSS*’s variables/math can pretty much do whatever you might want to do.

    Well, there is a way to get that aspect ratio stuff working right now. You can use transparent inline images or even SVGs.

    For example, this horrible construct:

    <img src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22640%22%20height%3D%22480%22%2F%3E"/>

    Creates a 4:3 (640×480) img node whose background or src can be set/replaced with whatever you want.

    Combining this with Nicolas Gallagher’s suggestion would already do the trick, I daresay.

  • Mardeg says:

    Well this seems to be completely ignoring the ability of all modern browsers now have to view the same SVG at different sizes perfectly well! There is already webpage authoring software (BlueGriffon) that lets you edit SVG directly, and I think binary formats are overly used anyway.
    It’s sad that instead of improving the adoption of an existing format designed for this use case they want to change the rules in a way that will delay that adoption further.

  • Yes, the proposal is clearly mixing CSS MQ and content for something that should be stylistic. Your alternative approach is much better and is contained in a CSS 3 draft…

    Daniel Glazman
    W3C CSS WG, Co-chairman

  • Images are often one-off on a site, so the abstraction that CSS gains you would really just be indirection in such a case. Whatever the approach it should be easily typed inline, as well as in external CSS files.

    (there was that HTML 2 <img> attribute of lowsrc but let’s ignore that for now)

    The img tag has always been a single childless node, so adding child elements to it seems kind of odd. I’d prefer attributes. E.g. data-src-gt-1000=”/logo.png”.

    When it comes to Print CSS then presumably the browser would know the DPI of the printer and it could just choose an appropriately highres image.

  • Yoav Weiss says:

    Interesting approach to a well known problem, but my main grief with it is the fact that it will make CSS as uncacheable as HTML currently is.
    Imagine a CNN-like page that changes images every 1-2 hours. We would need a special separate CSS page that maintains the images’ data that would have the same cacheability as the HTML (i.e. None).
    Here’s my proposal for this adaptive images mess: http://blog.yoav.ws/2011/05/My-take-on-adaptive-images

    Would highly appreciate your opinion!

  • Gonzo says:

    Although I find the server-side content negotiation the perfect solution, it wont work for the same reason language negotiation does not work. Because most of the people, creating or authoring websites do not understand the HTTP protocol. Since when you haven’t seen a website using language negotiation? We match IP addresses to country to language, save cookies or settings in the database… Actually we have content negotiation for the image format, but has anyone used it? And we can use that to serve WebP images to browsers, that support them, and fall back to JPEG or even BMP for other UA. But that was comment for another post.

    Robert, I don’t like your suggestion to pot the image in the CSS. If the image is decoration, it should be in CSS as background already, and if it is content, it belongs to the HTML.

    I find the problem with image sizes for mobile vs desktop users to be exaggerated. I mean, is it OK to serve 5 or 8 megapixel image over the web? If it’s not OK for users of mobile devices, why is it OK for desktop users? We are searching for solution to a problem that is still not well defined. If one is going to server different content to different devices, he can use WURFL, serve custom markup and different images to different devices. If we are serving the same markup and the same content, why not serve the same images? If there is concern about file sizes and traffic, use small images and link to the big one.

  • Robert Nyman says:

    Jos,

    Interesting about aspect ratio! Maybe DPI could be a factor as well that one might want to take into consideration.

    I think content propery and attr() function works, but it doesn’t feel really right for me.

    Mardeg,

    SVG is a great format and I’d like to see it used more! However, for all kinds of photographs and such it’s really not an optimal format.

    Daniel,

    Good to hear!
    I’d love some more information about that if/when you have it.

    Matthew,

    Yes, good old lowsrc was an interesting thing. :-)
    I think there could be some gain with CSS, though, and having specific pixel values in the HTML could be risky.

    Yoaw,

    Thanks for the suggestion, and I commented on your post.
    I’ll echo what i wrote there:

    My suggestion is that it doesn’t necessarily has to be in a CSS file for those cases you mention: if it’s a very dynamic web site it could be in a style element in the head section. Preferred, naturally, is the CSS file, though.

    Gonzo,

    I definitely agree about the problems you mention with doing this server-side, and the reason it won’t work.

    It’s a good point about image sizes and I agree we shouldn’t use enormous images on the web. It still doesn’t help with the fact that with a larger resolution optimized for desktop and the like will automatically have a larger file size.

    But it’s also about offering images in an optimal format for the end user device, and not just rescaling an existing one. So, I still think it is an important question, to make it in the most suitable way.

  • Arjan says:

    I think it should remain in HTML. Why not introduce a new element that can handle fallback?

    <image>
    <source src=”foo.webp” media=”screen and (min-width: 1000px)”>
    <source src=”foo-large.jpg” media=”screen and (min-width: 1000px)”>
    <source src=”foo-small.jpg” media=”screen and (max-width: 1000px)”>

    <img src=”fallback.gif”>
    </image>

  • Gonzo says:

    Robert, I think that if it’s about optimal image format, there is content negotiation. If it is about image dimensions, I don’t know… Arjan’s proposal looks promising.

  • Gerben says:

    If an image is inside the html, it’s not presentational. If it was it should have been in the CSS. So the CSS solution seems odd to me. Let alone the nightmare of having to change the html and css if you add an image (which makes the css less cachable).

    On way is to do the same as the video element with mulitiple sources having a media attribute. Since the is self closing, reusing it will break backward compatibility. So a new element has to be created. I like Arjan’s idea. This solution could also let browsers automatically download a bigger image if the user makes the browser-window bigger. (Or a “download large version” might be added to the context menu, also useful on handhelds)

    The other solution is server side. But for the server to decide which image to send it has to get some info about the current page. The browser could send all the variables that can be used in mediaqueries. Something like “x-media-info: width=320; device-width=320; height=408; device-height=480; pixel-density=2″

    Or maybe info about the dimensions of the image as set in the implied css.
    so , will result in a header like “x-dimension: width=300; height=200;”
    If the image hasn’t been given a explicit size; the browser could sent the maximum size the image can be in it’s current container. So will result in something like “x-dimension: max-width=300″

  • Gerben says:

    If an image is inside the html, it’s not presentational. If it was it should have been in the CSS. So the CSS solution seems odd to me. Let alone the nightmare of having to change the html and css if you add an image (which makes the css less cachable).

    On way is to do the same as the video element with mulitiple sources having a media attribute. Since the is self closing, reusing it will break backward compatibility. So a new element has to be created. I like Arjan’s idea. This solution could also let browsers automatically download a bigger image if the user makes the browser-window bigger. (Or a “download large version” might be added to the context menu, also useful on handhelds)

    The other solution is server side. But for the server to decide which image to send it has to get some info about the current page. The browser could send all the variables that can be used in mediaqueries. Something like “x-media-info: width=320; device-width=320; height=408; device-height=480; pixel-density=2?

    Or maybe info about the dimensions of the image as set in the implied css.
    so <img src=”sample.jpg” sendcontextinfo=”” style=”width:300px; height:200px;” />, will result in a header like “x-dimension: width=300; height=200;”
    If the image hasn’t been given a explicit size; the browser could sent the maximum size the image can be in it’s current container. So <div style=”width:300px”><img src=”sample.jpg” sendcontextinfo=”” /></div> will result in something like “x-dimension: max-width=300?

    edit preview showed the html-code correctly, but it got stripped on submit. I should have read the comment info more carefully.

  • Robert Nyman says:

    Arjan,

    I don’t think a new element would be needed for that – why not just extend img? But overall that would work fine in general, but with a page with maybe 50 images, it’s a lot of bulk HTML to load, especially since it won’t be cached in most cases.

    Gonzo,

    I don’t believe in server-side negotiation, for the things you mention plus the fact that a lot of web developers won’t have the access to do that.

    Gerben,

    Yes, I think one of the big discussions here is rather if you can have any type of image in the CSS or if you mix layers in a bad way.

    Regarding img and backwards compatible: would it be so hard for web browsers to see if there are any children elements, and if not, just self-close it?

    I do like the idea about web browsers sending their dimensions (default or set through CSS), even if it might not be the solution for this problem.

  • Jos Hirth says:

    >why not just extend img?

    That would be an option if we were using XML. With XML <img/> and <img></img> are exactly the same thing.

    So, if we would add some children, they would be indeed children of the img node.

    With this SGML-based tag soup, however, a tag is either empty or it isn’t. img elements are defined as empty. As such, they cannot have any children. The tag is auto closed, the children are added as siblings, and the final closing </img> tag is discarded as unexpected garbage.

    The only way to extend it are attributes.

  • Robert Nyman says:

    Jos,

    In general, yes, XML could have handled that. But with new HTML5 parsers in web browsers, which aren’t SGML-based, I was thinking it could be an option.

    However, since the parsers need to be backwards compatible, the problem might still be there though…

  • Jos Hirth says:

    Well, all current (100% correctly working) HTML5 parsers ensure that img nodes are empty, because that’s how they were defined.

    They reach the end of the opening img tag and that’s it. No matter if there is a slash or not – they are done with the tag. Case closed.

    Those other nodes which were supposed to be children are now added as siblings by the parser and that final closing tag is simply discarded.

    Adding this feature would break backwards compatibility completely. This won’t ever happen.

    You can add children via JS though, but that doesn’t look very useful.

  • Jarvklo says:

    Interesting discussion. I personally lean towards craving something along the lines arjan describes above – a new element with an img fallback.
    That would be great!

    However

    I would like to suggest we keep the media query stuff (presentational as Mq:s IMHO are) in CSS and would prefer to handle image variant selection solely in CSS –
    So arjans suggestion minus the @media part where we can select image variant via CSS display: (using the source element @class, @id or other generic attributes for selection (and the img fallback as the initially visible variant)) would get a humble +1 from me…

  • nemo says:

    What I like about the non-CSS syntax, is that not only would it offer sane fallbacks regardless of CSS support, but you’re finally offering child elements for [img /]
    If only the “syntactic sugar” of [/] had existed in HTML, it would have been easier to extend [img /] to have:
    [img src=”foo.jng” ]
    [img src=”foo.png]
    alt text
    [/img]
    [/img]

    Anyway, now that you guys are formalising child tags of images, perhaps fallbacks can finally work.
    [object]
    [object]
    alt text
    [/object]
    [/object]

    always worked, but not as well integrated as [img].

  • karl says:

    ahah you have forgotten HTTP content negotiation ;) with Alternates.

  • +1 on Gerben’s suggestion for the x-media-info HTTP header. In mobile web sites, you often want to serve an image that is exactly as wide as the display (or a percentage thereof). Media queries won’t work, since that would require one media query for every possible image size.

    Currenly, we’d have to generate HTML or CSS on the server side, e.g. with HTML like:<img src=”image.png?width=”>

  • That was supposed to be <img src=”image.png?width=<%=device_width%>”>
    (or the corresponding CSS)

  • Robert Nyman says:

    Jos,

    Shame, but makes sense. And I agree, just doing it via JS is not an optimal approach.

    Jarvklo,

    Interesting. I think it could work and I’m not really a big fan of having media queries in the HTML code either.

    nemo,

    Good point. There are definitely other use cases where children elements of an image would make things better.

    karl,

    Nope. :-) As mentioned in some of my comments above, there are many cases/situations where it’s not an option for the developer.

    Martin,

    Yes, such a header would be useful, but not the solution to all problems, I think.

  • […] Discussing Alternatives For Various Sizes Of The Same Image & Introducing src Property In CSS A… by Robert Nyman […]

  • […] through CSS content like Nicolas Gallagher suggested. It might be the element. It might be a srclist attribute in HTML or src property in CSS. It might be a […]

  • […] content like Nicolas Gallagher suggested. It might be the <picture> element. It might be a srclist attribute in HTML or src property in CSS. It might be a […]

  • I was thinking about this problem this week, and independently arrived at a solution that’s the same as your first one: http://www.broken-links.com/2012/06/14/a-notional-proposal-responsive-images-syntax/

    I think this problem is already well resolved in CSS using the srcset property, so what we’re looking for now is a solution in HTML, which I think seems answered by our syntaxes.

  • […] out to me that I have?—?completely independently?—?arrived at a solution very close to one proposed by Robert Nyman. That makes me think I may be on the right […]

  • Robert Nyman says:

    Peter,

    Nice! Thanks for sharing, and for letting me know! Will be interesting to see how this evolves!

  • […] p.s. Also, some great articles on the subject by Mat Marquis, Chris Coyier & Robert Nyman. […]

  • […] Nicolas Gallagher suggested. It might be the <picture> element. It might be a srclist attribute in HTML or src property in CSS. It might be […]

  • […] p.s. Also, some great articles on the subject by Mat Marquis, Chris Coyier & Robert Nyman. […]

  • […] content like Nicolas Gallagher suggested. It might be the <picture> element. It might be a srclist attribute in HTML or src property in CSS. It might be a […]

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>