I think the answer is SVG for anything we've got vectorized, and I've started delving more deeply into the format, which turns out to be pretty awesome.
First, to create them, I draw icons with vectors at the actual size the final icon will be rendered on regular non-retina displays, then export as SVG with Illustrator. But what I really want are the paths; fill and stroke colors and shading effects can be added manually.
Then, I open the SVG output in a text editor, and since it's all XHTML formatted, I can easily modify everything to get the look I want. I can re-organize the path and fill elements, change their fill colors, and add things like shadows right in the SVG file as filter elements, in case your editor makes sub-optimal choices as to how to encode your design.
These icons look perfect when rendered on both normal screens at 1x and retina displays at 2x resolution. If I needed an in-between size, I'd have to design a new vector for the new target size. One vector design will typically not work well for different rendered sizes at this small scale, as every pixel counts, and anti-aliasing does more harm than good. That problem is just unavoidable, even when you try to make a flattened PNG at all these in-between sizes.
I've also found SVG ideal for small bits of text with special non-web-safe fonts. Converting text to paths and exporting to SVG is the way to go over gif or png text, and looks great on retina displays.
OK, I take back what I said. SVG can be used to create a single asset that looks good at ALL resolutions; it's just going to take some work and possibly add too much bloat to be worth it in some cases.
So let's say you have a 16px icon design, with an element 7px wide, and you want a 24px version of that icon. The problem is when you scale an odd-numbered-height or width element by a factor of 1.5 in this example, you get an element with a height or width defined as a non-integer (10.5px wide in this case), which is when anti-aliasing kicks in and replaces that extra .5 pixel of element and .5 pixel of background with one pixel of element at half opacity. this makes it look fuzzy.
What you need to do is have a media query like this in the SVG file:
<style>
@media screen and (max-width: 24){#element {width: 10px}}
</style>
Or maybe:
@media screen and (max-width: 16){<shape id="element" width="7px"</shape>}
@media screen and (max-width: 24){<shape id="element" width="10px"</shape>}
I haven't played with it to be sure yet, but something like that might allow you to set the width, height or radius to an integer for the sizes you care about.
Complex paths would still likely need to be redrawn for various target sizes to get rid of the more egregious anti-aliasing issues. In that case, we're adding bloat to everyone's SVG files to serve the needs of different clients. Maybe we're still better off with different SVG files served to different clients when we pass a certain threshold of duplicated content within the SVG, and duplicated paths would seem to me to be in danger of crossing that threshold.
I'm curious if there are any standards for "patching" vector graphics. So you could download the base SVG and a separate vector and/or bitmap-based patch to produce something appropriate for the resolution. (As well as being appropriate for the bandwidth constraints etc.)
The patch could be downloaded simultaneously or progressively, i.e. after the base image has been rendered.
I've always wondered if adding something like "font hinting" would cover most use cases. Although I suppose for e.g. icons sometimes at the smaller sizes the actual graphic is pretty much a completely different image, rather than just a hand-tweaked rasterization.
See http://www.pushing-pixels.org/2011/11/04/about-those-vector-... for a detailed exploration of precisely the issue with icons and real-life examples of how smaller versions are actually different images (eg a large 3d image with drop shadows gets gradually flattened to a simplified 2d version).
One thing you can do for patching SVG is to have multiple versions of images/shapes and use CSS rules to select just the most appropriate one to show depending on a class you add to some root or parent item - hiding the other until needed.
I haven't tested this, but wonder if the browser would be smart enough to prioritise loading of the different images depending on the visibility.
Otherwise you could generate those parts of the SVG as required, and use the load event to only swap the display to the more appropriate version of an image once loaded.. hence as you zoom the display, you first get the "core" image/shapes etc simply scaled by the browser, and then as background images are loaded, these scaled versions are replaced by more appropriate versions.
This would match the way that zooming works with tiles in apps like Google maps - when you first zoom in you simply get the base tile images scaled by the browser, and then replaced by the more detailed versions as they're loaded.
There are many factors beyond screen size that could be involved in selection of image DPI: bandwidth availability and cost, screen density and current zoom level, amount of free memory available, hardware limitations (like iPad's max 1024px bitmaps).
Sending all these factors to the server would be problematic, so IMHO it's better if page declaratively specifies what sizes are available and lets UA pick one (so my UA doesn't need to tell every server when I'm out of my bandwidth allowance and hope server acts as expected).
I disagree to some extent. Given DPI, screen density and zoom level, the CSS etc should dictate the pixel width/height which can be sent to the server to obtain the correct version.
Actually, the media queries only work for CSS image properties, like background-image, not for HTML img elements. We do need something equivalent to HTML5's handling of video, where you just stick a bunch of different paths to various formats in the video tag, and the browser selects the best one. Something like that for images would be nice; now we have to resort to jQuery hacks.
If it contains all the different possible resolutions you might need, that one asset would be larger than the one of several assets appropriate for the device in question, so you'd be wasting everyone's bandwidth and needlessly degrading your site's performance.
Being icons, the difference is negligible. You can also show different images using pseudo elements, in any case you don't usually use image tags for icons, it's an image replacement, background or pseudo element.
What? You want a single asset that works at all resolutions, but you don't send the whole thing? Please elaborate.
[edit] I think you might be looking for a single vector design that looks good at all resolutions. Such a beast does not exist due to the low-resolution nature of most displays with which anti-aliasing can only help so much. There is no way to get around different designs for different rendered sizes if you want it to look good. You always design for a target rendered size. SVG just helps you serve 1x (most displays) and 2x (retina displays) resolution optimally with the same file. [/edit]
Not necessarily vector. For example, your server has two versions of your asset. One at 16px by 16px, the other at 32px by 32px. You browse to an associated page and your browser asks for the 16px by 16px version (by means of a header). The server sees two versions in storage and sends the correct one.
Apache already does this for languages, if you ask it to.
First, to create them, I draw icons with vectors at the actual size the final icon will be rendered on regular non-retina displays, then export as SVG with Illustrator. But what I really want are the paths; fill and stroke colors and shading effects can be added manually.
Then, I open the SVG output in a text editor, and since it's all XHTML formatted, I can easily modify everything to get the look I want. I can re-organize the path and fill elements, change their fill colors, and add things like shadows right in the SVG file as filter elements, in case your editor makes sub-optimal choices as to how to encode your design.
These icons look perfect when rendered on both normal screens at 1x and retina displays at 2x resolution. If I needed an in-between size, I'd have to design a new vector for the new target size. One vector design will typically not work well for different rendered sizes at this small scale, as every pixel counts, and anti-aliasing does more harm than good. That problem is just unavoidable, even when you try to make a flattened PNG at all these in-between sizes.
I've also found SVG ideal for small bits of text with special non-web-safe fonts. Converting text to paths and exporting to SVG is the way to go over gif or png text, and looks great on retina displays.