Illusions in CSS

The many new CSS features introduced in the CSS3 spec that are increasingly supported by all the modern browsers have interested me for quite a while. In an attempt to put see how powerful CSS without any JavaScript can be these days I decided to try implementing some of my favourite visual illusions in pure CSS. Most of these had previously only been available as Flash implementations, so it seemed like the exercise would also be good in the name of progress. Not only did it turn out to be good fun, I gained quite a few insights into the current state of CSS at the moment. The results of this exercise so far, and some notes on particular lessons learnt, are presented below.

Note: tested in Chrome 25, FireFox 18 and IE 10.

I used LESS and Lea Verou's -prefix-free in all the illusions in order to keep the CSS code. Both proved very useful, though -prefix-free turned out to have one or two unexpected quirks.

The code, including the more easily digestible LESS CSS files are all available on GitHub. Please do fork and add in more illusions if you want to!

Lucy In The Sky

  Check out this Pen!

This is a variation on a motion illusion originally created by Arthur Shapiro & Justin Charles. It appears to us as though the "bracelet of diamonds" is moving around in 3D space, but actually all that is happening is that the fill colours are oscillating between dark and light (while the edge colours stay constant).

As far as the CSS is concerned, there were a number of interesting parts. Firstly, a commonly found way to create a diamond shape involves playing around with a combination of borders and pseudo-elements. Unfortunately, support for animating pseudo-elements isn't particularly widespread yet so I wasn't able to change the background colour suitably. Furthermore, this approach meant I had to use wrapper divs to fake up borders... yuck! Instead, I used a combination of rotation and scaling transforms to achieve a diamond shape with a border, no faking involved!

Laying out the circle of diamonds was a doddle. After realising that by appropriately using a translation in the transform sequence you can rotate around different origins, I was able to combine :nth-child selectors and a LESS parametric mixin to create a very simple way of not only creating the diamond shapes but also positioning them. The mixin looks like this (updated! Thank you Luke):

.diamondPosition (@index) {
  @degs: (45deg * @index);
  transform: rotate(@degs) translateY(-130px) scaleY(0.5) rotate(45deg);

The full code is available here.

Mutually Interfering Shapes

  Check out this Pen!

In this illusion, devised by Maarten Wijntjes, Robert Volcic & Tomas Knapen, it seems as though the two dots are bouncing off one another as they go around the centre point. Actually the two dots are tracing simple square and circle shapes. However, even when clearly tracing the inner square it seems as though the outer dot follows four arcs rather than a perfectly regular circle.

CSS-wise there is nothing particularly clever going on here: there are two basic animations to create the movement and an animation to fade in the actual shapes.

The full code is available here.

Tilting Pyramid

  Check out this Pen!

Do you see the 3D tilting pyramid? The illusion was created by Pietro Guardini & Luciano Gamberini and results from a combination of different Gestalt principles and the motion of a changing angle.

I created the angled area at the bottom by combining solid and transparent borders. This meant the motion could be created by simultaneously animating the angle and the position of the div (well, actually the top margin in this case). The "pacman" shapes are created by using border-radius for the circular shape and multiple background gradients for the "mouth".

The full code is available here.

Grouping By Contrast

  Check out this Pen!

Hover over the illusion to remove the background colours and see how different it looks.

Initially it seems as though the blobs are grouped diagonally, but if you hover over the illusion the background colours are removed and suddenly the blobs are grouped as rows. The illusion was originally presented by Erica Dixon, Arthur Shapiro & Kai Hamburger and is a wonderful demonstration of how we see colours as relatives rather than absolutes, that is, the perception of a colour is entirely dependent on its context.

The main point of technical interest to come out of implementing this illusion was what initially seemed like a bug in -prefix-free: the filter being applied to the blobs to blur them was not being prefixed appropriately by the library. It turns out this is because filter is actually something of an ambiguous CSS property in most browsers, in that they support it as an un-prefixed property for SVG but not for HTML. This means -prefix-free cannot reasonable recognise how to behave.

The full code is available here.


Do You Need A Conversational UI?

The Catch 22 of Conversational UIs

blog comments powered by Disqus