reflection.js demo

December 17th, 2005

This post is from 2005 and refers to an old script. It’s now been deprecated. See GitHub for the final version from 2008. For a more up-to-date version of the script, please see Reflection.js for jQuery.

I’ve got the reflection script I mentioned earlier up to a workable state.

You can view the demo here. You need a browser which supports the canvas tag – Firefox 1.5, Opera 9 Preview or Safari 2.


How it works

The script uses unobtrusive javascript to find all images with the class name “reflect”. It does this by adding an onload hander to the window object. Every time it finds an image with the class reflect, it generates a new canvas element. It will do some canvas magic (scaling, cropping, gradients) and produce a reflection image.

The script then creates a new div element with two child elements – the original image and the canvas reflection. It will replace the original image with this div.


  • Degrades nicely in browsers which don’t support canvas
  • Automatically fades into the background colour
  • Original image is still a real image in HTML and can be right clicked
  • Keeps your HTML tidy

Like this tip? Get the most from your mobile phone...

  • Discover brand new ways to use your mobile phone
  • Techniques to get more out of your mobile phone for less
  • Be the first to learn about new mobile technology

Enter your email to receive free regular Ken's Tech Tips:

About Ken

Ken Lo

My passion is helping people to get the most out of their mobile phone. I've been blogging at Ken's Tech Tips since 2005.

Aside from writing about mobile technology, my interests are in software development, digital marketing and physics. Outside of the blog, I work with numerous technology companies helping them to explain their product and helping them to market it to consumers. Please get in touch for more information.

Your Comments

We'd love to hear your thoughts and any questions you may have. So far, we've received 75 comments from readers. You can add your own comment here.

  1. lunchboxbill said:

    funny reading some of the 2005 comments and how things have turned out πŸ™‚

  2. rsetes said:

    Little note Cow,

    Your script doesn’t work when you use the body-onload-tag in html. Then the reflections are not being displayed. I wanted a image-preload-script but when i drop the function in my body-onload the reflection.js didn’t work anymore. The function-name was not the problem. I tried more than one name.

    greetz me

  3. nico said:

    if youre stuggling with some “reflecting-before-loaded”-problems try that:
    rename the “add” method to “set” (means, change ‘add: function(image, options) {‘ to ‘set: function(image, options) {‘) and add the folowing method somewhere inside the Reflection-class:
    add: function(image, options) {
    image.onload = function(){ Reflection.set(image, options); };
    image.src = image.src;

    very hot now,

  4. Keikonium said:

    Hi Cow,

    First off, I’d like to thank you for this amazing script! It really makes things look prettier for sure.

    However, I am having a few problems (most likely my shotty knowledge of Javascript :P). Anyways, if I put this script in a folder with an image, and an index.php file, then define the class=”reflect” on the image and call the script to load, all works fine, the reflection shows up.

    But if I put the image in a different sub folder, the reflection no longer works. Do the images and the script all need to be in the same folder? If yes, is it possible for the script to look at any code on any page and if class=”reflect” is found, reflect the image?

    Hopefully that wasn’t to confussing, but thanks in advance for any help :).

    ~ Kei

  5. Gersom said:

    Little note Cow,

    Your script doesn’t work when you use the body-onload-tag in html. Then the reflections are not being displayed. I wanted a image-preload-script but when i drop the function in my body-onload the reflection.js didn’t work anymore. The function-name was not the problem. I tried more than one name.

    greetz me

  6. Ken Lo
    Ken said:

    Dear David,

    Try Reflection.js 1.9. I think this issue has been fixed!


  7. David Hopkins said:


    I’m using reflection.js v1.5 and am having trouble with IE 7. The reflection height for resized images is 100% for some reason. Only happens in IE 7.


    …then upload an image.

    Any help would be great!

  8. Gildas said:

    I managed to get the reflection work on but there is on problem remaining.
    As the elements are nested within a DIV tag that is set to a right alignment for the text, my CD Cover and its reflection should appear aligned on the right alas, they are aligned on the left border of my DIV.
    What’s happening ?

    Thanks again for your help

  9. Marco said:

    I’ve adjusted the onload lines with the following:

    if (window.addEventListener) {
    window.addEventListener(“load”, addReflections, false);
    else if (window.attachEvent) {
    window.attachEvent(“onload”, addReflections);

    It allows other onload events by other javascripts. At least it worked for me… πŸ˜‰

  10. ElGandoz said:

    First off, stunning work!
    But i’ve a little problem..
    referring to the issue of “The Technocrat”, about resizing a image…is there the possibility to resize an image, using the css attribute max-width/max-height ?
    Because right now it doesn’t work! This is very helpful for resize images just over a fixed dimension, more flexible than the fixed dimension (it affect larger and smaller images…)
    Thanks a lot for your work

  11. Khlo said:

    Comments closed due to spam. Use Reflection.js 1.6.

  12. Romulus said:

    This is a great script! But… 

    There is a problem with the links for an image who use reflection class with Internet explorer. Can you see that on my website, on the header, there is a RSS image with reflection class, but the link doesn’t work on IE.

    There is a solution for this?

    Thank you. 

  13. Max said:

    Perfect script. flawless implemetation, can’t be better if you ask me.


  14. Leo Kennis said:

    I just downloaded reflection.js and it work…as long as I don’t give my images a margin/padding in Opera/FF:

    <img src="samp.jpg" alt="Sample image" width=100 height=100 class="reflect rheight15" />

    img {
    float: left;
    display: block;
    margin-left: 25px;

    Now my image is 25px left, but the reflection is still "0px to the left"…how comes, and what can I do about it?

  15. Praca said:

    hi there

    script is fascinating – and good looking i wana use it could I? thx;)

  16. Jimy said:

    It looks amazing! Great script, Cow. + very easy to using

    Tnx u so much, i m going to try it for my blog

  17. Tanhnhi said:

    Great work, really!!

    But I think 2-3 pixels between the original image and the canvas would be better, take a look at my gallery

  18. Khlo said:


    Thanks for your kind comments.

    Andrew: Simply load reflection.js after you initialize moo.fx. This should solve the issue.

    Matth: I’m not aware of a way to do this directly; you’d probably have to have text rendered to an image which was run through the canvas tag. 

  19. Matth said:

    Very nice! I was allready begun to try and copy the script used by apple and iWeb but it seems they’re cheating a bit by making only a .mac server image flip.

    I was wondering: can text be rotated? or flipped?
    It may seem useless but i would need some sort of way for doing this for a very specific need of a client.

    ideas welcome

  20. Brub said:

    Perfect script. flawless implemetation, can’t be better if you ask me.


  21. Andrew said:


    I have been using this little script on developing my website for a few days now. Today I added some moo.fx code to the site and the reflection dissapeared. My initial thought was it is because i have the following in my head section now (with another onload event)

    <script type="text/javascript">
                    // Initialise the effects
                    var containerHeight;          
                    window.onload = function() {
                            containerHeight = new fx.Height(‘container’, {duration: 400});

      My problem is I am not clued up enough with JS  to know what may be the problem. I have tried adding the reference to the js file in the body of my page, but it did not help.

     Any help would be much appreciated!!

     Thanks for a great script by the way,


  22. Khlo said:


    Thanks. I managed to recreate the bug and identified the issue – it’s because in XHTML Strict images seem to have some kind of different vertical alignment. I managed to solve the issue by giving the image a vertical-align CSS value of "bottom".

    I’ll try and release a fix ASAP.


  23. Withinreach said:

    if doctype is set to xhtml strict, in firefox 1.5x, a space (empty border) appears between the image and the reflection. Not in IE. Change doctype to transitional, space goes away, and image/reflection are touching.

    Spent 2 hrs late last night trying to figure out why, looking for css and other js library collisions, breaking my page down div by div, and then building the sample page from this library up with my code/libraries/css.

    I noted that the example page had no doctype, and when i removed it (and put it back as transitional) the blank space went away.

    Maybe I’m a moron, or maybe I just saved some poor soul 2 hours of their life. πŸ™‚

  24. Joe Vinson said:

    To anyone’s knowledge, is there a way to have the “reflection” part go underneath other page elements? For example, let’s say I want to reflect an image in a div floated to the right of a paragraph of text. Is is possible to force the text to wrap around the image (as normal for a float), but to let the text flow over the reflection?

  25. The Technocrat said:

    just noticed that the wp-wetfloor plugin that uses the reflection script is packaged with v1.0…  replaced with 1.5 and it works well with resized images via the plugin in WP.


    The K2 theme’s img css needs to be commented out for it to work, but the good news is that the reflections are correct.  cheers.

  26. The Technocrat said:

    khlo – gotcha, I’ll test, sorry for the rambling comments…  πŸ™‚

    I’ll check version and try again with the inline 

  27. The Technocrat said:

    For example,

    I’ll try to make an RSS button with the text ‘rss’ next to it, by aligning the picture left…


    now go ahead and add the reflect class to the image, and it will turn into this in WP:

       [<– original pic is still left-aligned, but reflection img align is not specified]

    (reflection shows up here, without alignment specified) 

    RSS [<– since reflection img didn’t have an alignment specified, the text is put below reflection]


    Hopefully this explains my rambling a little more.  Also, I don’t want to come across as being all ‘DO THIS’ or anything, I’d be happy to do it myself and release it, but it’s fair to you to just let you know and come out with a new version here…sorry if I come across otherwise…

  28. Khlo said:

    reflection.js is floating pictures left by default, which i think is overwritting my style tags, i cant seem to find th e conflicting code though

    What reflection.js does is it copies the content of the style attribute on the image and adds it to the style attribute of the div element which contains both the original image and the reflection. There are several reasons why it does that – for example if you add a border around an image, you don’t want the border to appear twice. 

    reflection image needs to be resized if the original image is resized. 

    I think you installed reflection.js before I released the latest version – reflection.js v1.5. This makes it work with resized images.

    Also along the same lines, the reflection image needs to carry the same properties as the original image, like alignment, etc.

    If you stick the alignment as an inline style attribute, it’ll copy the styles over to the reflection. I believe it should do the same with CSS classes but I’m not sure.


  29. The Technocrat said:

    khlo, thanks, I found by trial and error that the ajaxy-live-search thing in the K2 theme was breaking it.  I got around it by turning it iff…didn’t need it anyway…

    a few usability issues, at least in WordPress, but probably in general also:

    reflection image needs to be resized if the original image is resized. Right now, it makes a reflection of the full-size image, and cuts off the reflection where the main image ends. To demonstrate this, put a 300px-wide image in a post and resize it to 150. ([img src="url" width="150]) Add the reflect class, and you’ll see what I mean.  You see the first 150 pixels of the full-size 300px reflection, cut off at 150.  Issue with wordpress, or in general?

    Also along the same lines, the reflection image needs to carry the same properties as the original image, like alignment, etc. (we already talked about width). With the plugin as it is currently, it is impossible to have text wrapped around an image, as the reflection is not aligned, and the text is pushed below it.

    Basically, both of these issues, and further issues down the line, can be solved if the reflection shared the same [img] properties as the original, except [height=] and  [src=], of course…

    any thoughts? 


  30. Giddy said:

    Thanks for the suggestion Khlo,

     reflection is working properly for the swapped images, the problem is that i can keep my intial style tags for the pictures

     reflection.js is floating pictures left by default, which i think is overwritting my style tags, i cant seem to find th e conflicting code though

  31. Khlo said:


    Try calling Reflection.add() on the image again when you have changed the image. 

  32. Giddy said:

    sure ill try

    this is my code (with reflection working, but floated left unintenionally)
     <div id="banner" >
     <img src="b.png" usemap="#1" name="selector" border="0" alt="" onload="Reflection.add(this, { height: 2/3, opacity: 1/3 });"/>
    <map name="1"><area shape="rect" coords="20,38,79,92" href="/home" onmouseout="MM_swapImgRestore()" onmouseover="MM_swapImage('selector','','b1.png',1)"/></map> 
    where my css code, id banner, centers the image b.png and the javascript swaps b.png with b1.png on mouse over and swaps back onmouseout 
    Im finding the image is floated left by default, so i force it to center by adding a style tag in <img>. this works for the orginal image, but when the image is swapped the style is overwritten again and the image is floated left again.
     how can i use reflection without it overwritting my css?
  33. Khlo said:

    I fail to understand; do you have an example?

  34. Giddy said:

    im trying to use reflection.js with a mapping within an styled div.  all of my css formating is being overwritten.  if i force the style with in the img tag, it works, but not when the image is swapped.

     any solutions to this?

  35. Khlo said:

    I suspect this is overwriting the reflection.js onload event:

    window.onload=function() {


    Stick the reflection.js code after that. 

  36. The Technocrat said:

    Hey all, I’ve followed the directions here using WP2.0.2 and K2 beta two r187 with the ‘trueblue’ style.  Just can’t get it working.  I even made a copy of prototype.js.php and renamed to prototype.js, no luck.


    Any words of advice?  check out the source code, I’ve done evrything like I’m supposed to….?


  37. Mooty said:

    also, will yours handle image borders? or will it in the future? thx

  38. Mooty said:

    khlo – yea sure you can save them, but as you said before, think of the use in a dynamic site situation. gives you a url which you use in your tag, so in the same way you use class=reflect, you can change the image= identifier on the livereflection URL.

    I think both the ideas are great for dynamic situations, both have their benefits… 1 or 2 reflections? Nah! use photoshop πŸ™‚

  39. Khlo said:

    It should already support borders. Got an example?

  40. Khlo said:

    Nice find. I personally wouldn't pay for this though. Since the latest version of Firefox supports canvas toDataUrl, it's quite possible that you can use Firefox to generate a reflection, save the reflection into a jpeg and have the reflection work in any browser without JS.

  41. Mooty said:

    If anyone doesnt like the canvas compatibility, you could always try

    Its $5 granted, but its compatible with all browsers, and keeps the reflection generation off of your server!

  42. And said:

    I have similar problem with reflection.js. In xhtml mode there can be only one pic in one line. imho it's because it uses <div> witch is block-line element. If i replace all div's to span's (in-line element) there can be more images in one line, BUT the reflection is on right, not below image 
    if images are in table it's ok as sayd before, but i dont want tables in my page  

  43. Khlo said:

    Well, I don't know. I just suggested it might be a conflict with something else (for example you seem to use lightbox – maybe this breaks reflection) or perhaps you use the align attribute instead of the CSS "float" style – I don't know.

  44. Poivre said:

    Which problem with my HTML.. Could you point me a direction where to look for?

    I got your script on the 12 of's the latest package I believe, isn't it?


    Thank you…

  45. Khlo said:

    I'm unsure why; make sure you have the latest version of reflection.js first as I thought these issues were mainly fixed. Otherwise, there may be an issue with your HTML – I don't know πŸ™‚ Sorry!

  46. Poivre said:

    Fisrt I admit I am not a pro in webdev so I hope when will understand me you won't laugh….

    What I mean is when I use the class reflect on an image on my blog (wordpress, K2 theme), and generally I use it on a thumbnail that links to the original, see example here;; all the lign is "occupied" by the pic….But when I don't use this "class" I am able to align my text around or place few pics next to each other with the effect. As you have done on your demo page. I looked at the source of your page and saw that you put the <table> <tr> and <td> attribute….I tried that, it worked but it made my pics ridiculously small. 

    I hope it's more clear now….And thank you for your pateince and help.

  47. Khlo said:

    Any chance you could elaborate? Didn't quite understand πŸ™‚

  48. Poivre said:


    Thank you very much for this script it really spices up the placement of images on my site. One problem though I am encountering is the fact that when I add the effect to an image, the image itself uses all the line, so if I want to have more than one image on the same line with the effect it's impossible…. Is it possible to tweak the script so the effect do not interfere on the horizontal level but only on the vertical level? Thank you.

  49. Khlo said:

    It will work; it's just the prototype way of doing it and it'll allow you to have more than one onload event. It's so it's less likely to interfere with other scripts. But sure, change it to the following if you don't have any other events:

    window.onload = addReflections;

  50. Qwertyuiop said:

    Ok. One final question…

    What's the purpose of using

    Event.observe(window, 'load', addReflections, false);

    when using

    window.onload = function(){addReflections();};


  51. Khlo said:

    As far as I know, only images can be drawn to a canvas so the answer would be no.

  52. Qwertyuiop said:

    Hi Khlo,

    I've just simplified prototype.js and it still works. Thanks.


    I have one more question. Can reflection.js be made to work with any element?


    Thanks and keep up the great work! 

  53. Khlo said:

    Hi guys,


    Earthsick: I expect this is a bug with the browsers as I read something about canvas transparency support in Mozilla a while ago. Happy to be proved wrong though!

    Qwertyuiop: reflection.js only uses the Element and Event objects AFAIK so you should be able to get rid of everything else.

  54. Qwertyuiop said:

    Hi, reflection.js is a great script! Could you please tell me which part of prototype.js the script requires? Prototype is a big script, and I don't need all of it.

  55. Earthsick said:

    Thanks… this is really amazing.
    But it doesn’t seem to work with transparent GIFs. They degrade in a weird pixelated manner.

  56. Khlo said:

    I’m not sure if it’s possible using canvas – I think I’ve made it 45 degrees before but it looks really strange because the perspective is wrong.

  57. Sharkbait said:

    I like it. Though on larger images, the reflect looks a bit odd.


    Any chance of it being slanted off to the side like at a 45degree.  Kinda like a shadow effect?  For smaller images it works nicely though.


  58. Pulssart said:

    Amazing ! i Use this scirpt on my photoblog ! ! Work perfectly under macosx 10.4.3 safari Version 2.0.2 (416.12) and firefox 1.5 Mac. Work perfectly under Window$ xp service pack 2 with firefox 1.5. Great job.

  59. Khlo said:

    This should fix reflection.js for Safari.

  60. Khlo said:

    I recieved an e-mail from someone who says they’ve managed to fix it in Safari and we’re working together to eliminate any issues with the fix. Safari seems to have problems with drawing on a canvas which is not part of the page.

    For anyone unlucky enough to be stuck on IE the Novell XForms plugin adds support for <canvas>. Obviously it’s not as good as proper support but it means you can at least access some <canvas> rich web applications if you can’t install Firefox.

    Anyone know if KHTML supports <canvas>? 

  61. Pablo Marx said:

    Moving the code does eliminate the undefined values, no exceptions are thrown, etc. But nothing visible happens (i.e. it looks like it does w/o the javascript being ran).

    Reading back all the various values (canvas.width/height, etc) are correct. Looking at the dynamic/generated source shows:

    <DIV><IMG src=”test.jpg” class=”reflect”><BR><CANVAS></DIV>

    If time permits today, I’ll try to poke around more.

  62. Schopenhauer said:

    Hi, those changes don’t help, unfortunately: still no load in safari (i did import the js file as well).

  63. Khlo said:

    Interesting Could you give it a go with the code which adds the gradient after the code which adds the canvas to the document?

    So try moving:

    var gradient = context.createLinearGradient(0, reflect[i].height/2, 0, reflect[i].width);
    gradient.addColorStop(0, "rgba(255, 255, 255, 1.0)");
    gradient.addColorStop(0.9, "rgba(255, 255, 255, 0.5)");

    context.fillStyle = gradient;
    context.fillRect(0, 0, reflect[i].width, reflect[i].height);



    I’m assuming this would be due to a bug in Apple’s canvas implementation.  

  64. Pablo Marx said:

    context.createLinearGradient(0, reflect[i].height/2, 0, reflect[i].width);

    Is returning undefined in Safari, thus the subsequent addColorStep’s are failing.

    Also it seemingly has a problem with:

    context.fillStyle = gradient;

    If I use an existing <canvas> tag, instead of creating it through document.createElement, those problems go away… the reflection doesn’t work, but the problems (undefined) go away.

  65. Slk said:

    You guys are aproaching this from the wrong end, Flash is gonna take this shit over… ppl can live with it

  66. Khlo said:

    Hmm… Thanks. I wonder if there is some Javascript I’ve written which doesn’t work in Safari. Unfortunately I don’t have a mac to test it on nor is there a version of Safari for Windows.

    If anyone using Safari knows what might be the problem please let me know  

  67. Derek Poon said:

    On the latest Safari (version 2.0.2, WebKit 416.13 on Mac OS 10.4, with JavaScript enabled), I don’t see any reflection. Works on Firefox 1.5, though.

  68. Khlo said:

    Hi Gfx πŸ™‚ Nice to see you around. I presume that you recieved my e-mail and you don’t have a problem with this script; if there is then please let me know. Thanks.

  69. Gfx said:

    I am glad to see someone using my idea for real things. As for writing the thing from scratch, well there aren’t many ways to do it…

  70. Khlo said:

    True, to say that canvas will change the entire face of the web is overkill just as saying Ajax will. If theres anything which will change the face of the web it’ll be the semantic web (the real web 2.0). Canvas is progressive enhancement rather than a total reboot.

  71. Sunny Boy said:

    Valid points. But I don’t see how it’s going to change the face of web design. The canvas tag is one step further towards a more dynamic web, but the problem is that most people will (at the moment) never see its effects.

  72. Khlo said:

    Pretty awesome, sounds like a new golden age of web design is coming.

    canvas can do some really immense stuff.

    It is true that a graphics program could do the exact same thing but canvas really comes into it’s own with dynamic content. For example, what if you wanted to add a reflection effect to user’s avatars? You could either manually photoshop a reflection or you could use canvas and allow the browser to generate the reflections.

    Another great thing about using canvas is that it can integrate with javascript events. If you made reflections in Photoshop you would also find it hard to get it to automatically blend in with the background colour.

    This script gives people with up to date browsers some additional eye candy and everyone else won’t notice a thing.

  73. Sunny Boy said:

    Although it’s quite amazing, I personally don’t see a widespread use of it. Sure, it looks nice; very nice, infact. But I don’t just see why anyone would want to use it. It can still be done with a graphics program with less effort.

    I agree that until the leading (by statistics) web browser, IE, supports the canvas tag, then it is of no real use. It’s a start though that Microsoft is using the Mozilla Firefox RSS icon on request. One step at a time. 

  74. Sexysora said:

    When you showed me this, I never thought it would reflect nicely on different coloured backgrounds.

    Pretty awesome, sounds like a new golden age of web design is coming.

  75. Skov said:

    Looks pretty nice, now we just need more browsers to support canvas

Leave a Reply

E-Mail Notifications: By default, I'll drop you an e-mail when there's a reply to your comment. If you don't want to receive such a notification, please select the "Don't Subscribe" option from the dropdown menu above.