- From: Edward O'Connor <eoconnor@apple.com>
- Date: Tue, 21 Feb 2012 16:57:57 -0800
- To: www-style@w3.org
Hi all, It's all too easy for authors to make mistakes when adapting their sites for high-resolution displays such as the iPhone's Retina display. Consider the following stylesheet: … selector { background: url(foo-lowres.png) center; } … @media mq { … selector { background: url(foo-highres.png) center / 100px 100px; } … } … The references to the low- and high-resolution variants of foo.png are far apart from one another in the stylesheet, and the (potentially complicated) selector has been duplicated. On a large site with many image assets, this causes stylesheets to become very large and less maintainable. Here are just a few of the problems with the current situation: * Bugs due to non-locality: One developer fixes a bug in the selector, but only in the low-resolution case. Another developer changes an image reference to refer to a different icon, but only in the high-resolution case. * Both assets may be loaded by the browser, which may degrade performance in a constrained bandwidth environment. * Authors can't specify both assets inside a style="" attribute. I'd like to propose a new function for the Images module. This function will allow developers to provide, in a compact manner, multiple variants of the same image at differing resolutions. Using @media pushes the two asset references apart from one another, whereas such a function keeps related asset references together. It also helps keep selectors DRY. We've called it image-set(), and it takes one or more image specifiers. Image specifiers consist of an asset reference and a scale factor: image-set( imagespec [ ',' imagespec ]* ) imagespec ::= <image> S {num} 'x' The above example could be rewritten using image-set() like so: selector { background: image-set(url(foo-lowres.png) 1x, url(foo-highres.png) 2x) center; } By using image-set() here, the author is saying that foo-highres.png is twice the resolution of foo-lowres.png. UAs which support image-set() could then use the 2x image on a high-resolution display, and the 1x image on a low-resolution display. UAs aren't required to fetch the assets in order to determine which should be displayed, so we avoid redundant asset loading. Some Q&A: * What's the intrinsic size of an image-set()? Does it vary depending on which image is picked? Does the UA apply the scale factor to derive the intrinsic size of the image? The intrinsic size of the image-set() can be computed from the intrinsic size of the actual image asset chosen and that asset's associated scale factor. Suppose that foo-lowres.png is 100x100 and foo-highres.png is 200x200 in the above example. If the UA chooses foo-lowres.png, it computes the intrisnic size as (100/1)x(100/1) = 100x100. If the UA chooses foo-highres.png, it computes the intrisnic size as (200/2)x(200/2) = 100x100. * Why a scale factor and not a full-blown media query? Media queries are a claim about the state of the UA, whereas here we're making a claim about (the relationship between) the image assets themselves. It would be confusing to use similar syntax for such different things. Also, UAs should have the ability to choose between the given variants based on a variety of factors. For instance, a UA could use the lower res asset when a user has zoomed out. No existing media query distinguishes between the page being zoomed-out and being zoomed in. And even if such a media query existed, UAs should be free to choose between variant assets regardless of which media queries happen to match. * The problem of stylesheet verbosity when using media queries isn't limited to image assets. Shouldn't we have a general mechanism for keeping media-specific property values together in rule sets? In talking with content producers here, we've found that the non-locality of asset references is a real source of Web author pain. I think a focused feature to help with that pain is sensible. That said, we should also explore how to help authors avoid selector repetition and the other pains of @media in general. * Why not enhance the image() function instead of inventing a new function? Unlike image(), these image specifiers are unordered. This isn't about fallback. There is no preferred variant. UAs are free to use whichever image it believes would be best. For instance, consider the page zoom example I mentioned earlier. Authors could even use image() and image-set() together to handle more exotic cases, e.g.: image(image-set(url(foo.png) 1x, url(foo@2x.png) 2x) rtl, image-set(url(bar.png) 1x, url(bar@2x.png) 2x) ltr); * What about other cases where authors would like to specify alternative image assets, such as when the UA is on a low- or high-bandwidth connection? This is definitely something worth exploring. In the future we could extend the asset descriptors to cover such cases. Something like this, maybe: selector { background: image-set(url(foo-lowres.png) 1x low-bandwidth, url(foo-highres.png) 2x high-bandwidth); } I don't have a proposal for how to describe bandwidth here, though, and I'd love to hear ideas. I don't think addressing the multiple- resolutions case needs to wait for a solution to the bandwidth case. * What about content images? First off, this is www-style, so the design of an HTML feature for responsive <img>es is out of scope. :) That said, I can imagine the image-set() microsyntax being used in an attribute like so: <img alt="A description of foo" src=foo-lowres.png set="foo-lowres.png 1x, foo-highres.png 2x"> I'll post something to the whatwg thread referencing this proposal. Ted
Received on Wednesday, 22 February 2012 00:58:26 UTC