Create Windows-8-like 3D animations with CSS3 and jQuery

The emergence of Windows 8 and particularly the style and design of it created a whole new design trend. There are various examples on the web showing how to achieve Windows-8-like design in you apps and websites. This great tutorial will show you how to create beautiful Windows 8 3D animations that look awesome.

(If you are interested of another example of how to achieve Windows 8 style, have a look at 5 Coding Frameworks you should try!  –  the Metro UI CSS.)

windows 8 animations

The CSS

For this demo, I’ve created the styles for mobile first. The following code samples contain widths that are applicable to small screens. Towards the end of this section, we’ll take a look at using media queries to adjust them for larger screens.

First, let’s take a look at the the styles for the demo wrapper, which is the container that wraps the entire demo. One important item to note is that, when the wrapper, we need to make sure to set a perspective to activate the 3D space, otherwise, the whole demo will look flat and two dimensional.

/*general styles*/
 html{
 height:100%;
 overflow-y:scroll;
 overflow-x:hidden;
 }
 body{
 width:100%;
 height:100%;
 line-height:1.5;
 font-family:'Lato', sans-serif;
 font-weight:300;
 font-size:16px;
 }
 ul{
 list-style-type: none;
 }
/*dashboard and pages styles*/
.demo-wrapper{
 background:url("1.png");
 background-size:cover;
 padding: 4em .5em;
 width:100%;
 perspective:3300px;
 position:relative;
 overflow:hidden;
 border-bottom:1px solid #eee;
 }
 .dashboard{
 margin:0 auto;
 width:100%;
 padding:1em;
 }
 .col1, .col2, .col3{
 width:99%;
 margin:1em auto;
 }
 .page{
 width:100%;
 height:100%;
 color:white;
 text-align:center;
 font-size:3em;
 font-weight:300;
 position:absolute;
 right:0;
 top:0;
 opacity:0;
 transform-origin: 100% 0%;
 transform:rotateY(-90deg) translateZ(5em);
 }
 .page-title {
 margin-top:1em;
 font-weight:100;
 font-size:2.5em;
 }
/*styling the pages*/
.page.random-page{
 background:#DFD4C1;
 }
.page.todos{
 background:#2FB1BE;
 }
/*the close button in the upper right corner of each page*/
.close-button{
 font-size:1em;
 width:1em;
 height:1em;
 position:absolute;
 top:1.25em;
 right:1.25em;
 cursor:pointer;
 border:1px solid white;
 line-height:.8em;
 text-align:center;
 }

I’ve set the original position of each page in the 3D space by first rotating it about the y-axis (the vertical axis), then I moved the page 5em to the left of the screen by using translateZ. You should always remember that when you transform an element in 3D, you also transform its coordinate system along with it. What I wanted to do is move the page 5em to the left of the screen, but instead of using translateX I needed to use translateZ because after the first transformation (i.e. the rotation about y axis) the coordinate system was also rotated. So now the z-axis points towards the left, and the x-axis is pointing towards you, the viewer.

These are the styles for the dashboard thumbnails, along with the transition defined on :hover.

.big, .small{
 float:left;
 margin:0 auto 1%;
 font-size:2em;
 color:white;
 text-align:center;
 height:4.5em;
 font-weight:300;
 overflow:hidden;
 padding:.75em 1em;
 cursor:pointer;
 transition:all 0.3s ease-out;
 }
 .big:hover, .small:hover{
 background:white;
 }
 .big{
 width:100%;
 }
 .small{
 width:49%;
 margin-right:2%;
 }
 .big p {
 line-height:1.5;
 margin-top:.6em;
 padding:0 .3em;
 transition:all 0.3s ease-out;
 }
 .small.last{
 margin-right:0;
 }
/*icon fonts styles*/
.icon-font{
 font-size:2em;
 }
 .big .icon-font{
 float:left;
 }
 .lock-thumb .icon-font{
 margin-left:25%;
 }
/*styling the dashboard boxes*/
.weather-thumb {background:#F2854C;}
 .weather-thumb:hover {color:#F2854C;}
.paint-thumb {background:#85A9C3;}
 .paint-thumb:hover {color:#85A9C3;}
.cpanel-thumb {background:#83A8C3;}
 .cpanel-thumb:hover {color:#83A8C3;}
.games-thumb {background:#04ACAD;}
 .games-thumb:hover {color:#04ACAD;}
.news-thumb, .calculator-thumb {background:#EBB741;}
 .news-thumb:hover, .calculator-thumb:hover {color:#EBB741;}
.videos-thumb, .shortcut-thumb{background:#BEA881;}
 .videos-thumb:hover, .shortcut-thumb:hover{color:#BEA881;}
.lock-thumb, .alarm-thumb {background:#EF3A5B;}
 .lock-thumb:hover, .alarm-thumb:hover {color:#EF3A5B;}
.piano-thumb, .favorites-thumb, .notes-thumb {background:#385E82;}
 .piano-thumb:hover, .favorites-thumb:hover, .notes-thumb:hover {color:#385E82;}
.photos-thumb {background:#BEA881;}
 .photos-thumb:hover {color:#BEA881;}
.calendar-thumb, .organizer-thumb {background:#8BBA30;}
 .calendar-thumb:hover, .organizer-thumb:hover {color:#8BBA30;}
.todos-thumb {background:#2FB1BE;}
 .todos-thumb:hover {color:#2FB1BE;}
.todos-thumb p{
 margin-top:.8em;
 }
 .todos-thumb-span{
 display:block;
 margin-top:1.5em;
 }
 .todos-thumb:hover p{
 margin-top:-2.7em;
 }

Each thumbnail contains an icon and may or may not also contain a paragraph with the text content. The box’s overflow is set to hidden in order to hide the span that reaches below the bottom border of the box. The paragraph has a margin-top set to .8em and, once the thumbnail is hovered, the margin is set to -2.7em, thus transitioning the thumbnail title and the details span upwards to the center of the thumbnail.

Related post:  jQuery simpleGallery - Fullscreen and responsive lightbox

All the pages, except the login screen, have the same initial position in the 3D space. Once a box is clicked, a corresponding class is added to the page that will open via JavaScript. Each class calls for a specific animation meaning that each page will get a class name that will define the 3D transition it will use.

These are the available class names:

.openpage{
 animation: rotatePageInFromRight 1s cubic-bezier(.66,.04,.36,1.03) 1 normal forwards;
 }
 .slidePageLeft{
 transform: rotateY(0) translateZ(0) ; opacity:1;
 animation:slidePageLeft .8s ease-out 1 normal forwards;
 }

I’m using the animation shorthand property here. The last value, “forwards,” corresponds to the animation-fill-mode property. This must be set to “forwards,” otherwise the page will go back to its initial “closed” position after the animation is over. In order to keep the page open, and be able to create sequential animations, the element has to stay in the final state defined by the first animation, and from there we can start the second animation.

These are the animations for the pages:

@keyframes rotatePageInFromRight{
 0% {transform:rotateY(-90deg) translateZ(5em);opacity:0}
 30% {opacity:1}
 100% {transform: rotateY(0deg) translateZ(0) ; opacity:1}
 }
/*When the close-button is clicked, the page slides to the left*/
 /*note that the start of the second animation is the same state as the
 end of the previous one*/
@keyframes slidePageLeft{
 0% {left:0; transform: rotateY(0deg) translateZ(0) ; opacity:1}
 70% {opacity:1;}
 100% {opacity:0; left:-150%; transform: rotateY(0deg)}
 }

In order for the second animation to start off from where the first one finished, you have to define the final state of the first animation in the initial state of the second one.

The login screen (which could just as well be any content screen, but I chose to make it look like a login screen), is initially positioned -150% to the left, which is off canvas to the left of the screen. When the lock thumbnail is clicked, the screen gets a class name that will trigger the animation and so it slides into view. The input on the login screen is a dummy, so no password is required. Simply press the unlock button and the screen will slide back to the left while also appearing to be “sliding backwards” along the way.

Here are the styles of the login screen, the class name applied to the screen when its thumb is clicked:

.login-screen{
 background:#EF3A5B;
 height:100%;
 width:100%;
 position:absolute;
 top:0;
 left:-150%;
 color:white;
 text-align:center;
 font-weight:300;
 z-index:1;
 }
 .login-screen p{
 font-size:6em;
 margin-top:2em;
 font-weight:100;
 }
 .myform{
 margin:2em auto;
 width:300px;
 }
input{
 display:block;
 line-height:40px;
 padding:0 10px;
 width:260px;
 height:40px;
 float:left;
 }
 #unlock-button{
 background:black;
 color:white;
 font-size:1em;
 float:left;
 border:0;
 height:2.5em;
 width:2.5em;
 padding:.3125em;
 text-align:center;
 cursor:pointer;
 border-radius:2px;
 }

And here are the the animations triggered upon locking/unlocking the login screen:

.slidePageInFromLeft{
 animation: slidePageInFromLeft .8s cubic-bezier(.01,1,.22,.99) 1 0.25s normal forwards;
 }
 .slidePageBackLeft{
 opacity:1;
 left:0;
 animation: slidePageBackLeft .8s ease-out 1 normal forwards;
 }
 @keyframes slidePageInFromLeft{
 0% {opacity:0; }
 30% {opacity:1}
 100% {opacity:1; left:0;}
 }
 @keyframes slidePageBackLeft{
 0% {opacity:1; left:0; transform: scale(0.95);}
 10% {transform: scale(0.9);}
 70% {opacity:1;}
 100% {opacity:0; left:-150%;}
 }

Now let’s get to the dashboard animation.

Related post:  Pure CSS3 Side Navigation Menu

The dashboard also fades into view and fades back when a thumbnail is clicked. Once a thumb is clicked, the dashboard translates back along the z-axis, decreases in size, and fades its opacity gradually until it becomes 0. When a page is closed, the dashboard fades back into view.

The three columns in the dashboard fade in one after the other, with a slight delay between them. When a page is closed, a class name is added to each column (again via JavaScript), and each of these classes calls the animation with a specific delay.

Here are the classes and the animations applied to the dashboard:

.fadeOutback{
 animation: fadeOutBack 0.3s ease-out 1 normal forwards;
 }
 .fadeInForward-1, .fadeInForward-2, .fadeInForward-3 {
 /*remember: in the second animation u have to set the final values reached by the first one*/
 opacity:0;
 transform: translateZ(-5em) scale(0.75);
 animation: fadeInForward .5s cubic-bezier(.03,.93,.43,.77) .4s normal forwards;
 }
.fadeInForward-2{
 animation-delay: .55s;
 }
 .fadeInForward-3{
 animation-delay: .7s;
 }
@keyframes fadeOutBack{
 0% {transform: translateX(-2em) scale(1); opacity:1;}
 70% {transform: translateZ(-5em) scale(0.6); opacity:0.5;}
 95% {transform: translateZ(-5em) scale(0.6); opacity:0.5;}
 100% {transform: translateZ(-5em) scale(0); opacity:0;}
 }
 @keyframes fadeInForward{
 0% {transform: translateZ(-5em) scale(0); opacity:0;}
 100% {transform: translateZ(0) scale(1); opacity:1;}
 }

Now let’s define how the styles will adjust to various widths using media queries. The three columns of the dashboard will change from having full width and will be floated beside each other.

@media screen and (min-width: 43.75em){
 .col1,.col2,.col3{
 float:left;
 margin-right:1%;
 width:49%;
 }
 }
 @media screen and (min-width: 64em){
 .col1,.col2,.col3{
 float:left;
 margin-right:.5%;
 width:32%;
 }
 .col3{margin-right: 0;}
 .col1{margin-left:2em;}
}

The Javascript

All click events in the demo app are handled with JavaScript. For this example, I am using jQuery. Event handlers are going to be set on each of the dashboard boxes, and when a click event is detected, we’re going to retrieve the name of the corresponding page from the data-page attribute, and open that page.

Other click events that will be handled include clicking on the close button in each page or the unlock button in the login screen.

function showDashBoard(){
 for(var i = 1; i <= 3; i++) {
 $('.col'+i).each(function(){
 $(this).addClass('fadeInForward-'+i).removeClass('fadeOutback');
 });
 }
 }
function fadeDashBoard(){
 for(var i = 1; i <= 3; i++) {
 $('.col'+i).addClass('fadeOutback').removeClass('fadeInForward-'+i);
 }
 }
$('.big, .small').each(function(){
 var $this= $(this),
 page = $this.data('page');
 $this.on('click',function(){
 $('.page.'+page).addClass('openpage');
 fadeDashBoard();
 })
 });
$(".lock-thumb").click(function(){
 fadeDashBoard();
 $('.login-screen').addClass('slidePageInFromLeft').removeClass('slidePageBackLeft');
 });
$('#unlock-button').click(function(){
 $('.login-screen').removeClass('slidePageInFromLeft').addClass('slidePageBackLeft');
 showDashBoard();
 });
$('.close-button').click(function(){
 $(this).parent().addClass('slidePageLeft')
 //this function will detect the end of the animation, and remove the classes added before
 //so that the page will get back to its initial position after it has been closed
 .one('webkitAnimationEnd oanimationend msAnimationEnd animationend', function(e) {
 $(this).removeClass('slidePageLeft').removeClass('openpage');
 });
 showDashBoard();
 });

Created by  Sara Soueidan.

Divi WordPress Theme

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *

By continuing to use the site, you agree to the use of cookies. more information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close