Taking inspiration from the marvellous mobile game “Monument Valley”, I created an interactive Escher-esque structure complete with animations and interactions using only CSS (and a sprinkling of HTML to contain the structure of the paths) – No Javascript was used in the production of this thing.
Monument Valley takes you on an adventure through a series of convoluted and geometrically baffling landscapes. It very effectively contorts and distorts your understanding of the physical layout of each section to offer a series of continually shifting paths. I wanted to try and recreate that using only basic web technologies.
The demo will load in the space below. If nothing is showing, give it a few seconds, or click here.
Use the buttons on the left to control the animation.
See the Pen Impossible Isometrics by Robin Metcalfe (@solarisedesign) on CodePen.
See the Pen Impossible Isometrics by Robin Metcalfe (@solarisedesign) on CodePen.
I encountered some fascinating challenges while building this.
Firstly, defining the isometric layout was achieved with use of the CSS3 transform
functionality, to apply a mixture of skew
and translate
effects, with a bit of scale
thrown in to fit everything into the scene.
@include transform-origin(0px 0px);
@include transform(rotateZ(45deg) scale(0.75))
Furthermore, the very nature of the scene, and the “impossible” nature of the isometric layout means that there is inevitably going to be issues with path blocks being both behind and in front of others.
There are some workarounds (e.g. additional classes given to specific path elements) to allow for situations where, say, a block occludes another portion of the path, yet the z-index ordering of the blocks means the rear block shows over the front block. For example, at one point on the path, I’ve defined a “triangle” shape so that the “rectangular” background would not overlap.
I don’t believe that my solution is particularly elegant though – I believe that there are cleaner approaches to developing an isometric viewpoint in CSS. One issue I encountered was when I realised I needed to apply fudge factors to various elements in order to align them more neatly – i.e. adjusting the position of elements manually, rather than having everything align properly based on initial positioning. Further improvements could include more detailed mathematical calculations to properly define the scene and implement a framework that more elegantly defines the view. An end-goal for this animation would be to allow the path to be adjusted fully within the HTML, without the need for additional CSS modifications.
I’d intentionally set myself the challenge of building the scene without using any image assets whatsoever, and allowing only a single HTML element per unique entity within the scene. So, to make it harder on myself, I decided that each individual cloud-bank would be an entity, and I would have to somehow generate an animated row of clouds using only a single element (you can see within the HTML code, elements with the class ‘cloud’)
To achieve this, I decided to make use of CSS’s ability to embed content within elements. And specifically, making use of glyphs to generate rounded graphics.
I searched through the list of glyphs available, and eventually found two, under Miscellaneous Symbols for the playing card symbols hearts (♥) and clubs (♣)
When converted into the appropriate CSS glyph notation these characters could then be repeated, styled and have animated transforms applied to create the cloud effect.
The buttons for the animation make use of CSS’s ability to target elements siblings, and combined with the :checked
pseudo-class of a checkbox element, can be used to set specific attributes on an element based on whether the button is “selected” or not
This is known as the checkbox hack, and I also had to make sure that I added a <label>
element, otherwise it wouldn’t work in Firefox.
// e.g. from the SCSS source
// When <input type='checkbox' class='sunmoon' /> is checked
.sunmoon:checked ~ #world #sunmoon {
@include transform(rotateZ(180deg) translateY(-2 * $block));
}
// When it's *not* checked...
.sunmoon:not(:checked) ~ #world #sunmoon {
@include transform(rotateZ(0deg) translateY(0px));
}
(The sun and the moon are generated from a single HTML element too. I won’t explain how that’s done here, but take a look through the code if you’re interested)
Take a look at any website on the internet. With the exception of those that are heavily Flash-based (or utilise a similar embedded technology), the chances are that you’ll be looking at a combination of HTML and CSS to achieve the look-and-feel of the site.
CSS is what makes the web look good. It defines the rules and parameters which bind the style-less elements of HTML together (without CSS, websites would look no more impressive than the first website ever made)
A lot of sites will use CSS for styling fonts, changing background colours etc. But there are some other extremely interesting ways in which CSS can be applied – and especially if you consider that it’s historically a tool for applying styles to content, the range of things you can achieve by using CSS alone are astonishing.
Especially with the recent improvements introduced by CSS version 3, features such as animations and transitions mean that it’s now possible to implement fairly complex movement and interaction within the visual styles of a website.
The fact that something like this can be done without the use of Javascript (essentially, CSS is not a “language”, traditionally not being something used to “do things”, rather to “style things”) is testament to the power of styling rules within modern browsers.
Further (optimistic) improvements may include:
I have a feeling those extra features may be a long way off…
Robin is the dedicated developer behind Solarise.dev. With years of experience in web development, he's committed to delivering high-quality solutions and ensuring websites run smoothly. Always eager to learn and adapt to the ever-changing digital landscape, Robin believes in the power of collaboration and sharing knowledge. Outside of coding, he enjoys diving into tech news and exploring new tools in the industry.
If you'd like to get in touch to discuss a project, or if you'd just like to ask a question, fill in the form below.
Send me a message and I'll get back to you as soon as possible. Ask me about anything - web development, project proposals or just say hi!