Create reflection effect using CSS3

Published on: 03-Jun-2011 | By:

  • Print Friendly and PDF
  • Print Friendly and PDF

In a recent project, the client asked me if there is any way to add reflection to images. He wanted this effect because he liked the reflection effect added by designer in the design of his website. But the issue was that he might need to add more images in the future, and he cannot go back to his designer every time. Of course learning photoshop to do it by himself did not excite him either.

This encouraged me to try and create this effect in CSS, and it could prove to be a lifesaver for all. I tried and came up with a solution, which works in all browsers (Yes it works in IE too, not very nicely however).

Before we dive into the code, take a look at the demo page, to get an idea of what we are going to build here.

Following screenshot is taken from Firefox:

Getting started:

To follow along, you need to create an HTML page, a CSS file, and few images. You can also download the source files of my demo page.

I have named my files index.html, style.css, and images are placed in a folder named images.

HTML Code

<div class="image-block">
   <img src="images/book1.jpg" alt="" />
   <div class="reflection">
      <img src="images/book1.jpg" alt="" />
      <div class="overlay"></div>
   </div>
</div>

Each image requires an extra block which contains a copy of the image for reflection and a div with class "overlay" that we will use for adding fading gradient.

I have grouped both image and div into a container div with class "reflection". Let’s call this reflection block for referring it.

Now both original image and reflection block is wrapped into a div with class "image-block". Let’s call this image block. You can have any numbers of image blocks in your code if required, and that’s why I have used classes for CSS instead if IDs.

Ok, this code is simple enough to understand (I guess), so let’s move on to CSS.

CSS Code

 
.image-block { width:78px; margin:0px 10px; float:left; } 
.reflection { position:relative; } 
.reflection img { 
    -webkit-transform: scaleY(-1); 
       -moz-transform: scaleY(-1); 
        -ms-transform: scaleY(-1); 
         -o-transform: scaleY(-1); 
            transform: scaleY(-1); 
    filter: flipv; opacity:0.20; 
    filter: alpha(opacity='20'); 
} 
.overlay { position:absolute; top:0px; left:0px; width:78px; height:120px; 
    background-image: -moz-linear-gradient( center bottom, rgb(255,255,255) 60%, rgba(255,255,255,0) 75%); 
    background-image:   -o-linear-gradient( rgba(255,255,255,0) 25%, rgb(255,255,255) 40%); 
    background-image:     -webkit-gradient( linear, left bottom, left top, color-stop(0.60, rgb(255,255,255)), color-stop(0.75, rgba(255,255,255,0))); 
    filter: progid:DXImageTransform.Microsoft.Gradient( gradientType=0, startColor=0, EndColorStr=#ffffff); 
} 

Let’s go through the code step by step.

 .image-block { width:78px; margin:0px 10px; float:left; } 

I have added width to image block equal to the width of image, and by doing so, the reflection div will automatically move down, as it will not have space for second image.

Now we have two images as shown in image below

Next I have added position relative to the reflection block. This will add the positioning coordinates for its child elements with position absolute.

  .reflection { position:relative; } 

Now we have our stage ready, so let’s begin the magic with CSS3

 
.reflection img { 
    -webkit-transform: scaleY(-1); 
       -moz-transform: scaleY(-1); 
        -ms-transform: scaleY(-1); 
         -o-transform: scaleY(-1); 
            transform: scaleY(-1); 
    filter: flipv; 
    opacity:0.20; 
    filter: alpha(opacity='20'); 
} 

This block of CSS code uses CSS3 and IE filters to flip the image vertically and add transparency to the image.

Because transform property is not completely implemented by all browsers, we need to add browser prefixes to make it working in each browser engine.

We have used transform: scaleY(-1); to simply flip the image vertically. Same effect can be achieved in Internet Explorer by adding filter: flipv;

Last 2 lines opacity:0.20; and filter: alpha(opacity='20'); adds transparency to the image.

Following image shows, what we have achieved so far:

Now we only need to add a gradient to add fading effect to the image, we have CSS3 gradients handy for this.

Some facts about CSS3 gradients:

  • CSS3 Gradient property is implemented differently in all browsers.
  • CSS3 Gradient property is not supported by IE including IE9.
  • Gradient in CSS is only supported on background images.
 
.overlay { position:absolute; top:0px; left:0px; width:78px; height:120px; 
    background-image: -moz-linear-gradient( center bottom, rgb(255,255,255) 60%, rgba(255,255,255,0) 75%); 
    background-image:   -o-linear-gradient( rgba(255,255,255,0) 25%, rgb(255,255,255) 40%); 
    background-image:     -webkit-gradient( linear, left bottom, left top, color-stop(0.60, rgb(255,255,255)), color-stop(0.75, rgba(255,255,255,0))); 
    filter: progid:DXImageTransform.Microsoft.Gradient( gradientType=0, startColor=0, EndColorStr=#ffffff); 
} 

Because CSS3 gradient property is only supported on background images, we cannot add it directly on our reflection image.

I have added a div with class "overlay" for this purpose. I have positioned this div above reflection image, with position absolute. And added a width and height equaling to image.

At last I have added CSS3 gradient property to this overlay div, which has added a fading effect to the image.

Following is the end result.

This works fine in all browsers, except internet explorer.

Microsoft has provided a gradient filter, but it does not provide the ability to add a start and end point for gradient, like CSS3 gradient property.

Following is the result in Internet Explorer after adding the gradient filter.

As an idea, you can play with heights of reflection div and overlay div to cut the image and improve the effect in Internet Explorer. I am still looking for a better solution for Internet Explorer.

Please let me know if you any suggestions for improvement of this effect, or share the links if you use this effect in your projects.

I’m looking forward to your comments and thank you so much for reading!

  • Malone R777

    I have not implemented this technique but first response after reading is “Thank you for your time and efforts!”.  Now it’s playtime!

  • Lyjuboy

    for IE, 
      you can use a background image (png file with gradient inside)  for  the overlay instead of the gradient effect 

    • http://www.xhtml-lab.com Jaspreet Kaur

      Using images for IE is a nice idea, however there are few concerns:
      1. you will need to use IE Hack for this
      2. it will be difficult to match if you have a complex background
      3. If these images are added dynamically by client, he will need to add 2 images, and it’s quite possible that client is not technical enough to create the reflection effect for images.

      • xJp1989

        Using a solid color to transparent background image is no big deal and can be applied to all browser, that’s what I did. Thanks great tut.

      • xJp1989

        Using a solid color to transparent background image is no big deal and can be applied to all browser, that’s what I did. Thanks great tut.

  • Pingback: Riflessi css cross browser | Laboratorio CSS

  • Guest
    • http://www.xhtml-lab.com Jaspreet Kaur

      Yes i know, This property is supported by Safari, Chrome and Firefox with following commands:
      -webkit-box-reflect
      -moz-box-reflect

      However it’s not yet supported by Opera and IE.
      Thanks for your comments.

  • Pingback: Creare un effetto riflesso con i CSS3 | buonaguida.com

  • http://beben-koben.myopenid.com/ Beben Koben

    amazing…this is play with transparent & gradient attribute for to be shadow…
    cool trick ;)

  • http://twitter.com/cyberstream_us CyberStream.us

    Thanks for this tip! Wouldn’t it be cool if you could add a reflection to the image with pseudo-elements:

    img:after {content: url(attr(src));transform: rotate(180deg);
    opacity: 0.35; }

    Then you could add a CSS3 mask to fade it out! Wishful thinking…

  • http://twitter.com/Wwebsites Wouter Mesker

    Why not use a jave script to turn the image and flip it,, and then overlay it with a javascript so every browser support?

  • Pingback: Weekly Design News – Resources, Tutorials and Freebies (N.97)

  • Pingback: Web Development articles, tutorials, help » Blog Archive » Weekly Design News – Resources, Tutorials and Freebies (N.97)

  • Pingback: Weekly Design News – Resources, Tutorials and Freebies (N.97) - WORDPRESS4free | WORDPRESS4free

  • http://twitter.com/uicart UICart

    Superb one :) )
    you could have put a javascript fallback model too
    like this 
    http://davidwalsh.name/javascrip-reflection

  • Pingback: Weekly Design News – Resources, Tutorials and Freebies (N.97)

  • http://www.xhtml-lab.com Jaspreet Kaur

    CSS will not validate because of browser prefixes and Filter.

  • Anoop

    great

  • Matteo

    really helpfull! But it works only if I have a color as website background. Thank you.

  • Reece

    CSS will never validated correctly unless you specifically design your website for one intended browser. which I’m sure will never be required unless you’re creating an in-house CDN for a company where they all use MAC’s where they all use Safari, Chrome or Firefox.

    -o-
    -webkit-
    -moz-

    these browser specific tags undoubtedly cause any CSS code to not be validated by the glorified piece of sh$# that is w3c..

© copyright 2011 XHTML-Lab.com, all rights reserved.