scottjehl / picturefill Goto Github PK
View Code? Open in Web Editor NEWA responsive image polyfill for <picture>, srcset, sizes, and more
Home Page: http://scottjehl.github.com/picturefill/
License: MIT License
A responsive image polyfill for <picture>, srcset, sizes, and more
Home Page: http://scottjehl.github.com/picturefill/
License: MIT License
I had the issue that on AJAX loaded content where I re-apply the picturefill, Safari 5.0.5 did confuse the img tag in the noscript tag with a already replace image. I made a commit where I fixed this:
This will allow to use inline list of pictures in responsive projects and provide "retina quality" images for it (e.g. list of sponsors logos, each different size) .
Hi
I'm testing the demo files that come with the project and in IE 9 (in IE 7 + 8 modes) it's only showing the small image.. is this correct behaviour?
EDIT:
Just realised the demo file an HTML5 doctype.. but - just added the head from HTML5 boilerplate and still no go..
EDIT v2:
I think I'm being really stupid and just not amending the src for the default image..
The stacking of min-width: 400px
, min-width: 800px
, etc., should behave like it would in CSS. I was expecting all the images to be downloaded at higher viewport dimensions – as all stylesheets would be if using the examples media
values – but only the larger one was.
When I resize the viewport, smaller images are downloaded. And when I resize to wider viewports, the larger images appear to be re-downloaded. So I can end up with dozens of requests in my dev tools when there are only 5 or so images referenced in the HTML.
For performance reasons, it's important to have the width
attribute specified in a image tag element.
Would be nice if we could specify this in a syntax like:
<span data-src="medium.jpg" data-width="400" data-media="(min-width: 400px)"></span>
Which will compile to the appropriate <img>
tag with the specified src
and width
attributes.
I'm loading content dynamically using a XHR-request, containing some picture-elements. How can I re-initiate picturefill to handle these?
When I resize Chrome to a point where picturefill changes an image, the container of the image element has a height of 0 for a very short period of time which causes all of the content below the image to move up to take up that newly available space. Then picturefill changes to the new image, causing the container to regain its height which then pushes all the other content back down.
This is very annoying since the page appears to flicker when it happens. This does not seem to happen in Firefox / Safari. Is there anything I can do to fix this? Giving the container a fixed height is not possible unfortunately.
...to save http requests if picturefill is merely being used to swap different sizes of the same crop.
This will allow for easier css selector access to the image based on whichever source is in play.
Hi Scott,
I don't know if someone else come up with the same idea but I found could be very interesting to debounce the multiple request on 'resize' event, I added the resize callback to only allow it to execute once every 500 ms:
// borrow from UnderscoreJS
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
}
// Run on resize and domready (w.load as a fallback)
if (w.addEventListener) {
// Added the resize callback to only allow it to execute once every 500 ms
w.addEventListener("resize", debounce(w.picturefill,500), false); // debounce!
w.addEventListener("DOMContentLoaded", function() {
w.picturefill();
// Run once only
w.removeEventListener("load", w.picturefill, false);
}, false);
w.addEventListener("load", w.picturefill, false);
} else if (w.attachEvent) {
w.attachEvent("onload", w.picturefill);
}
I hope it's helps!
All the best!
As a work around picturefill.js is being included via a script tag... and works perfectly.
Any light on the situation would be great. Thanks!
(function () {
"use strict";
requirejs.config({
paths: {
'lib' : '../lib',
picturefill : '../lib/picturefill',
jquery: [
'//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min', //google CDN
'../lib/jquery/jquery.min' // local fallback
],
}
});
require([
'common',
'picturefill'
], function (common) {
common.setupChrome();
});
}());
Is there discussion to align Picturefill with the the picture element spec?
The update would be to change the data-media
attribute to media
and the element being called <picture/>
with <source/>
as children.
A fork of srcset-polyfill would also be a nice addition for srcset
alignment of the spec.
When I tested picturefill in IE9, I got the following error:
CRIPT5007: Unable to get value of the property 'join': object is null or undefined picturefill.js, line 35 character 5
I haven't yet tested it in any other version of IE.
The code I am using for the picture element looks like this:
<picture alt="">
<source src="http://farm8.staticflickr.com/7110/6915941510_c219cfe8ed.jpg">
<source src="http://farm8.staticflickr.com/7110/6915941510_c219cfe8ed_c.jpg" media="(min-width: 400px)">
<source src="http://farm8.staticflickr.com/7110/6915941510_c219cfe8ed_b.jpg" media="(min-width: 800px)">
<noscript><img src="http://farm8.staticflickr.com/7110/6915941510_c219cfe8ed.jpg" alt=""></noscript>
</picture>
Given the following markup:
<picture alt="">
<!-- <source src="med.gif" media="(min-width: 400px)" /> -->
<source src="med.gif" media="(min-width: 400px)" />
</picture>
I’d expect the image to only load if the viewport is wider than 400px
, and then not load (or disappear) if the viewport is below that threshold.
However, this works up to a point: if my viewport’s ~320px, and I make it wider than 400px
, the image appears; however, bringing it back down below 400px
leaves the image in the source.
Changing the markup to point to a dummy default image fixes the problem, like so:
<picture alt="">
<!-- <source src="x.gif"> -->
<source src="x.gif">
<!-- <source src="http://placehold.it/175x132" media="(min-width: 400px)" /> -->
<source src="http://placehold.it/175x132" media="(min-width: 400px)" />
</picture>
I realize this may be a picture
-related syntax question—what should the proper behavior be here?—rather than a pure picturefill-specific issue. But hey, thought I’d post it anyway. Hi.
Is there a syntax that would support an anchor tag around the final image? I've tried placing the anchor in a few different spots in the markup to no avail.
The page I'm working with is here:
http://cloudfour.com/examples/image-breakpoints/
I noticed something odd:
http://f.cl.ly/items/3H0l36103y0d0f0w3V2e/chrome_shudder.mp4
Triggering a custom event at the end of the pictureFill function would have some benefits I think.
Imagine if you have a responsive slideshow with images of different height. Right now, If you add the slideshow on document ready it will have a wrong height since the images are not replaced yet. You could use some imagesLoaded plugin, but again, the images are not replaced when you call it and it will still give a wrong height.
One workaround is to create the slideshow on document load event but it's not the best solution and can have some "long" delay.
Since on my setup I have jQuery I simply added this at the end of the pictureFill function:
$(w).trigger("picturefill_complete");
Then I was able to simply do something like this and it fixed my issue:
$(window).on("picturefill_complete", function(){
$("#slideshow").imagesLoaded(function(){
slider.reloadSlider();
});
});
So, is this kind of addition possible? If it is, I could try to make a pull request : )
Source elements that have no media attribute, or a media attribute that specifies a media type (but not a query), these should work fine in all browsers. Media query support is not necessary for that case, and it'd allow for the initial source element to load in any JS-enabled environment.
In some cases it might make sense to exclude images for performance. For example, at 0px up to, say 400px, I might not want any cut of an image to download/display, if it is ancillary content. This can potentially increase performance by reducing page weight and HTTP reqs. for very old, incapable or legacy devices.
Seems like it would be a nice option to have. I drafted the idea in a clone if anyone's interested.
The user-prefs branch includes a behavior that, when viewed on HD/retina screens, will cause picturefill to default to the best standard definition image available, regardless of whether retina images are listed, and present the user with button to opt-in to HD quality images. After choosing a quality setting, a cookie is kept so that the user's preferences are remembered as the default on subsequent pages, but the option to switch between SD/HD is always present.
A demo of this can be viewed here (note that only retina-capable screens will have a choice to view HD images): http://filamentgroup.com/examples/picture-hd-prefs/
This pattern is common in video players on the web and is important for a few reasons. First, a user with an HD-capable screen may not have a connection speed that will load HD images efficiently, and might prefer a faster loading image to a higher quality image. Second, a user with an HD capable screen may have a data plan that has restrictions based on data usage, such as a monthly cap, or a downgrade in connection speed once a certain amount of data is used, so they may also prefer a lower quality (less data) image. Lastly, serving HD content can be costly for website owners, so the ability to ensure that they're only serving HD images to users who want HD may be desirable.
We're using the SD/HD toggle in production sites now, and would propose including it in picturefill by default. If included, we might include a mechanism for enabling or disabling the behavior (depending on the default) for those who do not want it on their site. Something like data-hddefault="sd|hd"
Feedback would be appreciated!
I'm using VirtualBox to test IE on my local machine. The spans wont display the appropriate images on IE8-9 Windows7. This is really strange because everything works correctly when I push and test in VirtualBox using my remote staging server for IE8 (w/out the conditional comments) and IE9. It also works for me on my Mac with Chrome and, Firefox with my local environment. As I stated VirtualBox seems to be the problem :\
If I strip out the img tag from the noscript tag and use the same img path testing locally in VirtualBox I see my image in both IE8 and 9.
I am coding up a design portfolio using AngularJS and Picturefill. If I include my picturefill html code in index.html
then picturefill will load my images just fine.
<span data-picture data-alt="Lounge Coffee">
<span data-src="../images/320/lounge_coffee-320.jpg"></span>
<span data-src="../images/480/lounge_coffee-480.jpg" data-media="(min-width: 480px)"></span>
<span data-src="../images/660/lounge_coffee-660.jpg" data-media="(min-width: 660px)"></span>
<span data-src="../images/770/lounge_coffee-770.jpg" data-media="(min-width: 770px)"></span>
<span data-src="../images/990/lounge_coffee-990.jpg" data-media="(min-width: 990px)"></span>
</span>
The problem is when I put the Picturefill html code in one of the AngularJS views. For some reason Picturefill does not think that loading a new AngularJS view is the same thing as loading a regular .html
page (URL). I will mention that if I resize the browser window, then Picturefill kicks in and serves up the right image. So it works but only on window resize, not on AngularJS view load.
How can I make Picturefill treat the loading of Angular views the same as the loading of a regular .html
page? so that it can load the image right when the view loads?
Also I came across this Stack Overflow question which is exactly that same issue I am facing.
http://stackoverflow.com/questions/17120888/using-picturefill-js-in-angular-js-app
Apparently it was ignored here. Now you know more than one person is going through this. Probably more out there.
This is very specific use case but when I tried a blank HTML document using just the latest picturefill.js elements, I was not able to display the data-src images that contained data-media property. The only way I can make it show up is if I delete the data-media property off the first image in the set. Is this just limited to Android <2.3 and is there a fix for this?
To see an example, take the demo here:http://scottjehl.github.com/picturefill/
Delete the first image that is without the data-media property and then try it on Android 2.3 browsers.
Given that ~60% of Android users are still using 2.3 (and many not ever being upgraded to ICS on these phones), I'm hoping there's a fix for this!
Since there is an already working draft for the picture and source elements, why not use these instead of divs?
http://www.w3.org/TR/2013/WD-html-picture-element-20130226/
Using the shiv for unsupported browsers that document.createElement('picture')
and document.createElement('source')
can make this future proof, even though the specification might change in the near future.
I wanted to check out the current prop branch but noticed this line:
picturefill.js - line 69
alert( window.getComputedStyle( this.cloneNode( true ) ).width );
Was this left in intentionally?
Other than this It works great.
matches = []; to matchedEl = null;
Now there is no need to push to the array.
matches.push( sources[ j ] ); to matchedEl = sources[ j ];
if( matchedEl ){
Use matchedEl variable directly...
}
This saves on array creation, pushing and popping to get the last source element that matches.
You can see the label vs. size on the following page, or in the zip.
0d793ea
I don't have the right program on this computer to alter the label, so I wanted to make note of it.
See https://github.com/weblinc/picture for example of this in use.
Note that I store some picture specific properties on the element. I think this could have a positive performance impact since elements are not reparsed.
Would love to hear feedback. Thanks
In the Picture spec the source elements, like <audio>
and <video>
, are ordred from most restrictive media type to least:
<picture width="500" height="500">
<source media="(min-width: 45em)" src="large.jpg">
<source media="(min-width: 18em)" src="med.jpg">
<source src="small.jpg">
<img src="small.jpg" alt="">
<p>Accessible text</p>
</picture>
Picturefill orders them the opposite way, with the default or least restrictive source first. Could someone point me to a reason why?
The new div
markup is having some difficulty with sizing the actual element for Retina. In order to adjust for retina Authors must have the @2x version that is a 200% scaled version of the original. Once we have this original scaled 200% we bring the new doubled proportions back to our original size from within our style sheets.
The current usage wont allow Authors to size the new retina div
to it's original proportions. So if the original proportions are 48px x 48px and I have my Retina sized at 96px x 96px I need to resize the image back down to 48px x 48px for Retina in order to keep the proportions. So the following won't work to resize our Retina Image. The only way currently is to wrap an element around the entire div
and resize that element for the desired outcome.
<div data-picture data-alt="">
<div data-src="img/twitterBird.png" data-media="(-webkit-min-device-pixel-ratio: 1)"></div>
<div data-src="img/[email protected]" data-media="(-webkit-min-device-pixel-ratio: 2)"></div>
<!-- Fallback content for non-JS browsers. Same img src as the initial, unqualified source element. -->
<noscript><img src="img/twitterBird.png" alt=""></noscript>
</div>
</div>
@media screen and (-webkit-min-device-pixel-ratio: 2) {
div[data-src="img/[email protected]"] {
height: 48px;
width: 48px;
}
}
You had your table showing support... just wanted to confirm it appears to work dandy on my Blackberry.
Blackberry 8900 smartphone (EDGE, wifi)
v5.0.0.681 (platofrm 5.2.0.67)
using Standard Internet Browser.
Hope that helps!
I assume it's compulsory that the calls to picturefill and matchmedia go at the top of the document, before the images load, and can't be shunted to above the closing </body>
tag?
Could you add something on this to the README?
I assume i could just replace span with figure for semantic reasons in the JS file if i wanted?
Ie. var ps = w.document.getElementsByTagName( "span" );
to var ps = w.document.getElementsByTagName( "figure" );
Any drawbacks here?
I, I want make a carousel with polyfill.
It's possibile use more image in one page?!?!?!?
Tnx. D.
If the loading of picturefill.js is deferred until after load is fired, images will not load unless the browser window is resized.
@scottjehl Any chance of getting a tag for picturefill so it can be added to cdnjs?
The picturefill()
function is leaked into the containing (usually the global) name space.
I haven't tested it, but it seems that w.picturefill = function()...
could be var picturefill = function()...
and all subsequent references to w.picturefill
changed to just picturefill
and everything should still work, but the function then won't be leaked.
Bower now looks for bower.json instead of components.json.
Also, the version number in the file needs updating. Thanks!
Threw a good chunk of the test lab at it. No problems.
Samsung Series 7 Slate - Windows 8 Release Preview - Working just fine. (Extra Large Image)
BB Playbook - OS 1.0.3 - Working Fine (Extra Large Image)
8900 Curve - BB 4.6 Cursor - Working Fine (Small Image)
N8 - Anna s3 - Working Fine (Small Image)
Nokia Lumia 800 - WP7.5 - Working Fine (Small Image)
C7-00 - Anna S3 - Working Fine (Small Image)
701 - Belle - Working Fine (Small Image)
Samsung Wave 3 - Bada 2.0 - Working Fine (Small Image)
Blackberry 10 Dev Alpha - Working Fine (Small Images)
Hi Scott,
Thanks so much for an amazing plugin. I was testing in iOS4 with an iPhone 3gs and found on rotate of orientation of the screen it'd show both versions of the images..
Just wondering if there's some way to fix this
Thanks.
Tom
Picturefill doesn't work on content requested from an ajax call.
I've got a jquery driven infinte scroller that loads 'More' content onto a page. Following an ajax call for the next batch of items the image containers do not display their images. They do though suddenly pop into existence if the browser window is resized.
I'm assume that the browser resizing is triggering Picturefill into action. So, I need to add a trigger at the end of my infinite scroll jquery that activates picturefill at the end of the ajax request.
Is there already a way to do this?
This could be purely down to me using an incorrect syntax. However, should Picturefill support a full vendor stack for targeting high-resolution devices?
For example, in the example below, I would expect high-resolution.jpg to load for any media-query capable user agent. However, it doesn't. Is that because I have the syntax wrong? Do I need to declare each vendor prefix separately?
<div data-picture data-alt="An image, whose source changes depending upon the media query style expressions"> <div data-src="normal.jpg"></div> <div data-src="high-resolution.jpg" data-media="(min-resolution: 96dpi,-webkit-min-device-pixel-ratio: 1,min--moz-device-pixel-ratio: 1,-o-min-device-pixel-ratio: 1/1,min-device-pixel-ratio: 1,min-resolution: 1dppx)"></div> <!-- Fallback content for non-JS browsers. Same img src as the initial, unqualified source element. --> <noscript><img src="normal.jpg" alt="An image, whose source changes depending upon the media query style expressions"></noscript> </div>
data-picture
, we could not force the tag to be always <div>
in which case, we could use the <picture>
element.<a>
), I have tried a bunch of combinations without success to make the image linkable. Should we define a better way? Like data-href perhaps so the <img>
appended is wrapped in <a>
tag ?Wouldn't be a better way for setting classes on images to use the data- attribute, rather than the class=?
For example:
It'd be interesting if Picturefill could optionally generate a subtle selectmenu button over the corner of an image that'd let users choose one another of the available sources to display, overriding whatever the media queries decided was sensible. An actual select element with onchange behavior would likely suffice for styling it as a subtle icon button.
This would be an extension, not part of the default script itself.
No images are displayed on Android 2.2.2 (haven't dug into why yet)
UA string is: Mozilla/5.0 (Linux; U; Android 2.2.2; en-gb; HTC Desire Build/FRG83G) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1
It’d be great if I could set a class
attribute on a source
/[data-src]
element, and it’d be preserved in the rendered img
.
Absent a draft spec, this behavior seems intuitive to me.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.