I found an interesting article about will-change property in CSS (which allows to tell the browser beforehand what will change and react proactively). The main reason behind this property is to improve the performance.
As far as I understood I can use it in the following way: jsFiddle (click on the square)
<div class="element"></div>
.element {
width: 50px;
height: 50px;
margin:30px;
background: red;
transition: transform 1s ease-out;
}
.element:hover {
will-change: transform;
}
.element:active {
transform: rotate(90deg);
}
So far so good, but in order to speak about improving in performance, there should be a way to measure this improvement.
So is there a way to measure performance, CPU/GPU utilization with and without will-change?
At the time of writing of this article, only Chrome Canary 36+, Opera
Developer 23+, and Firefox Nightly support the will-change property.
There is an intent to ship it to the stable channel too.
This is the compactability as of today::
http://caniuse.com/#search=will-change
You can Enable the
1. FPS meter
2.Show paint rectangles
in rendering tab in google chrome console.
The FPS rate won't decrease from 60 FPS if you are using will-change property.
Also the show paint rectangle won't be shown.
Will-change property will be most effective if we add to fixed elements.(When scrolling)
Related
In order to fill the whole height of the page, I use height: 100%; for html and body tags,
and it works fine until a browser would be closed and reopened.
(I don't use 100vh because of issues on mobile devices https://nicolas-hoizey.com/2015/02/viewport-height-is-taller-than-the-visible-part-of-the-document-in-some-mobile-browsers.html )
Steps to reproduce:
Open https://angelika94.github.io/rick/ in Google Chrome on iPhone
(you will see that navigation (Morty and Beer) is placed on the bottom of the page) screenshot of css Rick with navigation
close the browser and remove it from multitasking navigation:
https://support.apple.com/en-us/HT201330
open the browser again (you will see that bottom navigation moved off the "first screen" and now you need to scroll to see it)
screenshot of css Rick without navigation
the page will be fixed by itself in these cases:
update page
rotate the device to landscape
open and close browser's navigation by tabs
close and reopen browser without closing it in multitasking nav
Why does it happen? How can I fix this behavior?
Thank you in advance!
I had a very different issue, but I think the solution I worked out may work for your situation also, because you mentioned updating the page would fix it.
So I had issues with chrome on android where if you scroll very quickly (not uncommon on mobile), some elements would fail to get re/painted. Searched everywhere for a solution but couldn't find anything that would work.
Finally, I figured out a working fix:
.pagewrap {
transform: translateZ(0);
animation-name: 'repaint';
animation-duration: 3s;
animation-iteration-count: infinite;
animation-play-state: running;
animation-timing-function: linear;
}
#keyframes repaint {from { zoom: 99.99999%; } to { zoom: 99.99998%; }}
So what this does is forces the page to continually repaint on a 3 second cycle.
Maybe I should tweak it to only shift for a fraction of a second every 2 seconds, instead of continually:
.pagewrap {
transform: translateZ(0);
animation-name: 'repaint';
animation-duration: 2s;
animation-iteration-count: infinite;
animation-play-state: running;
animation-timing-function: linear;
}
#keyframes repaint {
0% {
zoom: 99.99999%;
}
99% {
zoom: 99.99999%;
}
100% {
zoom: 99.99998%;
}
}
I tried zoom: 99.99999; to 1 but certain elements that transitioned scale above 1 on some hover effects would show the zoom breathing. So 99.99999 to 99.99998 was what worked for me to make the effect invisible.
Slightly hacky solution that could present performance issues for very long pages, but maybe not, because the browser should only be rendering what's onscreen. The pages I used this on are graphically heavy with a lot of complex multi-layer effects, and this doesn't seem to have a noticeable performance impact.
Seems like many mobile browsers have excessively optimized rendering, which leads to quirky failures with few well documented fixes. Forcing repaints was the only working fix I found.
I tried other, slightly less aggressive, documented methods of forcing repaints. Like adding some text to the page (invisibly) after scrolling stops for 200ms, and such. Nothing worked though, thus my animate-the-entire-page-forever hack.
In your case, some of those other hacks may work better. This article outline all the various things that cause repaints/reflows so you could try doing some of these things via script.
Light way to fix an issue:
Firstly, a tiny js-code*:
function defineVisibleHeight (){
const h = window.innerHeight * 0.01;
document. documentElement.style.setProperty('--vh', `${h}px`);
}
defineVisibleHeight();
window. onresize = defineVisibleHeight; // not mandatory;
*code sample has extra whitespaces to prevent plain copy/paste
With a previous code we found out a true visible area of a screen and stored it as variable for stylesheet;
Finally, css:
.wrapper{
height: calc(var(--vh, 1vh) * 100);
}
I am currently faced with a situation, for which I need to constantly render a flickering animation within a web page. This is currently done by means of CSS, using animation: 0.05s step-end infinite keyframe_name. The keyframe changes the button's background-color at 0% and 50%. As can be expected, using Chrome's Dev tools, this area is constantly being re-painted by the browser, which is leading to an overall poor performance.
I am aware that the use of certain properties, such as the will-change property, or even using the transform: translate3d(0, 0, 0) hack, will enable hardware accelerated rendering. However, opting for either of these options, still hasn't resulted in the desired performance improvement.
The following shows some basic code for what I am trying to achieve (optimizations are not included in code snippet):
#keyframes keyframe_name
{
0% { background-color: red; }
50% { background-color: blue; }
}
button
{
animation: 0.05s step-end infinite keyframe_name;
}
According to a number of online resources, it seems that only the transform and opacity CSS properties make it possible for the browser to optimize compositing. Since neither of these properties can be used to achieve my desired goals, which other approach/es could possibly lead to a performance enhancement, when it comes to the in-browser rendering of such a resource-intensive graphic?
I am building an accordion with animated height on open/close, in which the content height is calculated via JS. I want to ensure the best performance, so I was thinking about forced hardware acceleration.
.accordion-item-content {
overflow: hidden;
transition: height .3s ease;
transform: translateZ(0);
will-change: transform;
}
In the Chrome Dev Tools I can see that the accordion-items are each getting a layer (because of the will-change and/or transform property), but will this result in any performance boost?
Or are transform, opacity and filter the only properties that can ever benefit from GPU rendering, as I understood here: http://www.sitepoint.com/introduction-to-hardware-acceleration-css-animations/
Another question: Does 'will-change: height' do anything? It looks like it's valid (https://developer.mozilla.org/en-US/docs/Web/CSS/will-change), but it does NOT create a layer, I can observe in the dev tools.
Not really will-change or transform: translateZ() will promote your element to it's own layer which get's send over to your GPU.
Have a look at https://csstriggers.com/. You should only animate transform and opacity. Any other properties cause repaint or layout recalculation even if you are using will-change.
I am trying some CSS3 keyframe animations in a web app I'm developing. I have tried both my own custom animations and some provided by animate.css. The result is the same: the animation works fine, but after a while, even if I leave the browser alone, the CPU usage goes up to around 100% and stays there. Killing that process kills the web app, removing the CSS animations gets rid of the problem, so there is no doubt what's causing it. I am mainly using Chrome, and that's where I have seen the problem so far.
Target platforms for the web app includes iOS and Android via Phonegap, Windows and OSX via node-webkit. The problems I describe do not seem to occur in mobile Safari, but what about other platforms? Is this a general problem with keyframe animations? Are there any tricks to avoid this?
EDIT: Added demo link, but unable to replicate the problem. In the full app I am using a number of libraries and frameworks, like AngularJS, Angular-UI, Angular-UI-router, Fastclick, Animate.css, etc. I guess they might interfere somehow? Hard to say, but removing my animations from the app also removed the delayed 100% CPU usage.
HTML:
<button id="start">Start</button> <button id="reset">Reset</button>
<br/>
<div id="ball" class="ball"></div>
Javascript:
document.getElementById('start').addEventListener('click', function(e) {
document.getElementById('ball').classList.add('remove');
});
document.getElementById('reset').addEventListener('click', function(e) {
document.getElementById('ball').classList.remove('remove');
});
CSS:
.ball {
width:100px;
height:100px;
border-radius:100px;
background-color:darkred;
position:absolute;
top:100px;
left:200px;
}
#-webkit-keyframes slide {
from { top:100px; left:200px; }
to { top:100px; left:-100px; }
}
.remove {
animation: slide 1s linear;
-webkit-animation: slide 1s linear;
-webkit-animation-iteration-count: 1;
-webkit-animation-fill-mode: forwards;
}
The cause of the 100% CPU usage is due to the -webkit-animation-fill-mode: forwards declaration, if my suspicion that you're doing your primary testing on Chrome is correct.
It looks like it's a current bug with Chrome (tested on version 30.0.1599.101), according to an article by Wercker and my own research:
For this animation we use animation keyframes and the
-webkit-animation-fill-mode: forwards; so that the sidebar retains its position from the last frame of the animation. An animation normally
would snap back to its original setting after it is finished playing.
This is great for us, but not for Chrome. The CSS animations using
-webkit-animation-fill-mode: forwards; are causing the 100% CPU load bug. It actually only occurs when the CSS animation ends and the tab
is inactive.
This seems to be corroborated by this issue on the Chromium project page.
As Lindsey Bateman says in the article, the bug is fixed in Chrome Beta and Chrome Canary (33.0.1706.0 canary), so we shouldn't be waiting for very long to get this into current Chrome.
If you're using 3d (eg even if not, some recommend tricking CSS into 3d to let the GPU help render), try this trick via mddw
translateZ(0) /* only needed if no CSS-3d commands are used to toggle GPU rendering */
-webkit-backface-visibility: hidden;
-webkit-perspective: 1000;
backface-visibility: hidden;
perspective: 1000;
I got rid of the problem by disabling all extensions. It remains to be investigated which one was responsible. These are the suspects:
AngularJS Batarang 0.4.3
avast! Online Security 8.0.1500
ColorZilla 0.5.4
HootSuite Hootlet 4.0.10
iGetter 2.9.2
Intel® XDK 2.6.1
Ripple Emulator (Beta) 0.9.15
Xmarks Bookmark Sync
I am working on a catalog which uses css -transform attribute to scale each 'swatch' upon hovering.
Here's my problem: In some browsers and on certain sites, when you hover over the swatches, it causes the page to 'blink' as your roll over them. I cannot nail the problem down either, on one site it may be unique to Safari, on another it may only happen in Chrome, on another it's perfectly fine.
Wish I had more information, but maybe someone else has run into a similar problem.
.swatch {
-webkit-box-shadow: #EFEFEF 2px 2px 0px;
-webkit-transform: scale(1);
-webkit-transition-duration: 0.2s;
border: 1px solid white;
position: relative;
z-index: 1;
.swatch:hover {
position:relative;
z-index:10;
transition-duration: 0.2s;
transform:scale(1.8);
-webkit-transition-duration: 0.2s;
-webkit-transform:scale(1.8);
}
It also seems that the problem is remedied when removing any z-index attributes, but then the hover swatch is behind the other swatches; which does not work for this project.
Any thoughts are appreciated.
I've had success adding
-webkit-backface-visibility: hidden;
to the offending element (.swatch in your case).
However, test it in older versions of Chrome and Safari to make sure it doesn't break anything else. In my experience, Safari 4 specifically isn't a big fan.
I had the same problem at this morning. But I found an answer on the web few moments ago.
To prevent the Blink issue, put the follow property on your .swatch class (not on :hover):
-webkit-transform-style: preserve-3d;
Try changing position:relative to position:absolute, and/or specify position attributes (top: x, left: y.
No idea if it will work, just throwing it out there.
when mouse over the images(img:hover) in chrome works fine. you can use like this
.swatch img:hover
http://dinolatoga.com/2009/09/18/amazing-imag-hover-effects-with-webkit-and-css/
I had the same problem try using opacity instead of z-index
img:hover{
opacity: 0;
}
On a different subject, I had the same effect (the awfull blink).
However, it wasn't on hover principles. It was on a dragable area, I wanted as smooth as possible on iPad. The area was originally moved with a css margin-left property.
Then, I used -webkit-transform':'translate3d(X, Y, Z)' for the smooth rendering, which is the case.
BUT, the use of translated3d made the famous blink, on the first drag (on iPad only).
Thanks to Fábio ZC, the -webkit-transform-style: preserve-3d; worked perfectly to get rid of the blink
For those who wants to know more about the -webkit-transform-style: preserve-3d and what is involved.
Back to the original problem, these are my thoughts:
You mention Safari & Chrome (so, webkit). Is the problem only on those browser? Which would lead to -webkit suspicious properties.
If so, -webkit-backface-visibility: hidden; or -webkit-transform-style: preserve-3d; are still good candidates to be tried:
Did you attach them on the .swatch class? (not hover state, otherwise, they will be considered too late, as the animation will be played directly)
You stated that the whole page is blinking? Strange as only the swatches should be impacted.
I deleted this line from the hovering class:
"display: none;" and amazingly, that worked. Try it and hope it solves your problem.