CSS Image Reflection
Trying to mimic webkit-box-reflection through moz-element and friends.
HTML
<!DOCTYPE html>
<html lang="en">
<meta charset=UTF-8>
<title>CSS Image Reflection</title>
<section>
<h1>Kittens from Flickr</h1>
<div id=container>Please enable JS for the images to load.</div>
<svg height="0">
<mask id="svgGradientMask" maskUnits="objectBoundingBox" maskContentUnits="objectBoundingBox">
<linearGradient id="g" gradientUnits="objectBoundingBox" x1="0" y1="100%" x2="0" y2="0">
<stop stop-color="white" offset="0"/>
<stop stop-color="white" stop-opacity="0" offset="50%"/>
</linearGradient>
<rect x="0" y="0" width="1.0" height="1.0" fill="url(#g)"/>
</mask>
</svg>
<aside>
<h1>Note:</h1>
<p>You need a recent WebKit browser or Firefox 4 beta to view this demo. WebKit uses <code>-webkit-box-reflection</code>, Firefox 4 uses: <code>mask</code>, <code>-moz-transform</code> and <code>-moz-element</code>.
<p>This is valid HTML5, but invalid CSS (lots of vendor-prefixed CSS properties used)
<p><small>An HTML5 + CSS + JS + SVG experiment by <a href="http://www.marcoos.com">marcoos</a> (<a href="http://twitter.com/marcoos">@marcoos</a>). Flickr querying <a href="http://developer.yahoo.com/yql/">powered by YQL</a>.
</aside>
</section>
CSS
/* some basic styling first */
body {
background:#000;
color: #fff;
font-family: Lucida Grande, Lucida Sans, sans-serif;
}
a {
color: #f00;
text-decoration: none;
}
h1 {
text-align: center;
font-size: 1.2em;
}
aside {
font-size: 0.8em;
width: 50%;
margin: auto;
}
aside h1 {
text-align: left;
}
#container {
text-align: center;
margin-bottom: 160px;
}
#container img {
max-width: 150px;
max-height: 150px;
margin: 5px;
vertical-align: bottom;
}
/* here's where the reflection is rendered by WebKit */
#container a {
display: inline-block;
-webkit-box-reflect:below 5px -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0.5, transparent), to(white));
/* some transitions to be used by :hover below*/
-webkit-transition: 0.5s ease-out;
-moz-transition: 0.5s ease-out;
}
#container a:hover {
-webkit-transform: skew(15deg);
-moz-transform: skew(15deg);
-moz-transform-origin: 50% 25%;
}
/* :-moz-any(x) is used to make the rules only apply in Gecko 2.0+ */
:-moz-any(x), #container {
margin-bottom: 0;
}
/* we'll render the rotated copy of the image in generated content */
:-moz-any(x), #container a:after {
display: block;
max-width: 150px;
margin: 5px;
height: 150px;
content: " ";
color: #fff;
/* rotate the image 180 degrees and mirror it, so that it is a proper reflection */
-moz-transform: rotate(180deg) scaleX(-1);
/* mask the image with an SVG gradient.
* Shame it's not possible to do something like this: mask: -moz-linear-gradient(...),
* so we have to use SVG. */
mask: url(#svgGradientMask);
background-repeat: no-repeat;
background-position: bottom left;
}
/* Make the generated-content pseudo-elements mirror what is displayed in the original elements;
* It would be...
JavaScript
function $(id) {
return document.getElementById(id);
}
function createImageLink(image, index) {
// this will be called as an argument of the Array.prototype.map method
// create an img element using data from the YQL query
var elem = document.createElement("img");
elem.src = "http://farm" + image.farm + ".static.flickr.com/" +
image.server + "/" + image.id + "_" + image.secret + "_m.jpg";
elem.title = elem.alt = image.title;
elem.id = "img_" + index;
// we need to put the image inside the a element,
// so that generated content in :after works
var a = document.createElement("a");
a.id = "s_img_" + index;
a.href = "http://www.flickr.com/photos/" + image.owner + "/" + image.id;
a.target = "_blank";
a.appendChild(elem);
return a;
}
function yqlCallback(res) {
try {
var container = $("container"),
pics, imageLinks;
pics = res.query.results.photo;
imageLinks = pics.map(createImageLink);
container.innerHTML = "";
imageLinks.forEach(function (elem) {
container.appendChild(elem);
});
} catch (e) {
container.innerHTML = "Error. See console for details.";
if (window.console) {
window.console.log(e);
}
}
}
function yqlGetImages() {
$("container").innerHTML = "Loading...";
var queryUrl = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20flickr.photos.search%20where%20text%3D%22kitten%22%20limit%205&format=json&callback=yqlCallback";
scriptElem = document.createElement("script");
scriptElem.setAttribute("src", queryUrl);
document.body.appendChild(scriptElem);
}
window.onload = function () {
yqlGetImages();
}