Syntax issue with displaying high-resolution images in the picture element
Posted on:EDIT: We can all agree that the picture element can become very verbose. Especially if you are thinking about supporting a wide range of devices with multiple screen sizes/resoltions.
I’ve put together an example of some markup that would help allievate this issue based on image-set() CSS and URI Temapltes.
View Example Mark-Up – https://gist.github.com/2572749
Big thanks to Adam Bradley for his feedback on this and helping me understand why this makes so much sense as an alternative way to author picture elements which makes them easier to maintain and keeps our markup DRY.
Also, Philip Ingrey reminded me that these can all be in one media query and that each vendor prefixed device pixel ratio doesn’t need to be in an individual media query. I must have had a mind blank when I originally wrote this. I’ve updated the markup to show his example which I think is a perfect solution to the “issue” I was describing. I’ve also moved some of the code examples to github.
<picture alt="Alt tag describing the image represented"> <source src="photo.jpg"/> <source src="photo@2x.jpg" media="-webkit-min-device-pixel-ratio:2,-moz-min-device-pixel-ratio:2,-o-min-device-pixel-ratio: 2/1,min-device-pixel-ratio:2"/> <img src="photo.jpg" /> </picture>
As more and more high-resolution devices come out, from smart phones, to tablets, to laptops and desktops, I think we will start to need 2 images for each breakpoint. Where originally the picture element might have been used like so: https://gist.github.com/2509519
I feel like a more realistic example of the picture element being used in the future will be: https://gist.github.com/2509534
I’m glad Philip reminded me of my mistake, because the markup I had imagined to handle all the vendor prefixes to do this was crazy.
On a side note, I’d love to see the user be able to choose if they want high-resolution graphics in their browser, just like they can choose their default font-size. Maybe an option where you can pick SD graphics and HD graphics. If they choose SD, it would say their device had a pixel ratio of 1 rather than 2 even if they were on a retina device.
What about nested source elements for pixel-ratios?
I cant get the code block working in the comments, so here is a less example:
picture alt=”Alt tag describing the image represented”
source media=”min-device-pixel-ratio:1″
source src=”photo-s.jpg”/
source src=”photo-m.jpg” media=”min-width:321px”/
source src=”photo-l.jpg” media=”min-width:641px”/
source src=”photo-xl.jpg” media=”min-width:1281px” /
/source
source media=”min-device-pixel-ratio:2″
source src=”photo-s.jpg”/
source src=”photo-m.jpg” media=”min-width:321px”/
source src=”photo-l.jpg” media=”min-width:641px”/
source src=”photo-xl.jpg” media=”min-width:1281px” /
/source
img src=”photo-s.jpg” /
/picture
The other point to remember is media queries can contain ‘OR’, represented by a comma: for example:
<source src=”photo-l@2x.jpg” media=”-webkit-min-device-pixel-ratio:2,-moz-min-device-pixel-ratio:2,-o-min-device-pixel-ratio: 2/1,min-device-pixel-ratio:2″/>
Thanks Philip for reminding me of that, I must have had a mind blank. I’ve updated the post with your solution, to my “issue” which turns out, wasn’t really an issue after all.
No problem Brett, glad I could help.
The final example still looks quite scary, but at least it’ll look a lot better once the (level 3) media queries spec gets finalised and the prefixes can be dropped!
With 4-5 break points and a couple of screen ratios all with vendor prefixes the whole thing becomes pretty messy..
You would be required to have a backend system or use snippets to create the markup as it is way to massive for simply writing the code.
Agreed, the picture element does start to get messy when you think about supporting multiple devices with multiple resolutions.
Matt Wilcox had some great ideas that I think would help alleviate some of that mess. One idea was to create a HTML element where media queries could be declared as variables and used in each picture element, keeping the markup DRY. I’ve put a gist together of my spin on this idea.
https://gist.github.com/2509672
Christopher Schmitt has made some good arguments why a responsive image format is needed. http://www.christopherschmitt.com/2012/04/04/the-need-for-a-responsive-web-image-format/
I think Christopher’s idea would work nicely with another idea Matt mentioned. Matt’s idea was having the picture element be able to support multiple image formats similar to how the video tag works. Here’s a gist of that my take on that markup.
https://gist.github.com/2509735
Both solutions would be nice and are ideas I think should be considered before the picture element makes its way to a browser.
There’s a common theme in your code: the src attribute values have a filename, then the size of the photo, then the device pixel ratio (if its 2). This is for just one image, now imagine once its goes across your entire site. What about when you do a site redesign and instead of a breakpoint of 641px you change it to 721px? Or what about when you decide to also offer 1.5 or 2.5 pixel ratio versions, or remove 2 pixel ratios all together?
The source elements all have the same information, except a different filename. We’re repeating ourselves not only for every image variant, but also for every image on every page. When you look at just one example its fine, but what about when your blog has thousands? This format would help lazy authors create errors by forgetting to update parts of each source value after each copy/paste.
Matt Wilcox mqs head tag idea is great (https://gist.github.com/2509672), but this only alleviates duplicating the media queries within one webpage. But we’re still duplicating the filename pattern for each image, and media queries for each page.
Authoring the picture element with multiple child source elements and a media attribute should be an option. However, I believe the preferred method should be to control the image source with CSS: media queries that have different image-set()’s per breakpoint, and uri templates providing the request format (DRY).
Step 1 should be to get the picture element standardized which has already been largely discussed. But I believe that we’ll quickly see there needs to be a better way to maintain image variants and media queries on a large scale, and authoring presentational information into HTML is not it.
No matter how you look at it, it’s going to be complicated to manage numerous image variants and breakpoints. Our options are to either duplicate this complicated info for every image on every page, or centralize the craziness into one area.
Agreed! I see your point that a native HTML media query variable element would only work on one page. The only way to get it to work on other pages would be to add it to a PHP include. And if that’s the case, might as well just use PHP to create the media query variables. https://gist.github.com/1893129
I really like your idea of modifying the main image src via a URI template through image-set(). To me, the URI template is the missing piece of the image-set(). I didn’t see any information about it readying through the available documents on image-set() but I know you’ve implemented in foresight.js. Do you know if URI templates are part of webkit’s implementation of image-set()?
I’ve come to the same conclusion as you, “the preferred method should be to control the image source with CSS: media queries that have different image-set()’s per breakpoint, and uri templates providing the request format (DRY).” I think the issue will be making sure the browser only downloads the correct image from the image-set() in native solution for content images.
So far image-set() is a proposed solution when dealing with image variants for background images. But if this does become a standard then content images should follow the same format, rather than having one way to do background images and one way to do content images.
But no, image-set() does not use uri templates because it doesn’t need to for background images. However, I believe adding this feature into image-set() would make it much more flexible and powerful.
An entire website could format its hi-res and responsive images with one, or a small number of CSS classes all centralized in one location. But if authors choose to, they could still specifically code numerous source elements with repeated media attributes for every image variant on every page. I’d compare this to using inline styles instead of external css; sure there are times an inline style is all you need, however, an entire site should be designed with external css so you don’t repeat yourself and it’s easy maintain.
Additionally, the URI Template RFC was recently approved, RFC 6570, which may help to explain itself:
http://tools.ietf.org/html/rfc6570
https://datatracker.ietf.org/doc/draft-gregorio-uritemplate/history/
http://code.google.com/p/uri-templates/
Adam, this sounds like the best solution to me. Being able to use image-set() CSS and URI templates natively on the picture element solves the issue of the mess the markup of the picture element can turn into when you start supporting multiple devices with various sizes/screen resolutions, as well as keep our code DRY.
I know you’ve seen my proposed markup for this on github Adam, but I wanted to bring the conversation back to the community. For those who havn’t seen it, I’ve put together a gist of how I see this idea could be implemented with the current picture element here: https://gist.github.com/2572749
This would be an alternative method to use the proposed picture element, as opposed to creating multiple source tags with various inline media queries.
Feedback on this concept is much appreciated.
It looks boilerplate-y too me.
Logically everybody on every website will want to do a similar thing — choice of resolution is more mechanical than an artistic decision.
I think there should be a shortcut for this, e.g.:
<picture>
<source src="1x.png">
<source src="2x.png" resolution="2x">
</picture>
or even
<img src="1x.png" src-2x="2x.png">
This also gives user-agents more flexibility, e.g. can download smaller resolution when on expensive/slow connection.