# CSS3 transitions performance enhancement

I am building a website with heavy CSS3 transitions. The menu is hidden on the left and slides in on hover pushing the main content right. The menu contains transformed elements and has a semi transparent background.

I am concerned about the performance of the animations. When the animation is triggered several times (and also often on the first trigger) the frame rate goes under 30 FPS.

How can I enhance the performance of the animation and have a higher frame rate?

I tried making these animation with jQuery and it is worse.

I made a simple example that has the FPS issue here (hover the envelope icons on the left).

HTML:

body,html,ul,li {margin: 0; padding: 0;}
nav {
width: 0; height: 100%;
position: fixed;
top: 0; left: 0;
background-color: rgba(255, 145, 0, 0.8);
-webkit-transition: width .5s ease-out;
transition: width .5s ease-out;
}
nav:hover {
width: 40%;
}
ul {
list-style-type: none;
position: absolute;
width: 60%;
left: 20%;
}
nav li {
position: relative;
margin: 0.5em 0;
min-width: 5em;
}
nav li:before {
content: '';
position: absolute;
width: 100%;
height: 100%;
background: teal;
z-index: -1;
opacity: 0;
-webkit-transform: skewX(30deg);
-ms-transform: skewX(30deg);
transform: skewX(30deg);
-webkit-transition: opacity .5s ease-out;
transition: opacity .5s ease-out;
}
nav:hover li:before {
opacity: 1;
}
nav li * {
vertical-align: middle;
}
nav img {
height: 2em;
}
nav a {
opacity: 0;
-webkit-transition: opacity .5s ease-out;
transition: opacity .5s ease-out;
}
nav:hover a {
opacity: 1;
}
/* MAIN */

section {
width: 60%;
margin-left: 20%;
min-height: 100%;
background: url(http://lorempixel.com/output/nature-q-g-640-480-9.jpg);
-webkit-transition: margin-left .5s ease-out;
transition: margin-left .5s ease-out;
}
nav:hover +section {
margin-left: 30%;
}
<nav role='navigation'>
<ul>
<li><span><img src="http://www.meilleurs-masters.com/images/classement_icon_mobile_mail.png" alt=""/></span><a href="#">Home</a>
</li>
</li>
<li><span><img src="http://www.meilleurs-masters.com/images/classement_icon_mobile_mail.png" alt=""/></span><a href="#">Clients</a>
</li>
<li><span><img src="http://www.meilleurs-masters.com/images/classement_icon_mobile_mail.png" alt=""/></span><a href="#">Contact</a>
</li>
</ul>
</nav>
<section>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus porta augue vitae bibendum vulputate. Nam sed pulvinar neque. Pellentesque justo neque, aliquet at risus sed, tristique mattis purus. In laoreet diam at porttitor tempor. Vestibulum ante
ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Cras in lorem sit amet purus egestas aliquet. Cras dignissim venenatis facilisis. Suspendisse id dui consectetur, lobortis mauris nec, egestas augue. Sed dui sapien, dignissim
in dui eget, pretium laoreet leo. Phasellus semper faucibus elit eu consequat. Maecenas aliquam nibh sit amet sapien blandit, non sagittis mi vestibulum.</p>
... More content ...
</section>

• Works beautifully for me. I think this is the most efficient method. – Jivings Jul 30 '14 at 10:10
• OK, then I might have to concider simplifying the animation then, it still seems laggy. – web-tiki Jul 30 '14 at 10:21
• meta.codereview.stackexchange.com/q/2163/9357 – 200_success Jul 30 '14 at 18:30

One thing I would like to add is to try and only transition 'cheap' properties like transform and opacity. They cost a lot less to the browser then playing with margin, position and width. The reason why is explained here and a comparison (sort of) is available on jsperf

I went ahead and changed your fiddle to achieve the same effect (almost, might need some fine tuning), but with transforms. The 3d is used because some devices will use the GPU only for calculating 3d transforms (not sure where I read this, and if it still applies, but it won't harm).

Have a look at the updated fiddle

A rough comparison of your fiddle (fps 30) against mine (fps 50) does show a noticeable difference (on mac/chrome).

• Very nice, but the animation now goes behind the background picture in your fiddle. – syb0rg Jul 31 '14 at 20:41
• @syb0rg missed that, but it is just a matter of adding a z-index to the nav. Something like this: jsfiddle.net/mJKdn/5 And as I said, it is more an attempt to demonstrate my point then to exactly replicate the OP's fiddle, though it should be doable. – Pevara Jul 31 '14 at 21:03
• I figured it was something simple like that. +1, since your answer actually addresses the OP's request and contains some very useful information. – syb0rg Jul 31 '14 at 21:24
• Out of curiosity, how did you measure the FPS? – syb0rg Jul 31 '14 at 21:37
• @sybOrg Open Chrome Devtools > hit escape to open the console > click on the 'rendering' tab > check the 'Show FPS meter' option. I think it is a fairly new feature, I accidentally bumped into it lately, and already found a use for it :-D – Pevara Jul 31 '14 at 21:41

I'm pretty new to CSS, but I do have a few notes:

• As @Jivings said, the animation worked nicely for me. No stutter or anything.

• I would use Font Awesome instead of your envelope .png (but keep the PNG as a fallback for cases such as some IE versions not supporting SVG). Why? Because now I can scale the envelope infinitely (due to SVG graphics), and customization of the image becomes a whole lot easier (size, color, drop shadow, etc.).

• You should give a little bit more space between the envelope picture and the item text.

nav:hover a {
margin-left: 5%;
opacity: 1;
}

• I think it looks nicer with the picture and text centered.

nav:hover {
text-align: center;
width: 40%;
}


JSFiddle with the suggested changes.

• If there's just one icon being used, you'd be better off with an SVG with a PNG fallback rather than asking the user to download an entire font file. – cimmanon Jul 30 '14 at 18:51
• thanks for the answer but changing the icons, margins doesn't seem to affect the animation frame rate. – web-tiki Jul 31 '14 at 8:39
• @web-tiki All aspects of the code are up for review, not just the ones that you request (though they may sway whose answer you choose to accept). – syb0rg Jul 31 '14 at 20:38

This really doesn't have anything to do with performance, but you don't need all those span tags in there, I double checked because I didn't know what all you had going on but this will work the exact same and has less tags that need to be parsed.

<nav role='navigation'>
<ul>
<li>
<img src="http://www.meilleurs-masters.com/images/classement_icon_mobile_mail.png" alt=""/>
<a href="#">Home</a>
</li>
<li>
<img src="http://www.meilleurs-masters.com/images/classement_icon_mobile_mail.png" alt=""/>
</li>
<li>
<img src="http://www.meilleurs-masters.com/images/classement_icon_mobile_mail.png" alt=""/>
<a href="#">Clients</a>
</li>
<li>
<img src="http://www.meilleurs-masters.com/images/classement_icon_mobile_mail.png" alt=""/>
<a href="#">Contact</a>
</li>
</ul>
</nav>


I also changed the formatting to how I prefer it (it really doesn't matter as long as it's readable for you and the next guy, and that you have all the syntax correct)

it might speed up if you have the pictures on server you are serving the page from, I would try this with (small) .jpg's that you have downloaded onto your server this way the request isn't bouncing all over the web to make your navigation menu bounce around.

• Not really an answer to the question. And I don't see how the server that houses the images has anything to do with the animation speed... – Pevara Jul 31 '14 at 0:45
• The image has to be loaded at least once, loading it from a second website is inefficient one way or another causing performance to be poor on the loading of the page. The entire (actual) page may not be entirely loaded when the user is trying to make the animation happen, which slows the animation because of all the loading going on. – Malachi Jul 31 '14 at 12:15