Giter Site home page Giter Site logo

scottjehl / picturefill Goto Github PK

View Code? Open in Web Editor NEW
9.9K 347.0 1.1K 17.05 MB

A responsive image polyfill for <picture>, srcset, sizes, and more

Home Page: http://scottjehl.github.com/picturefill/

License: MIT License

HTML 15.50% CSS 2.24% JavaScript 82.26%

picturefill's Introduction

Picturefill

A responsive image polyfill.

This project is archived and deprecated!

At the time, it helped us transition to responsive image HTML patterns until browsers supported them. Support and fallback strategies are now very good, and this project is no longer needed or recommended. Thanks everyone!`

build-status Join Slack channel picturefill on npm

Picturefill has three versions:

  • Version 1 mimics the Picture element pattern with span elements. It is no longer maintained.
  • Version 2 is a lightweight polyfill of the Picture element draft specification.
  • Version 3.0.3 is the current stable release.

Usage, Demos, Docs

To find out how to use Picturefill, visit the project site.

The gotchas

Be it browser issues, the responsive images specifications, or Picturefill itself, there are a couple gotchas you should be aware of when working with Picturefill:

  • Firefox 38 and 39 has some bugs [1] [2] [3] where images won't update on screen resize. These issues are addressed by Picturefill 3.0.0, and was fixed in Firefox 41.

  • Per the picture spec, using % isn't allowed in the sizes attribute. Using % will fallback to 100vw.

  • Trying to use the src attribute in a browser that doesn't support picture natively can result in a double download. To avoid this, don't use the src attribute on the img tag:

<picture>
    <source srcset="../img/sample.svg" media="(min-width: 768px)" />
    <img srcset="default.png" alt="Sample pic" />
</picture>
  • If you only want to have an image show up at certain sizes, and not show up at others, you will need to use a transparent placeholder gif:
<picture>
    <source srcset="../img/sample.svg" media="(min-width: 768px)" />
    <img srcset="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
        alt="Sample pic" />
</picture>

Contributing

For information on how to contribute code to Picturefill, check out CONTRIBUTING.md

Issues

If you find a bug in Picturefill, please add it to the issue tracker

Discussion

Picturefill discussion takes place via Slack. For an invitation, visit https://pf-slackin.herokuapp.com/

Support

There are currently no known unsupported browsers, provided that you use the markup patterns provided.

picturefill's People

Contributors

albell avatar andreruffert avatar attiks avatar bmuenzenmeyer avatar bruceontheloose avatar cbieser avatar davebeesleyarchived avatar fgnass avatar gbokiau avatar gordonbrander avatar jansepar avatar jcutrell avatar jefflembeck avatar jegtnes avatar johnbender avatar jonathantneal avatar marek-saji avatar maxklenk avatar michaelgilley avatar mike-engel avatar moox avatar nschonni avatar pborreli avatar peterdavehello avatar petergok avatar pizzabrandon avatar saranrapjs avatar scottjehl avatar wilto avatar zcorpan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

picturefill's Issues

Syntax issue/question

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.

IE9 error

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>

Two Improvements

  1. Considering the relevant data attribute is data-picture, we could not force the tag to be always <div> in which case, we could use the <picture> element.
  2. Considering anchor tags (<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 ?

More Device Testing

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)

Picturefill initialises randomly when using through RequireJS

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!

My RequireJS file:

(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();

    });

}());

Safari 5 Bug

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:

luksak@0b82846

Consider including the SD/HD toggle behavior in Picturefill core

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!

No images displayed on Android 2.2.2

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

IE 7+8 only renders small image?

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..

Can't Resize Mahkuhp Divs fo' Retinah

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.

The Following Won't Work

HTML


<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>

CSS


@media screen and (-webkit-min-device-pixel-ratio: 2) {
  div[data-src="img/[email protected]"] {
    height: 48px;
    width: 48px;
  }
}

need to trigger picturefill at end of ajax request

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?

multiple size requests on resize idea

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!

Blackberry - not an issue, more of an update!

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!

Chrome Issue

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.

VirtualBox won't display images locally in IE8 & 9

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.

"width" attribute in the generated image tag

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.

matchmedia and media query support should not be required to run

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.

Prevent images being re-downloaded

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.

Re-initiate on ajax-load

I'm loading content dynamically using a XHR-request, containing some picture-elements. How can I re-initiate picturefill to handle these?

Not showing image with media query info using default browser on Android 2.3 Gingerbread

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!

Allow for image exclusion?

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.

picturefill() leaks into containing name space

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.

Trigger an event when pictureFill completed

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 : )

Update Components.json file

Bower now looks for bower.json instead of components.json.

Also, the version number in the file needs updating. Thanks!

Does tag used matter?

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?

`media` does't work as expected

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.

How can I make Picturefill load an image when a new AngularJS view (URL) is called?

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.

Support for a full vendor stack for targeting high-res devices?

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>

Screen Rotate on iPhone 3gs running iOS 4

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

Why the data-source order?

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?

Performance suggestion: Do not store matched sources in array

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.

Consider optionally adding a subtle source switcher

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.

Position of <script> tags

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?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.