This week I felt like doing something Christmas related, it seemed quite relevant. Instead of enjoying the summer sun that a New Zealand Christmas offers I decided to build an experimental landing page to share. Hope you enjoy it.

What is it?

We wanted a neat way to send our users a present for the holiday season. The obvious way to give a present is in a box that they can open. Who opens presents in a 2D space? Maybe Mario but I don’t think he’s one of our users. Here is my Christmas Landing equipped with a 3D present fully animated.

Let’s break it down.

The Layout

The new version of Skeleton responsive boilerplate came out recently so I decided to use that. It gives a base which doesn’t get in the way and it is basically a better browser default. This allows me to extend it really easily, pairing their grid system with our repeatable regions means I can set up the layout and hand it off. Check it out, I highly recommend it.

The Snow Background

The Snow background adds a really nice effect. It uses a set of background images paired with CSS animations to make them move separately from one another. A full tutorial is available on designmodo.com.

@keyframes snow {
    0% {
        background-position: 0px 0px;
    }
    100% {
        background-position: 500px 1000px, 400px 400px, 300px 300px;
    }
}

body {
    background-color: #eee;
    background-image: url('snow.png'), url('snow2.png'), url('snow3.png');

    animation: snow 20s linear infinite;
}

The Box

The Box uses 3D transformations to align all the edges. I originally based the code off a tutorial found by googling “CSS Cube”. It goes in depth about the 3D transformations. One very important attribute to note is transform-style: preserve-3d;, this tells the browser to act in a 3D space. If your transforms and transitions are looking very flat then this is probably what is missing. FYI, colours used are from the Google Material Design colour pallete.

<section class="cube-wrapper">
    <div class="cube">
        <figure class="front"></figure>
        <figure class="back"></figure>
        <figure class="right"></figure>
        <figure class="left"></figure>
        <figure class="top"></figure>
        <figure class="bottom"></figure>
        <figure class="shadow"></figure>
    </div>
</section>

This box will live in two states, ‘open’ and ‘closed’. I want the difference between the states to be a single class on the parent element. This way I can toggle between the states with just:

$(".cube-wrapper").click(function () {
    $(this).toggleClass("open");
});

The closed state has 4 segments on the top all pointed inwards. This is just four divs occupying the four different quadrants of the parent square. I did it this way instead of adding more parent figures to keep things modular.

<figure class="top">
    <div class="lower lower-left"></div>
    <div class="lower lower-right"></div>
    <div class="upper upper-left"></div>
    <div class="upper upper-right"></div>
</figure>
.cube .top div {
	width: 50%;
	height: 100%;
	position: absolute;

	font-size: 60px;
	transform-origin: left center;

	border: 1px solid #3E2723;
	box-sizing: border-box;
}

.cube .top .lower {
	height: 50%;
	width: 100%;
	line-height: 96px;
}

.open .cube .top .lower {
	z-index: 2;
}

.cube .top .upper-right {
	transform-origin: right center;
	transform: translateZ(0px) translateX(98px);
	background: #795548;
}

.cube .top .lower-right {
	transform-origin: bottom center;
	transform: translateZ(-1px) translateY(98px);
	background: #8D6E63;
}

.cube .top .upper-left {
	transform-origin: left center;
	transform: translateZ(0px);
	background: #8D6E63;
}

.cube .top .lower-left {
	transform-origin: top center;
	transform: translateZ(-1px);
	background: #795548;
}

This CSS places the 4 flaps in the correct position using transforms. The Z translations are very important here. The upper flaps need to be 1px above the others to prevent any overlapping effects. Another important part are the transform origins, these say where the animations should originate from.

For the open state we want the elements to flip across from the outside edge which is where we have set the transform origin.

.open .cube .top .upper-right {
	transform: translateZ(-1px) translateX(98px) rotateY(150deg);
	background: #795548;
}

.open .cube .top .lower-right {
	transform: translateZ(-1px) translateY(98px) rotateX(-150deg);
	background: #A1887F;
}

.open .cube .top .upper-left {
	transform: translateZ(-1px) rotateY(-150deg);  
	background: #A1887F;
}

.open .cube .top .lower-left {
	transform: translateZ(-1px) rotateX(150deg);
	background: #795548;
}

We have translated the elements to be all on the same Z plane. I chose 150 degrees very intentionally, if it gets too close to 180 degrees the browser can’t decide which way to rotate the flaps. The inverse rotation through the box didn’t look that realistic so I decided to use 150 degrees.

A Shadow to top it all off

Quite a simple effect gives the whole scene a lot more depth. I replicated the bottom edge of the box, extended it and changed the background.

.cube .shadow {
	transform: rotateX(-90deg) translateZ(101px) translateX(0);
	width: 355px;
	background: rgba(0,0,0,0.1);
	border: 0;
	padding: 2px;
}

.open .cube .shadow {
	transform: rotateX(-90deg) translateZ(101px) translateX(100px);
}

The Animations

This is where a great looking box comes alive. Everything to this point has been built using transforms and a single class change. This means that all the hard work has been done and we can just roll over some CSS transitions.

First we want to add the transitions to the original state. This will allow us to synchronise the different parts when the box is closing.

.cube {
	transition: transform 1s ease 0,
				background 1s ease 0;
}

.cube .top div,
.cube .shadow {
	transition: transform 1s ease 1s,
				background 1s ease 1s;
}


.cube .top .lower {
	transition: transform 1s ease 0,
				background 1s ease 0,
				z-index 0 ease 0;
}

Second we want to add the transitions to the .open state. This will allow us to synchronise the different parts when the box is opening.

.open .cube {
	transition: transform 1s ease 2s,
				background 1s ease 2s;
}

.open .cube .top div,
.open .cube .shadow {
	transition: transform 1s ease 0s,
				background 1s ease 0s;
}

.open .cube .top .lower {
	transition: transform 1s ease 1s,
				background 1s ease 1s,
				z-index 0 ease 1s;
}

You can try these out by clicking any box on this page.

All Together Again

Why would I ever use this?

This shows just how much you can achieve with CSS; 3D transformations, animations and handy boilerplates lets you get a lot done in a very short amount of time. Also it’s Christmas, and who doesn’t like to give out presents.

That’s it

This landing page was a great afternoon project, plugging together a whole lot of different tutorials into a really useful resource. If you like it feel free to contribute to the GitHub Repository. I’d love to add some other branches with different holidays. If you have any questions or want to spread some cheer be sure to comment below. Merry Christmas.