All in the <head>

– Ponderings & code by Drew McLellan –

– Live from The Internets since 2003 –

About

Supersleight jQuery Plugin for Transparent PNGs in IE6

12 March 2009

I never meant to become obsessive about getting PNG transparency working nicely in IE6. In the summer of 2003, I hit across a situation on a client project where what the designer wanted required the use of PNG transparency. The script that came to hand to get this working in IE6 at the time was called Sleight, but that only dealt with applying the filter to IMG elements. My design needed to do the same for CSS background images, so I hacked up a different version of the script for that purpose, called it bgSleight, and occasionally updated it.

Back in late 2007, I gathered up the work I’d been doing on bgSleight along with updates from Aaron Boodman’s original Sleight script and wrote Transparent PNGs in Internet Explorer 6 over at 24ways. In the article I go into some depth about the issues and the pitfalls of using an IE filter, so it’s a useful background read. Included with the article was a script I called SuperSleight which attempted to wrap up both my work and Aaron’s into a single script that made PNGs work in IE6, regardless of them being applied with CSS or HTML IMG tags.

Despite some efforts to make my script play nice and integrate with other JavaScript that may be in use on the page, a lot of users still found the script problematic. Whilst I was checking for existing onload event handlers in the page before adding mine, other scripts don’t necessarily do that and so could overwrite my event handler causing the script not to work. Not my fault, but still not good for those with the problem.

With the rise of JavaScript libraries over the last couple of years, the ecosystem has got a lot more friendly. Rather than having a page running a mishmash of different scripts running in different methodologies, the adoption of a library brings with it shared methodology and infrastructure. That means you can do things like set an onload handler and not worry that your code will not get executed – the library is managing that across all the JavaScript that may be on the page. This also means that there’s a lot less code that needs to be written per-script, as you can tap into what the library already has on offer. So it made sense to me to re-implement SuperSleight using a common JavaScript library.

The Plugin

I personally use jQuery in my work, and its widespread use and solid plugin architecture made it a good choice.

Download SuperSleight for jQuery (current status: beta)

You apply it to a section of the page like this:

$('#content').supersleight();

Of course, if you wanted to fix PNGs for the entire page, you can just apply it to the body element. For all sorts of reasons, it’s better to be specific if you can.

$('body').supersleight();

This can be safely reapplied after importing a chunk of HTML via an Ajax request (something I end up doing a lot), and it uses jQuery’s browser detection to only apply it to the appropriate versions of IE, so it’s safe to deploy for everything, or to include inside some Conditional Comments as you prefer.

As always, the script requires the path to a transparent GIF shim image. By default, and almost by tradition with this script, that’s x.gif, but you can specify any image you like:

$('body').supersleight({shim: '/img/transparent.gif'});

Other possible configuration values are imgs and backgrounds (both boolean, default true) to tell the script which PNGs to fix up, and apply_positioning (boolean, default true) to tell the script not to try and fix up some of the bugs around unclickable links. (See the 24ways article for more info on that).

As always, this is a work in progress, and I value any feedback on technical issues, ease of use or style. I’ve labelled the plugin as beta, because although it’s tested it could always use more. I need to thank Brad Wright for his valuable input so far. I welcome yours.

- Drew McLellan

Comments

  1. § Tim Marshall:

    Having always hated the IE specific hacks and additional file methods i was chuffed when i started using Jquery with IFIXPNG but it had it’s issues especially with transparencies in external style sheet background images.

    Will be taking a look at this now to see if it gives a nice easy way to remove that lovely grey background in IE6 although i really wish it wasn’t an issue. That’s a story for another day!

    Cheers Drew…

  2. § Andy Ford:

    Fantastic! I’m interested in comparing this to my latest favorite PNG fix script DD_belatedPNG by Drew Diller (link)

  3. § Sherwin Techico:

    I thought IE6 was dead =\ haha… Can’t wait to try it. Thanks Drew.

  4. § Bradley Wright:

    One thing to be careful of: if you’re using an image element with padding or borders, this will fail, as the calculated width and height will include said borders and padding (so the image width and height will be increased).

    A workaround is to use margins instead of padding.

  5. § Francis Booth:

    Thanks for this Drew, we used this on a project last Friday and extended it to be <input type=“image” /> aware:

    // image elements
    if (settings.imgs && (self.is(‘img[src$=png]’) || self.is(‘input[src$=png][type=image]’))){

    …I’m sure you could do something sweet with a preference too like has been done for img tags, something like: inputimgs: true

  6. § Marc Hall:

    I was wondering if you had fleshed out the background png handler? Whilst using the ss js at 24ways I found that if you had a background set background-repeat: repeat-y; it would enlarge the image to 100%.
    I hacked this together to handle it: (supersleight.js)

    var bg_fnFixPng = function(obj) {
    var mode = ‘scale’;
    var bg = obj.currentStyle.backgroundImage;
    var src = bg.substring(5,bg.length-2);
    if (obj.currentStyle.backgroundRepeat == ‘no-repeat’) {
    mode = ‘crop’;
    }
    if (obj.currentStyle.backgroundRepeat == ‘repeat-y’) {
    obj.currentStyle.backgroundPosition = obj.currentStyle.backgroundPositionX;
    mode = ‘crop’;
    }
    obj.style.filter = “progid:DXImageTransform.Microsoft.AlphaImageLoader(src=’” + src + “’, sizingMethod=’” + mode + “’)”;
    obj.style.backgroundImage = ‘url(’shim‘)’;
    };

    Now, obviously, this only handles the one exception and there is the issue of having to enforce the postion of the image, yet, I think you get the picture. I’m thinking we need to rewrite this part to be more like an object class.

  7. § Keith Chadwick:

    One can only hope that the hoops we have leaped through for years in order to support IE6 are nearing an end. With the release of IE8 last Friday Firefox has shown its great value in moving the monster to compete and catch up. Perhaps by next year we can start saying to clients they do not need to support IE6.

    Cheers
    Keith Chadwick
    http://keithchadwick.wordpress.com

  8. § Stefan Baur:

    Using this nicht plugin, I found a 2 little bugs in the implementation of the “apply_positioning” position:relative fix.

    1) In the settings-object the variable name is called “apply_positioning”, whereas in the code it is used as “settings.applyPositioning”, which obviously doesn’t match.

    settings = jQuery.extend({ imgs: true, backgrounds: true, shim: ‘x.gif’, apply_positioning: true }, settings);

    if (settings.applyPositioning && …){}

    2) self.css(‘position’) === ‘’ will never be true in my case, because position is always set to ‘static’ as default value. So it would be nicer to test for the position value being == ‘static’ rather than empty.

    Greetings, and thanks for sharing!
    Stefan

    ==> To fix both problems I rewrote the last if-statement as following:

    if (settings.apply_positioning && self.is(‘a, input’) && self.css(‘position’) == ‘static’){ self.css(‘position’, ‘relative’); };

  9. § Antony Blakey:

    I suggest modifying the select in the code to this:


    jQuery(this).find(’*’).andSelf().each(function(i,obj) {

    e.g. add ‘andSelf()’ so that you can apply it directly to image elements.

  10. § Drew McLellan:

    Antony – thanks, I wasn’t familiar with the andSelf() method. That’s going to help fix another bug, too.

  11. § Carl:

    Restricting to PNG files is all well and good until you start trying to embed them into your DLL in a .NET project. As a lazy fix I modified the regular expression to \.png|WebResource.axd which at least gets the job done. I don’t know if there’s a more sophisticated way to do that… if you’re smart enough to be using transparent PNGs, you can be smart enough to tell jQuery which selectors to mess with anyway.

  12. § N Rohler:

    First, thanks for a great plugin — it’s very helpful.

    I have been using it in a unique case where jQuery adds and removes classes when buttons are hovered over/out. The hover-state class uses transparent PNGs for the button background, so I have to call the supersleight() method on hover to fix the button for ie6. However, when the removeClass() method is used, the background still remains due to it being an element-specific style. My solution to this was to add a new supersleightUndo method. The updated script is posted on snipt: http://snipt.net/dwuser/undo-function-for-supersleight-jquery . The supersleight method had the following line added:

    self.attr(‘supersleight-bg-applied’, ‘true’); // THIS LINE ADDED BY N ROHLER 8-1-09, TO ENABLE THE UNDO FUNCTION ADDED BELOW

    Then, the entire jQuery.fn.supersleightUndo method was added.

    Hopefully this will be a time saver if you’re doing this type of implementation and need to undo supersleight’s magic. This was just thrown together, so it may not be perfect!

  13. § M.O.E:

    Does it work for png24?
    png8 images are appearing as they should, but png24s are still displaying a greyish background…

    Maybe i’m missing something. Anyways, great work, thanks for putting this together.

  14. § M Leach:

    Hello. This is great work! It really helped me out of a jam and it’s plugin nature makes it easy to integrate. I did run into one problem/usability issue. I was getting red X’s for my backgrounds and could not figure out why. I finally realized it was because of how the code looks for the source of the image for either the AlphaImageLoader(src=‘XXXXX’ or the settings.shim file. I moved the x.gif file to the same directory as the page being loaded and it worked perfectly. I was just handed this bug today so I did not have time to fully understand what is happening, but I wanted to leave this note so perhaps others can find this and start their search 90% of the way to the solution. What a nasty IE bug this is, though, thank you again for making life easier on web devs everywhere!

  15. § Scott C:

    Hello there,

    Loveley work, however i am stugling.
    I need to use this method, but i have command buttons with images in them, could you help me with this atall?

  16. § Matej:

    If you use png for textarea background, it would not let you type in, to fix it change last if-statement to this:

    if (settings.apply_positioning && self.is(‘a, input, textarea’) …

  17. § house9:

    Great plugin!

    I had to change line #25 since I use the ruby on rails image helper which appends a timestamp to the image file name
    which renders as <img src=”/images/my_image.png?1241218462” alt=“my image” />

    changed

    if (settings.imgs && self.is(‘img[src$=png]’)){

    to

    if (settings.imgs && self.is(“img[src*=’.png?’]”)){

  18. § Michael Bakonyi:

    Hi,

    as M.O.E. already asked: doesn’t this script support PNG 24?

    Michael

  19. § Dave:

    Small bug with the img handling: It doesn’t handle cache-busting URLs that append the timestamp (or version number) to the end of the URL because of the regex used in self.is(). It’s currently using src$=png — ends with ‘png’ — which won’t match something like “image.png?1232123”. Changing it to src*=\.png fixes it.

  20. § Josh Price:

    Thanks for this script, it is working well for me and came in very handy on my current project.

    My one small gripe is that it isn’t version controlled or really packaged up for distribution, making it a bit of extra work to figure out whether to trust it, see what changes have been made to it, test it out, etc.

    Drew would be able to put this on GitHub? I’m happy to show you how to do it or even do it on your behalf, just let me know if you need a hand.

  21. § Anthony:

    What is your license on using SuperSleight for jQUery. It works, and I would like to use it in a commercial product that is not open-source.

    Please inform.

    Thanks!

  22. § Ole Marius:

    Seems like background-position is reset when using this. Would it be possible to get the css-position from the element, then re-applying it in some way?

  23. § Tim Younger:

    this script is great. easily the best i’ve come across so far. i made some improvements:

    we use image inputs with src attributes on our sites at work. so far none of the other png fixes account for this (yours included!) so i added it.

    labels for form inputs should also be corrected with position:relative; so i added that.

    as well, you mention that the images are scaled when padding or borders are used. it just so happens i have a script for calculating “real” or “total” width/height and i added this to the plugin too, renamed appropriately so that there is little chance it will conflict with other plugins. enjoy : )

    http://bustedtubes.com/plugins/supersleight.pngfix.js

  24. § Eddie Adolf:

    Yeah 2 people already asked this, but does it support PNG24? They have much nicer transparency. I really need to know asap. Can any one answer super soon? … Or are we implementing it wrong?

  25. § Tim Younger:

    Eddie, i have used this plugin with PNG24. works great.

  26. § Michael Bakonyi:

    I don’t know exactly anymore but I’ve something in mind that an automatically included colorprofile didn’t let the PNG24 work for me. So check for that if you’re exporting slices in PS for example.

  27. § Joke Buddha:

    Works great but unfortunatelly doesn’t help when background-position are used. We use one css sprite for all images…

  28. § Darren Watt:

    Brilliant, saved me a lot of time, probably. Cheers.

  29. § George Stephanis:

    Something I’ve come up with while using this, is to save from needing the extraneous background-image shim file, just base-64 encode the image and shove it into the javascript code.

    For example,

    shim: ‘data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAA AACXZwQWcAAAABAAAAAQDH lV/tAAAAAnRSTlMA/1uRIrUAAA AKSURBVAjXY/gPAAEBAQAbtu 5WAAAAAElFTkSuQmCC’

    I just generated the x.gif, and shoved it through smush.it, snipping the 8-bit beta transparency (ie6 compliant) png on the other side, which was 90% smaller, base64 encoded it, and shoved it in. Scripts should parse it properly, and use the resulting image. And … no shim file!

  30. § A2daK:

    @Ole Marius

    I have the same issue with the css background-position being reset. It works great for me and is my new preferred method for trans png’s. I’m not sure how to set the config value for “apply_positioning”. Does anyone know? I would need to position the image top right…

    Big Up Drew for this. Love the logo of the site too.

    Adam

Photographs

Work With Me

edgeofmyseat.com logo

At edgeofmyseat.com we build custom content management systems, ecommerce solutions and develop web apps.

Follow me

Affiliation

  • Web Standards Project
  • Britpack
  • 24 ways

I made

Perch - a really little cms

About Drew McLellan

Photo of Drew McLellan

Drew McLellan (@drewm) has been hacking on the web since around 1996 following an unfortunate incident with a margarine tub. Since then he’s spread himself between both front- and back-end development projects, and now is Director and Senior Web Developer at edgeofmyseat.com in Maidenhead, UK (GEO: 51.5217, -0.7177). Prior to this, Drew was a Web Developer for Yahoo!, and before that primarily worked as a technical lead within design and branding agencies for clients such as Nissan, Goodyear Dunlop, Siemens/Bosch, Cadburys, ICI Dulux and Virgin.net. Somewhere along the way, Drew managed to get himself embroiled with Dreamweaver and was made an early Macromedia Evangelist for that product. This lead to book deals, public appearances, fame, glory, and his eventual downfall.

Picking himself up again, Drew is now a strong advocate for best practises, and stood as Group Lead for The Web Standards Project 2006-08. He has had articles published by A List Apart, Adobe, and O’Reilly Media’s XML.com, mostly due to mistaken identity. Drew is a proponent of the lower-case semantic web, and is currently expending energies in the direction of the microformats movement, with particular interests in making parsers an off-the-shelf commodity and developing simple UI conventions. He writes here at all in the head and, with a little help from his friends, at 24 ways.