This article is a variant of a tutorial in my book (Pro CSS3 Animation), promoted by a reader bringing my attention that there was a tiny but vital piece of code missing from the printed text. I’ve also wanted to upgrade the code ever since I wrote it, so this entry is a chance to address both issues.
The HTML
The construction of this CSS 3D gallery is fairly straightforward: eight images, absolutely stacked inside a relatively positioned figure element, which in turn is placed inside a containing div.
<div id="gallery">
<figure id="spinner">
<img src="wanaka-tree.jpg" alt="">
<img src="still-lake.jpg" alt="">
<img src="pink-milford-sound.jpg" alt="">
<img src="paradise.jpg" alt="">
<img src="morekai.jpg" alt="">
<img src="milky-blue-lagoon.jpg" alt="">
<img src="lake-tekapo.jpg" alt="">
<img src="milford-sound.jpg" alt="">
</figure>
</div>
(I’ve left the alt attribute values of the images blank for the sake of brevity).
The CSS
The initial CSS is also fairly simple: the z of the origin for the images and figure (the axis around which the elements will be transformed) is pushed “back” into the screen by 500 pixels, with the figure provided a transition speed of one second. The images are 40% wide, with a left of 30% positioning them in the center of the figure, making the gallery perfectly responsive.
body { background: #100000; font-size: 1.5rem; }
div#gallery { perspective: 1200px; }
figure#spinner { transform-style: preserve-3d; min-height: 122px; transform-origin: 50% 50% -500px; transition: 1s; }
figure#spinner img { width: 40%; position: absolute; left: 30%; transform-origin-z: 50% 50% -500px; outline: 1px solid transparent; }
(The min-height on the figure and outline on the images are provided to avoid the issues I discussed in my recent article on CSS 3D tips and tricks, while the min-width on the images ensures that the photographs do not grow so large as to overlap).
The images are then evenly distributed around the central axis, using nth-child selectors:
figure#spinner img:nth-child(1) { transform: rotateY(0deg); }
figure#spinner img:nth-child(2) { transform: rotateY(-45deg); }
figure#spinner img:nth-child(3) { transform: rotateY(-90deg); }
figure#spinner img:nth-child(4) { transform: rotateY(-135deg); }
figure#spinner img:nth-child(5) { transform: rotateY(-180deg); }
figure#spinner img:nth-child(6) { transform: rotateY(-225deg); }
figure#spinner img:nth-child(7) { transform: rotateY(-270deg); }
figure#spinner img:nth-child(8) { transform: rotateY(-315deg); }
At this stage, you’ll see that the 3D carousel is naturally responsive: as you narrow the browser window, the images get smaller, while the separation between them increases.
I have not used vendor prefixes in the code thus far, as I’d rely on Lea Verou’s prefix-free to take care of that. However, prefixes will need to be addressed in the JavaScript code that controls the rotation of the gallery.
JavaScript-driven controls
Finally, we want to add two controls for the gallery: a left and right arrow to control the spin. Adding the linked elements below the page, we’ll use them to call on a JavaScript function that carries a variable.
<a href="#" style="float: left" onclick="galleryspin('-')">◀</a>
<a href="#" style="float: right" onclick="galleryspin('')">▶</a>
As you can see, the left-hand arrow carries a negative sign as a variable to a galleryspin function:
var angle = 0;
function galleryspin(sign) {
spinner = document.querySelector("#spinner");
if (!sign) { angle = angle + 45; } else { angle = angle - 45; }
spinner.setAttribute("style","-webkit-transform: rotateY("+ angle +"deg); transform: rotateY("+ angle +"deg);");
}
The function looks at the sign variable, and, based on its absence or presence, adds or removes 45 degrees from the orientation of the gallery, producing the result you see at the top of this article.
Issues
The code presented here works well in all modern browsers, with issues in just two:
Safari (and mobile Safari) still retains a bug that moves the figure element over the z-axis, rather than the
transform-origin, making the result appear larger on screen, while throwing off the center of rotation. While there are ways around this (applying more transforms, rather than moving theorigin) I have not shown them here to keep the code simple… and I expect the issue to be resolved in the next Safari update.IE 10 may also have issues with the gallery, as the browser can have problems supporting CSS 3D when it is applied to child elements.
Conclusions
Outside of wider browser support, there many possible improvements that we could make to the 3D carousel gallery, including:
I’ll show those additions, and more, in future articles. Play with this code on CodePen
Pro CSS3 Animation, Apress, 2013
Massive Head Canon
The New Defaults
CSSslidy