Crossbrowser CSS3 Reflections

Reflections are integral design elements, and if using them sparingly one can achieve sleek and modern looks for their website. (Un)fortunately, the only browser that supports CSS reflections out of the box is Google Chrome, via the -webkit-box-reflect property, which did not make it to the final draft of CSS3 and is unlikely that other browsers will ever support it. For portability purposes, on GFACE it was not possible to have icons exported directly with a reflection, and in this blogpost we will explain our cross-browser approach for achieving a CSS-only reflection effect on any element.

If you are impatient and anxious to see how we do it, go straight to the demo, otherwise, let’s get into a few details.

We will use the following markup:

<div class="gf-icon-huge gf-icon-public-cloud gf-icon-reflection">
<div><!-- / --></div>
</div>

The nested <div /> is hidden for any browser except Internet Explorer. The reflection flip and mask are done with CSS inheritance, gradients, generated content and no JavaScript at all.

What we did first was pretty straight forward – we applied a background image, height and width to the parent <div />. To avoid using additional markup for the reflection and the mask we used the ::before and ::after generated content with 100% top offset and inherited background, width and height:

.gf-icon-reflection::before,
.gf-icon-reflection::after
{
content: "";
position: absolute;
top: 100%;
z-index: -1;
width: inherit;
height: inherit;
display: block;
}

.gf-icon-reflection::before
{
background: inherit;
}

Then reloaded… And voila! We have an exact clone of the parent element. In order to achieve real reflection effect we used the CSS transform property with full vertical scaling (-1), which produced for us a fully flipped element:

.gf-icon-reflection::before
{
-moz-transform: scaley(-1);
-webkit-transform: scaley(-1);
-o-transform: scaley(-1);
-ms-transform: scaley(-1);
transform: scaley(-1);
}

Internet Explorer 9 and less do not support CSS transforms, but have had their own implementation long before CSS3 – the vendor-specific flipv() filter:

.gf-icon-reflection::before
{
filter: flipv();
}

What was left was just the gradient mask, which we applied to the ::after content of the parent element:

.gf-icon-reflection::after
{
background: linear-gradient(
90deg, #fff 60%,
rgba(255, 255, 255, 0.8) 100%
);
}

To make it both interoperable and future proof we used the respective vendor-specific properties like -moz, -webkit, -o and -ms for each gradient definition. To make it work on Internet Explorer we used the gradient filter with alpha-channel applied to the nested <div /> element. According to MSDN, a CSS filter can be applied to elements that have layout (the infamous hasLayout property), but unfortunately layout cannot be triggered with the known techniques (such as zoom: 1) on CSS-generated content, that is why we used the nested <div />:

.gf-icon-huge div
{
top: 100%;
position: absolute;
z-index: -1;
width: inherit;
height: inherit;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#7fffffff, endColorstr=#ffffff);
}

In order to display that <div /> on any version of IE, we used the \9 hack instead of conditional comments:

/* IE<10 */
.gf-icon-huge div
{
display: block\9;
}

If you like this solution and you wish to use it in your own projects, you may consider adapting the reflection according to your designs – you can play with the color spread percentage and with the colors. If your background color is different from white you can easily change the reflection’s mask. This fine-tuning is a bit more complicated in Internet Explorer:

  • The percentage of the color spread cannot be set.
  • Only two colors can be defined – start and end color.
  • Opacity is set in the first two letters of the startColorstr and endColorstr values, as this type of declaration allows RGBA channel:
    startColorstr=#alpha red green blue

    or:

    startColorstr=#red green blue
  • Shorthand color values like #000 instead of #000000 do not work (but named color values do).

You can go to the demo or download the example straightaway from this link. If you like our series of front-end-related posts, please, suggest what articles you would like to see here and we will be happy to share our knowledge and experience with you. If you have comments or suggesttions, find me on GFACE – Martin.

The GFACE Team

Play. Together. Live

This entry was posted in CSS3, HTML, HTML5 and tagged , , . Bookmark the permalink.

Comments are closed.