CSS reflections

I’m trying to create a reflection of some HTML, where the reflection fades away. Example of what I have so far: http://www.iliveinabin.com/reflection-test/

For Webkit / blink, this can be achieved by using

-webkit-box-reflect: below 0 linear-gradient(rgba(0,0,0,0) 50%, rgba(0,0,0,1));

However, the reflection overlays the following content. I am not sure how the following content can be pushed down below the reflection, unless the item being reflected had a definite height, in which case you could apply a margin-top to the list’s following sibling, e.g.

#list-webkit +*{margin-top: 50px;}

For Firefox the reflection can be created using css generated content, with a transform applied and -moz-element() used as the background to copy the item you want reflecting.

However, there does not seem to be a way to fade out the reflection in Firefox. You can apply a gradient on top, but this only really works if your site has a plain background. I have tried using mask with an SVG, but I think I must be doing something wrong (either with my SVG or CSS code) as it just makes the reflection disappear completely.

<!DOCTYPE html>
<html>
<head>
    <title>CSS Refection test</title>
    <style type="text/css">
        html,body{
            height: 100%;
        }
        body{
            background: #000 linear-gradient(#777, #000) 0 0 no-repeat;
            /*background-size: 100% 300px;*/
            color: #fff;
        }
        a:hover{
            color: #f00;
        }


        #list-webkit{
            -webkit-box-reflect: below 0 linear-gradient(rgba(0,0,0,0) 50%, rgba(0,0,0,1));
        }

        #list-moz:after {
            content: "";
            display: block;
            background: linear-gradient(to bottom, rgba(60,60,60,1) 0%,rgba(67,67,67,0) 100%), -moz-element(#list-moz) 0 -50px no-repeat;
            width: auto;
            height: 50px;
            margin-left: -40px; /*undo -moz-padding-start applied to parent ul otherwise the reflection will be indented*/
            -moz-transform: scaleY(-1);
            /*mask: url(gradient.svg#r);*/
        }
    </style>
</head>

<body>
<h3>Webkit / Blink:</h3>
<ul id="list-webkit"><li><a href="#">Item One</a></li><li><a href="#">Item Two</a></li><li><a href="#">Item Three</a></li><li><a href="#">Item Four</a></li><li><a href="#">Item Five</a></li></ul>
<p>Here is some text.</p>
<h3>Gecko:</h3>
<ul id="list-moz"><li><a href="#">Item One</a></li><li><a href="#">Item Two</a></li><li><a href="#">Item Three</a></li><li><a href="#">Item Four</a></li><li><a href="#">Item Five</a></li></ul>
<p>Here is some text.</p>
</body>
</html>

Hi,

I don’t think you can automatically create enough space for the reflection as you can’t find the 100% height of the element. Percentage padding refers to the width of the element so you can’t pad it out exactly either. Only height and position percentage values can refer to the height of an element but are no use in this case.

Regarding the svg mask for Firefox then I just used your code with the svg mask form Stu’s example here and it worked out of the box (with the id change).

Thanks for the confirmation on the spacing issue and the info on the SVG mask. I modified my SVG to use a mask element like Stu’s, and changed the width and height of the <rect /> to 1 (rather than 100%) and got it working. His idea of using absolute positioning to make the behaviour between Webkit and Gecko the same was very helpful too.

I’ve just been checking to see if MS has a filter based solution for IE, but it seems not unless you want to have two copies of the HTML (which wouldn’t give a true reflection anyway).