Create the cubic-roll animation in pure CSS

Sakshi Shreya
6 min readAug 7, 2019

--

Recently I revamped my portfolio from Vanilla JavaScript to Angular 7. Obviously, that in itself is a big change, but I also changed the complete theme AND complete look and feel. I am happy with what I have got at the end. The people on twitter gave me such precious suggestions throughout the process and it helped me make the portfolio so much better.

One day I tweeted this. I got such a nice response and was asked to write a tutorial on how to make it:

Note: I created this site using Angular, but I have not used anything specific to Angular for animations. Animations are pure CSS and anyone can make it for their site.

Make HTML

HTML part is very simple. Just have a look at the codepen code and you will understand.

The JS

We will write the CSS later. First, we will create the JS which is very simple and intuitive. There are two pages: Cover(front) and back. When cover is open, back is closed and vice-versa. The JS handles just that.

isCover = true;

This is done so that we can initially define that we are currently viewing the cover page

function flip() {
isCover = !isCover;

const base = document.querySelector('.base');
const appFront = document.querySelector('.front');
const appBack = document.querySelector('.back');

if(isCover) {
appFront.classList.add('open');
appFront.classList.remove('close');
appBack.classList.remove('open');
appBack.classList.add('close');
base.style.height = '100vh';
} else {
appFront.classList.add('close');
appFront.classList.remove('open');
appBack.classList.remove('close');
appBack.classList.add('open');
setTimeout(() => {
base.style.height = 'auto';
}, 1000);
}
}

In this flip function, we first invert the state of isCover variable. Then we select the HTML elements and apply/remove relevant classes or styles.

The last portion is a little interesting. I have waited for 1 second before setting the base height to auto. This is done because the animation takes 1 second to rotate. After that, we set the base height so that we will see the scroll bar only when animation has ended.

Interesting CSS

This is the most interesting part of the animation. You may get to know some new things in CSS when you will read this section. So, fasten your belt. We are about to start a new journey.

.base {
perspective: 2000px;
background: rgb(241,159,77);
overflow: hidden;
}

First of all we set the style for base.

What is perspective?

perspective was introduced in CSS-3. The value (2000px) defines the distance between the screen and your eyes. There are some formulas written in the browser that create a 3D effect when you try to rotate any element which is present inside an element containing “perspective”.

Right now, “base” has this perspective, so, its children- front and back will look 3D when we will rotate them.

You can try to play will the value. More smaller the value, browser will think you are more close and thus give you much more depth. For this situation, 2000 suits best both for large and small screens.

Why overflow?

Because, when we are on cover page, if we don’t use overflow, we will see some part of the background screen because of the “back” element. We want to hide that. That is why we want height and overflow on cover page. We can remove overflow on back page. Because it does not do anything there. But that will increase the JS code. So, we will let it be like that.

.front, .back {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}

min-height - This is set to 100vh to cover atleast the whole page.

What is vh as in 100vh?

Just like px, em, % etc. there are many other units in CSS that make your site responsive.

1vh = 1% of View Height.

That means, 100vh = 100% of view height.

Note: You can check other CSS measurement units here.

display: flex - I have used flex to center the element. This is totally upto you whether you want to use it or not.

justify-content - Centers the text in horizontal direction in this case. But in my portfolio, it centers in vertical direction.

align-items - Centers the text in vertical direction in this case. But in my portfolio, it centers in horizontal direction.

.front {
background: rgb(68,132,206);
color: white;
transform-origin: bottom;
}

Most of the code here is self explainatory.

transform-origin - By default, this property is ‘center center’. This means when we try to transform the element, it will be transformed from center in both x and y direction. tranform-origin: bottom means, now the transform will start from bottom in x direction and center in y direction.

transform-origin behavior
.back {
background-color: white;
background-image: linear-gradient(0deg,rgba(241,159,77,.5) 1%,transparent 2%),linear-gradient(90deg,rgba(241,159,77,.5) 1%,transparent 2%);
background-size: 30px 30px;
transform-origin: top;
}

Background portion is a little tricky in this part. Maybe I will write about the background in some other blog.

transform-origin - Here again, I have used the same concept as explained above. You can see that when we rotate the block in the animation (from front face), it seems as if there is a hinge at the bottom of the front face. We rotate the front face and at the same time move the hinge to top. Similarly, there is a hinge at the top of the back face. We rotate the face and at the same time move the hinge up.

When we flip from the back face, the hinge is still at the same place, but we move it down. I hope, this clears some doubts instead of increasing them. If you are still confused, please observe the movement in the animation.

.front.open {
animation: flipFrontOpen 1s linear;
animation-fill-mode: forwards;
}
.front.close {
animation: flipFrontClose 1s linear;
animation-fill-mode: forwards;
}
.back.open {
animation: flipContentOpen 1s linear;
animation-fill-mode: forwards;
}
.back.close {
animation: flipContentClose 1s linear;
animation-fill-mode: forwards;
}

These are the triggers of animations. They trigger animation whenever ‘open’ or ‘close’ classes are applied to ‘front’ or ‘back’.

animation-fill-mode - This property tells CSS to stop at the point where animation stops. For e.g. let’s say, we have a block that has 100px height. We increase it’s height to 150px using animation. When the animation stops, the height will revert back to 100px instantly. To stop it at 150px, we write animation-fill-mode: forwards.

@keyframes flipFrontClose {
from {
transform: rotateX(0deg);
margin-top: 0vh;
}
to {
transform: rotateX(90deg);
margin-top: -100vh;
}
}

I will explain this animation, other is similar for front face. Please look in the codepen code for others.

This animation will be triggered for front-face when animation starts from front face and ends at back face.

Initially, the front-face is at 0 deg and at the end it will be at 90 deg. This part is easy. But what about that margin?

When we rotate an element, it still takes up its initial space in the DOM. Since we have provided a fixed height of 100vh to front-face, it will keep taking 100vh in DOM even when it is at 90 deg. Means, the cover will be empty now and you will see the backface after scrolling down. To solve this issue, we give a negative margin to the front face so that it shifts up and does not take space.

This also solves that problem where we have to move the hinge upwards.

@keyframes flipContentOpen {
0% {
transform: rotateX(-90deg);
margin-bottom: -100vh;
opacity: 0;
visibility: hidden;
}
10% {
opacity: 0;
visibility: visible;
}
30% {
opacity: 1;
}
100% {
transform: rotateX(0deg);
margin-bottom: 0vh;
opacity: 1;
visibility: visible;
}
}

This animation is a little tricky. This animation will be triggered for back-face when animation starts from front face and ends at back face.

Intially, backface is at 90 deg and at the end it will be at 0 deg. This part is easy. Margin part is also clear now (I have explained it in the above section).

The problem here is that when the backface is at 90 deg, it is drawn over a small part of the front-face. If you remove the opacity, you will be able to see it. That is why, we start from 0 opacity. We keep the opacity 0 till 10% till it has rotated a little bit. Then we slowly increase the opacity so that it looks like it is appearing from fog. And After 30%, we keep opacity to 1.

I hope I was able to explain things properly. I would love to have feedback from you. You can connect on various places. Open my portfolio, travel to the back face and you will easily find me at different sites. Feel free to follow me and thanks for reading.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Sakshi Shreya
Sakshi Shreya

Written by Sakshi Shreya

Web UI developer in Edelweiss.

Responses (2)

Write a response