Experiment 2: 360° view Skyscraper at night made only with CSS gradients and 3D transforms - No JS or external/ embedded resources (images, data URIs).

Alcides Queiroz
5 min readMar 26, 2018

Firstly, I want to say that for the next few weeks I’ll be a little busier than normal, so my Pen experiments and OSS contributions will decrease a little (or even pause completely) until at least the middle of April. I’ll try to post some technical articles in the meantime.

Maybe you already saw my CSS-pure version of the Super Mario World classic. If not, here’s the link to the article where I presented it. Today’s experiment certainly is not so nostalgic as Mario.css was, but I have to confess that the former was reasonably more complex than the latter. The number of elements involved made it way harder to fine-tune (windows’ textures and animations, stars’ textures and animations, 3D modeling…).

Today’s experiment

The GIF on the top of this article shows a 3D animation made only with CSS (with Stylus as preprocessor), by using gradients, 3D transforms and animations. Similarly to the Mario Pen, there’s no external or embedded resources being used (JS, images, data URIS and so forth). Even the HTML is tiny:

Each one of those thousands of windows (literally) has its luminosity controlled individually.

For this, I created a mixin to render the texture of each building side (with linear-gradients). It receives a bidimensional Stylus list as a parameter, with the lightness level for each window:

// Each number will set the luminosity of the respective window 
// to a specific level:
// 0 - Turned off
// 1 - Turned on (intensity of 80%)
// 2 - Half light (intensity of 30%)
// 3 - Half light (intensity of 20%)
// 4 - Half light (intensity of 10%)

Here’s an example of an animation frame’s texture data for a building’s side:

building-side-texture(100%,
(4 4 3 2 1 1 2 3 0 0 0 0 3 3 4 4 0 0 0 0 1 1 1 1 2 3 4 4),
(1 1 1 1 0 0 0 0 1 1 1 1 1 1 2 2 0 0 0 0 0 4 3 2 1 1 1 1),
(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0),
(4 4 3 2 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 2 3 4 4),
(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0),
(1 1 2 3 4 4 3 2 1 1 1 1 1 1 1 1 1 1 1 1 2 3 3 2 3 2 1 1),
(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0),
(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0),
(4 4 3 2 1 1 1 1 2 3 4 0 0 0 0 4 4 3 2 2 1 1 1 1 2 3 4 4),
(0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 4 4 4 4),
(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0),
(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0),
(1 1 1 1 2 3 3 2 1 1 2 3 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1),
(1 1 2 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 2 1 1),
(0 0 0 0 0 0 0 0 0 0 0 0 3 4 4 4 0 0 0 0 0 0 0 0 0 0 0 0),
(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0),
(0 0 0 0 3 2 1 1 1 1 2 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0),
(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0),
(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0),
(0 0 0 0 0 0 0 0 0 0 0 0 0 4 3 2 1 1 1 1 2 3 4 0 0 0 0 0),
(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0),
(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0),
(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
);

The textures are so complex that the compilation time is way longer than usual (~25 – 40s). As a consequence, I couldn’t create a normal Pen to host this experiment, as it wasn’t rendered properly (probably due to some kind of CodePen usage limit). So, I created a CodePen project to share it. The interface is a bit different from classic Pens, but everything is there: the live preview and, of course, the CSS and HTML source code. I suggest you to expand the live preview panel to be able to see the “big picture”. If you’re curious to know how it was made, the code is well commented.

It works fine in Chrome 64 and Firefox 59 on MacOS. As some of the techniques applied in this experiment are similar to those used in the Mario Pen, the former shares the latter’s browser-support issue:

  • In Safari, unfortunately, it simply doesn’t work at all, and I’m out of patience and time to debug it for now.
  • I suspect that this issue has something to do with defining gradient backgrounds within animation keyframes. But this isn’t confirmed yet.
  • I didn’t test it with other browsers or devices.

To see the Pen Project, >>>> click here. <<<<
;-)

--

--