With CSS3’s 3D transforms I’ve illustrated how to build a cube and a tetrahedron. It is also possible to create a sphere-like object, albeit with many elements.
3D CSS Sphere
Works in the latest Safari and iOS (just about runs on an iPhone 4).
Recently I’ve been looking at creating applicable 3D carousels. These rely on positioning panels in a circle around a central point (ie. rotation about the Y-axis), I put these panels in an unordered list. A natural extension is to duplicate each <ul> and rotate about the X-axis. With ‘A’ rounds (or lists), and ‘B’ panels per round (<li>s), I built a script that would distribute these in a circular manner, panels about Y-axis, lists about the X-axis, creating a sphere.
The more elements per round and the more rounds, the smoother the sphere. But this soon stacks up and kills Safari. The optimum numbers have been about 9 rounds and 30 panels per round for a decent looking sphere, but that’s 279 3D elements and Safari starts to choke. Allowing the panels to overlap eases this somewhat and leads to a tighter sphere but it still appears blocky.
The biggest gains come with border radius. Using a huge radius that made each panel circular the sphere suddenly gained a lovely curvature, and the number of rounds and panels could be reduced. In the experiment I use 8 rounds and 24 panels (200 elements). This doesn’t start choking until I start aggressively animating.
Playing with this I’ve built a few different styles of sphere. In the experiment I’ve included the blocky “square” version, along with the smoothed out border radius one (default). Marking panels white, and a few black can create a nice eye-ball effect.
Also included in the experiment are versions showing a single round and another style named “contact”. This takes two lists and animates them like the space transportation device in the Jodie Foster movie of the same name.
Animating the border radius on all 192 panels (if your machine can cope), gives a neat kaleidoscope effect, also included in the experiment.
Code
The generated HTML is simply a couple of <div>s containing lists:
<div id="sphere"> <div class="container"> <ul> <li></li> <li></li> … </ul> … </div> </div>
To transform each set of panels into a circle the total number is divided by 360 to get the angle of rotation. Merely rotating will put all panels on top of each other, translating in the Z axis will move them out from the centre point. The correct translation distance so the panels slightly overlap (i.e. the circle radius) is worked out with some simple trigonometry. Lists are rotated in the X axis, simply the number of lists divided by 360.
Looping through each panel for each list, the angles of rotation are gradually increased by the calculated increments and applied to the elements:
var panels = p || this.panels,
rounds = r || this.rounds,
rotationPerPanel = 360/panels,
rotationPerRound = 360/2/rounds,
yRotation, xRotation,
width = this.panelWidth,
zTranslate = (width/2) / Math.tan(rotationPerPanel * Math.PI/180),
$container = this.el,
$ul, $li, i, j;
this.el.html('');
for(i = 0; i < rounds; i++) {
$ul = $('<ul>');
xRotation = rotationPerRound * i;
$ul[0].style[transformProperty] = "rotateX("+ xRotation + "deg)";
for(j = 0; j < panels; j++) {
$li = $('<li>');
yRotation = rotationPerPanel * j;
$li[0].style[transformProperty] = "rotateY("+ yRotation +"deg)
translateZ("+ zTranslate +"px)";
$ul.append($li);
}
$container.append($ul);
}
To achieve the 3D effect we give #sphere some perspective, which forms the containing block. A second container transitions between different transforms, letting us rotate the sphere. The complicated transform parts are applied inline via the JavaScript above, but each list element needs preserve-3d so its direct descendants are transformed in the same 3D space (rather than in 2D).
#sphere {
width: 100px;
height: 100px;
margin: 200px auto;
-webkit-perspective: 800;
-moz-persective: 800;
}
.container {
width: 100px;
height: 100px;
-webkit-transition: -webkit-transform 200ms linear;
-webkit-transform-style: preserve-3d;
-moz-transition: -webkit-transform 200ms linear;
-moz-transform-style: preserve-3d;
}
.container > ul {
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
width: 100%;
height: 100%;
position: absolute;
}
.container li {
width: 98px;
height: 98px;
position: absolute;
display: block;
background: #000;
border: 1px solid #fff;
opacity: 0.1;
border-radius: 50px;
}






Discussion
Looks cool but it says I don’t have 3D support for 3D transformations. I’m using Firefox 4. Do I need to add a plugin?
well done mate that’s incredible
Useful stuff Paul. I’ve been working on implementing 3D using HTML and CSS and was wondering how to to implement spherical objects in my 3D worlds.
I’ve also been wondering if it’s possible to emulate triangles using the CSS border arrow techniques and CSS transform rotations/skews. Cracking that would allow the use of complex 3D meshes, although I think the math will pretty intensive (more so on me than the browser!)
Here’s what I’ve been working on:
http://www.keithclark.co.uk/labs/3dcss/demo/
Great work! Looks amazing!
I am using Chrome 12.0.712.0 dev and your experiments says my browser doesn’t support 3d css transforms. Shouldn’t every Webkit-based browser support them?
Ummm its telling me that Cgrome does not support 3d transforms! INCORRECT
It’s a feature detection test. It is not incorrect. Here is the test file: http://www.paulrhayes.com/experiments/tests/3dtransforms.js?5
It uses media queries to test for transform-3d support.
Chrome reports that it supports 3D transforms but actually renders them in a 2D way. If you click “show me the experiment anyway” you’ll see that it doesn’t work.
Full 3D transforms are currently enabled on the Chrome Beta, and the feature detection correctly spots this and shows the sphere.
Thanks Paul for sharing. Great stuff here!
Great! Something I’ve to study here…
Oh wow.
Comment