CSS keyframe animation CPU usage is high, should it be this way? - css
I use following keyframe animation on several elements:
#keyframes redPulse {
from { background-color: #bc330d; box-shadow: 0 0 9px #333; }
50% { background-color: #e33100; box-shadow: 0 0 18px #e33100; }
to { background-color: #bc330d; box-shadow: 0 0 9px #333; }
}
#-webkit-keyframes redPulse {
from { background-color: #bc330d; box-shadow: 0 0 9px #333; }
50% { background-color: #e33100; box-shadow: 0 0 18px #e33100; }
to { background-color: #bc330d; box-shadow: 0 0 9px #333; }
}
.event_indicator {
display: inline-block;
background-color: red;
width: 5px;
margin-right: 5px;
-webkit-animation-name: redPulse;
-webkit-animation-duration: 1s;
-webkit-animation-iteration-count: infinite;
animation-name: redPulse;
animation-duration: 1s;
animation-iteration-count: infinite;
}
On my computer I am getting around 40% CPU usage both in Chrome and Firefox.
Is it the current state of animations (nice but not usable for now) or am I missing some magic property?
You can check the following sample with the same animation:
http://jsfiddle.net/Nrp6Q/
Yes, this is normal because you have several infinite-loop animations on the page. The CPU is therefore continually doing work while these elements are rendered. There is a "magic" property that will significantly cut-down the CPU usage and that is:
transform: translateZ(0);
This will composite the elements into their own layers (by tricking the browser into thinking it will be doing 3D transforms) and the browser should, in most cases, take advantage of GPU acceleration, lessening the burden on the CPU. For me this cut it down by about 20% (almost half).
To read more about this technique take a look at: http://ariya.blogspot.com/2011/07/fluid-animation-with-accelerated.html
Additionally, the more keyframes you have in the animation, the more taxing it will be as well. Just try the animation with the middle keyframe cut out and you will see another substantial (~10-12%) drop in CPU usage.
Lastly, not all properties are equal -- box-shadow is much harder for the browser to animate smoothly than, say, background-color. Leaving all of the keyframes intact but dropping the box-shadow property, using the translateZ(0) trick had my CPU usage hovered at only 10-11%.
As much as it pains me to say this, for infinite-loop animations an animated .gif is going to perform much, much better than CSS3 in the current state of browser animation, especially if you plan for many of them to remain rendered on the page for some time.
Update 2017:
For those still finding their way to this question and answer, translate3d(0, 0, 0) provides the same benefit as translateZ(0), you're just also setting translateX() and translateY() at the same time. Please ignore the comment by #Farside as he uses translate3d(X, Y, Z) in his demo but does not compare it to translate(X, Y), which would show that using this technique still makes a significant difference.
According to this question, some people have found better performance across all browsers, especially Chrome, with transform: rotateZ(360deg).
One of the possible ways to reduce the load on CPU, is to use a so called null transform hack, which is often hailed as something of a silver bullet. In many cases it will drastically improve rendering performance in WebKit and Blink browsers like Chrome, Opera and Safari.
Usage of the "Null transform hack" (a hardware compositing mode)
The null transform hack basically does two things:
It switches on the hardware compositing mode (assuming it's supported for the platform)
It creates a new layer with its own backing surface
To "force" a browser, simply add one of these CSS properties to the element:
transform: translateZ(0);
/* or its friend: */
transform: translate3d(0, 0, 0);
When working with 3D transforms, it's good to have these properties as well to improve the performance:
backface-visibility: hidden;
perspective: 1000;
Caveats of the "null transform hack"
Enabling a hardware acceleration in CSS3 for a lot of objects may slow down performance!
Apparently, each null 3D transform creates a new layer. However, force-hacking layer creation may not always be the solution to certain performance bottlenecks on a page. Layer creation techniques can boost page speed, but they come with a cost: they take up memory in system RAM and on the GPU. So even if the GPU does a good job, the transfer of many objects might be a problem so that using GPU acceleration might not be worth it. The cite from W3C:
However, setting up the element in a fresh layer is a relatively expensive operation, which can delay the start of a transform animation by a noticeable fraction of a second.
Moving a few big objects has a higher performance, than moving lots of small items when using 3D-acceleration. So they must be used wisely and you need to make sure that hardware-accelerating your operation will really help the performance of your page, and that a performance bottleneck is not being caused by another operation on your page.
Moreover, a GPU is designed specifically for performing the complex mathematical/geometric calculations, and offloading operations onto the GPU can yield massive power consumption. Obviously, when hardware kicks in, so does the battery of the target device.
The modern way: the will-change property
The progress is not standing on the one place... W3C introduced the will-change CSS property. To cut the long story short, the will-change property allows you to inform the browser ahead of time of what kinds of changes you are likely to make to an element, so that it can set up the appropriate optimizations before they're needed.
Here's what they say in the the draft:
The will-change property defined in this specification allows an author to declare ahead-of-time what properties are likely to change in the future, so the UA can set up the appropriate optimizations some time before they’re needed. This way, when the actual change happens, the page updates in a snappy manner.
Using will-change, hinting to the browser about an upcoming transformation can be as simple as adding this rule to the element that you’re expecting to be transformed:
will-change: transform;
When developing for mobile, developers are forced to take the wide array of device constraints into consideration while writing mobile web apps. Browsers are becoming smarter, and sometimes, it's better to leave the decision to the platform itself, instead of overlapping acceleration and forcing the behavior in a hacky-way.
I had a similar case of high CPU usage when animating some elements with CSS3. I was animating the "left"-property of ~7 elements, with some opacity- and shadow-properties used in my whole page. I decided to switch to jQuery.animate, which sadly didn't improve the performance at all. My CPU (i7) was still at ~9-15% while displaying the page, several tricks (translateZ, etc) didn't really improve the performance either - while having my layout messed up (some absolute-positioned elements were involved, ouch!).
Then I stumbled upon this wonderful extension: http://playground.benbarnett.net/jquery-animate-enhanced/
I simply referenced the .js-file, didn't make a single change at the jQuery transitions, and my CPU usage is now 1-2% on the very same page.
My recommendation: when facing CPU issues using CSS3 transitions, switch to jQuery + the animate-enhanced-plugin.
You can also use this on any of the following class elements where you want to use GPU instead of CPU
.no-cpu {
transform: translateZ(0);
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
}
<element class="event_indicator no-cpu">animation...</element >
To a particular case of 'pulsing' background animation, reported here, I've come up with a css+js solution.
In my case the background animation was on background-position property rather than on the background-color, but the principle is the same.
Ok, let's say you have a block with a particular background:
<div class="nice-block">...</div>
Let's style it: (scss)
.nice-block {
background-color: red;
//or it can be: background: linear-gradient(45deg, #red, #white, #red);
//and: background-size: 600% 600%;
//the transform and will-change properties
//are here to only enable GPU
transform: translateZ(0);
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
will-change: transform;
transition: background-color 5s ease;
//if you want to add a pulsing effect
//to a gradient, see the following two lines:
// background-position: 0% 50%!important;
// transition: background-position 5s ease;
&.animated {
background-color: white;
//and in case of gradient animation:
// background-position: 100% 50%!important;
}
}
Now it's time to make the effect happen by adding a class 'animated' to the block with some JavaScript:
var bgAnimateTimer;
function animateBg () {
clearTimeout(bgAnimateTimer);
bgAnimateTimer = setTimeout(function () {
clearTimeout(bgAnimateTimer);
bgAnimateTimer = setTimeout(function () {
document.querySelector('.nice-block').classList.toggle('animated');
//jQuery alternative is:
// $('.nice-block').toggleClass('animated');
animateBg ();
}, 5000); //5 seconds for the animation effect
}, 2500); //2.5 seconds between each animation
}
animateBg ();
This improved performace in my case by ~15 times.
(i) Note to calculate seconds for transition and timeouts correctly both in css and js if you want values different from 5 seconds.
Besides all these answers, I've found another way to optimize it. The answer is simply to change animation Xs inifinite linear to animation Xs inifinite steps(20,end). Or even steps(60,end).
The rationale is that the web is doing very advanced calculation to calculate the animation from one state to another endlessly (and they try to smooth things out). By applying a step function, it cuts a (close to) continuous transition to 20 or 60 different separate states. Theoretically it will provide less smooth result compared with linear, but however, if you get a step function to 60, human eyes could tell no difference among a lot of animations.
I hope this helps!
Animate endless loops with JS instead of CSS infinite to increase CPU perfomance
Method 1 - Change animation to ''
#keyframes comet4Translate {
0% {
transform: translateX(0%) translateY(-50%);
}
100% {
transform: translateX(100%) translateY(100%);
}
}
#keyframes comet1Opacity {
0% {
opacity:1;
}
100% {
opacity:0;
}
}
#XMLID_640_{
transform: scale(.8) translateX(-20%) translateY(-20%) translateZ(0);
animation: comet4Translate 7.5s 3s ease-in-out alternate, comet1Opacity 8s .5s ease-in-out alternate;
will-change: transform;
will-change: opacity;
}
createAnimation = (selector, intervalDelay) => {
setInterval(() => {
$(selector).css('animation', 'none')
setTimeout(() => {
$(selector).css('animation', '')
}, 3000)
}, intervalDelay)
}
// first comet
createAnimation('#XMLID_640_', 16000)
Method 2 - Use transition instead of animation
#XMLID_640_{
transform: scale(.8) translateX(-20%) translateY(-20%) translateZ(0);
animation: comet4Translate 7.5s 3s ease-in-out alternate, comet1Opacity 8s .5s ease-in-out infinite alternate;
will-change: transform;
will-change: opacity;
opacity: 1;
}
#XMLID_640_.animated {
transform: scale(.8) translateX(150%) translateY(150%) translateZ(0);
opacity:0;
}
let switcher
const animateViaJs = selector => {
setInterval(() => {
if (!switcher) {
switcher = true
$(selector).css('transition', 'opacity 3s ease-in-out, transform 4s ease-in-out')
} else {
switcher = false
$(selector).css('transition', 'none')
}
document.querySelector(selector).classList.toggle('animated')
}, 5000)
}
animateViaJs('#XMLID_640_')
Method 3 - AnimeJs
#XMLID_640_{
will-change: transform;
will-change: opacity;
translateZ: 0;
}
const createAnimeJsLoop = (selector, intervalTimer, cfg) => {
const tl = anime({ loop:true, targets: selector, easing: 'easeInQuad', ...cfg })
setInterval(() => {
tl.pause()
setTimeout(() => tl.restart(), 5000)
}, intervalTimer)
}
createAnimeJsLoop('#XMLID_640_', 30000, {
opacity: [
{ value: 1, duration: 0 },
{ value: 0, duration: 2000 }
],
translateX: [
{ value: '-20%', duration: 0 },
{ value: '150%', duration: 3000 }
],
translateY: [
{ value: '-20%', duration: 0 },
{ value: '150%', duration: 3000 }
],
translateZ: 0
delay: 3000
})
Related
What is the most reliable way to hide elements and fade them in purely with CSS transitions?
I want to hide an HTML element when the page loads, then fade it in with a CSS transition. My plan is to set the opacity to 0, and then use a CSS animation to transform it to 1. But I am worried that the content will remain hidden in old browsers that can't handle CSS transitions. Is there a safer way to hide the content? Or to exclude this code from browsers that can't handle it?
As always, your problem is with older versions of IE. http://caniuse.com/#feat=css-animation I'm a big believer in progressive enhancement amd handling things CSS only. Using Javascript could provide fallback for older browser or using libraries like Modernizr but I hate these kind of solutions and they come with there own problems. What if the visitor has JS disabled? Luckily we can safely let older browser ignore the fade in animation. Just set opacity on 1 for the default div you want to fade in and start the keyframe animation at opacity set to 0. div { height: 300px; width: 300px; background-color: red; opacity: 1; animation: fadeIn 7s ease infinite; } #keyframes fadeIn { 0% { opacity: 0; } 50% { opacity: 1; } 100% { opacity: 0; } } https://jsfiddle.net/3rzL0xz8/
GPU Acceleration of animated and blurred content
Question: Why does my CPU register ~30% when blur is applied versus ~6% when no blur is applied to an animated object? Details: I have a set of randomly generated items on a page that have a CSS animation assigned (in a CSS file) and randomly generated values for width, height, and importantly, blur, applied inline. CSS file styles looks like: animation-name: rise; animation-fill-mode: forwards; animation-timing-function: linear; animation-iteration-count: 1; -webkit-backface-visibility: hidden; -webkit-perspective: 1000; -webkit-transform: translate3d(0,0,0); transform: translateZ(0); width, height and blur are applied inline via style attribute. <div class="foo" style="width:99px;height:99px; filter:blur(2px); -webkit-filter:blur(2px) opacity(0.918866247870028); -moz-filter:blur(2px) opacity(0.918866247870028); -o-filter:blur(2px) opacity(0.918866247870028); -ms-filter:blur(2px) opacity(0.918866247870028);"></div> With the blur enabled my CPU usage is ~30%. When I disable the blur, CPU usage goes down to ~6%. What's happening here? Is chrome only able to GPU accelerate when no blur is applied? If so, why? Update 1: The animation rise looks as follows: #keyframes rise { 0% { transform: translateY(0px); } 100% { transform: translateY(-1000px); } }
I don’t think the blur is actually causing your issues, it just seems to make it more noticeable than before. The problem is that the transform: translateY in your animation is overwriting the transform: translateZ(0) you’re using to force GPU acceleration. This is a timeline recording for the the code you’re running right now, notice how there’s all this activity on the main and raster threads: Now compare this to a recording where I applied will-change: transform to the .foo: No activity on the main and raster whatsoever. There’s two steps to applying this fix: Apply will-change: transform to .foo. This will let the browser know you intend to change that property and have it render that element on the GPU to account for this. No versions of Edge and IE support will-change at the moment. Therefore we’ll use transform: translate3d(0, -1000px, 0); in the animation to force GPU acceleration. Note this is a hack, so we’ll detect support for will-change and use transform: translateY in browsers that support it. Final code: #keyframes rise { 0% { transform: translate3d(0, 0, 0); } 100% { transform: translate3d(0, 1000px, 0); } } #supports (will-change: transform) { #keyframes rise { 0% { transform: translateY(0px); } 100% { transform: translateY(1000px); } } } div { width: 100px; height: 100px; background: #f00; animation: rise forwards 2s linear infinite; will-change: transform; } See here for a working version: http://jsbin.com/mosuvikoto/edit?html,css,output
Don't blur it in inline styles. Put your blur in the style file.
Performant CSS3 animation (Simple animation still not performant in Chrome Developer Tools)
I am struggling with finding a way to make CSS page transition perform well in google chrome. In Chrome developer tools on the timeline I noticed some red markers and they all say the same thing: Long frame times are an indication of jank and poor rendering performance. Read more at the Web Fundamentals guide on Rendering Performance. On the app that I was working on that seemed legit and I tried to investigate, but could not find the source. I've make a simpler demo and I still get the red marker: http://codepen.io/anything/full/qOOpza/ .page { position:absolute; top:0; left:0; width:100%; height:100%; background:#ccc; &--1 { background:green; } &--2 { background: yellow; } &.moveToRight { animation: moveToRight ease .5s; animation-fill-mode: forwards; } &.moveToLeft { animation: moveToLeft ease .5s; animation-fill-mode: forwards; } } #keyframes moveToRight { from { } to { transform: translateX(100%); } } #keyframes moveToLeft { from { } to { transform: translateX(0); } }
I have been playing around with ytour demo, and I found 2 issues: First, changing from translate to translate3d improves (at least in my system) a little bit the performance. So, writing this #keyframes moveToRight { from { transform: translate3d(0%, 0px, 0px); } to { transform: translate3d(100%, 0px, 0px); } } is better. (This has been told several times before, but it is always good to check). Also, a new property should help somewhat . setting will-change: transform; should prepare the browser for a future change in this property. But I haven't been able to see any difference. Second, there seems to be a problem in the way Chrome gathers statistics. You have "Screenshots" enabled. And this seems to be the main cause of the delays, the time that Chrome needs to render and store the screenshots. By definition, the time needed by a performance tool to do its work shouldn't be computed in the analysis. But this doesn't seem to be the case here... I would say this is a bug. At least in my case, changing both issues makes the red markers almost disappear And, in the remaining marked frames, there doesn't seem to be any performance issue. Notice in the screenshot that the frame duration is 25.57 ms long, but the CPU time is 1.239 ms .
Can't get 60fps on opacity transition in Chrome
I'd like a 60fps or better opacity transition and am testing with Chrome dev tools timeline. I've created a jsfiddle (http://jsfiddle.net/jnoody/Zt8nd/) to demonstrate, but basically it's just a div that has a class toggled every few seconds and transitions on opacity for the two states. It looks fine to the eye, but I've been led to believe 60fps should be achievable. HTML: <div id="fader"></div> CSS: #fader { height: 1000px; width: 1000px; background-color: grey; opacity: 1; transition: 1s opacity; } #fader.fadeOut { opacity: 0; transition: 1s opacity; } JavaScript: var fader = document.getElementById('fader'); setInterval(function () { fader.classList.toggle('fadeOut'); }, 2000); I've tried the null transform hack, too, but either way it appears to be in its own layer (using "render composited border layers").
Not really sure if that helps, but I do get 60fps in the fiddle, going full window (that is appending /show to the fiddle) There is only one moment where the frame rate drops, but I believe it's when the javascript executes (so, nothing to do with posible GPU acceleration)
css3 transition animation on load?
Is it possible to use CSS3 transition animation on page load without using Javascript? This is kind of what I want, but on page load: image-slider.html What I found so far CSS3 transition-delay, a way to delay effects on elements. Only works on hover. CSS3 Keyframe, works on load but are extremly slow. Not useful because of that. CSS3 transition is fast enough but don't animate on page load.
You can run a CSS animation on page load without using any JavaScript; you just have to use CSS3 Keyframes. Let's Look at an Example... Here's a demonstration of a navigation menu sliding into place using CSS3 only: #keyframes slideInFromLeft { 0% { transform: translateX(-100%); } 100% { transform: translateX(0); } } header { /* This section calls the slideInFromLeft animation we defined above */ animation: 1s ease-out 0s 1 slideInFromLeft; background: #333; padding: 30px; } /* Added for aesthetics */ body {margin: 0;font-family: "Segoe UI", Arial, Helvetica, Sans Serif;} a {text-decoration: none; display: inline-block; margin-right: 10px; color:#fff;} <header> Home About Products Contact </header> Break it down... The important parts here are the keyframe animation which we call slideInFromLeft... #keyframes slideInFromLeft { 0% { transform: translateX(-100%); } 100% { transform: translateX(0); } } ...which basically says "at the start, the header will be off the left hand edge of the screen by its full width and at the end will be in place". The second part is calling that slideInFromLeft animation: animation: 1s ease-out 0s 1 slideInFromLeft; Above is the shorthand version but here is the verbose version for clarity: animation-duration: 1s; /* the duration of the animation */ animation-timing-function: ease-out; /* how the animation will behave */ animation-delay: 0s; /* how long to delay the animation from starting */ animation-iteration-count: 1; /* how many times the animation will play */ animation-name: slideInFromLeft; /* the name of the animation we defined above */ You can do all sorts of interesting things, like sliding in content, or drawing attention to areas. Here's what W3C has to say.
Very little Javascript is necessary: window.onload = function() { document.body.className += " loaded"; } Now the CSS: .fadein { opacity: 0; -moz-transition: opacity 1.5s; -webkit-transition: opacity 1.5s; -o-transition: opacity 1.5s; transition: opacity 1.5s; } body.loaded .fadein { opacity: 1; } I know the question said "without Javascript", but I think it's worth pointing out that there is an easy solution involving one line of Javascript. It could even be inline Javascript, something like that: <body onload="document.body.className += ' loaded';" class="fadein"> That's all the JavaScript that's needed.
I think I have found a sort of work around for the OP question - instead of a transition beginning 'on.load' of the page - I found that using an animation for an opacity fade in had the same effect, (I was looking for the same thing as OP). So I wanted to have the body text fade in from white(same as site background) to black text colour on page load - and I've only been coding since Monday so I was looking for an 'on.load' style thing code, but don't know JS yet - so here is my code that worked well for me. #main p { animation: fadein 2s; } #keyframes fadein { from { opacity: 0} to { opacity: 1} } And for whatever reason, this doesn't work for .class only #id's(at least not on mine) Hope this helps - as I know this site helps me a lot!
CSS only with a delay of 3s a few points to take here: multiple animations in one call we create a wait animation that just delays the actual one (the second one in our case). Code: header { animation: 3s ease-out 0s 1 wait, 0.21s ease-out 3s 1 slideInFromBottom; } #keyframes wait { from { transform: translateY(20px); } to { transform: translateY(20px); } } #keyframes slideInFromBottom { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
Well, this is a tricky one. The answer is "not really". CSS isn't a functional layer. It doesn't have any awareness of what happens or when. It's used simply to add a presentational layer to different "flags" (classes, ids, states). By default, CSS/DOM does not provide any kind of "on load" state for CSS to use. If you wanted/were able to use JavaScript, you'd allocate a class to body or something to activate some CSS. That being said, you can create a hack for that. I'll give an example here, but it may or may not be applicable to your situation. We're operating on the assumption that "close" is "good enough": <html> <head> <!-- Reference your CSS here... --> </head> <body> <!-- A whole bunch of HTML here... --> <div class="onLoad">OMG, I've loaded !</div> </body> </html> Here's an excerpt of our CSS stylesheet: .onLoad { -webkit-animation:bounceIn 2s; } We're also on the assumption that modern browsers render progressively, so our last element will render last, and so this CSS will be activated last.
add this to your css for fade in animation body{animation: 2s ease-out 0s 1 FadeIn;} #keyframes FadeIn { 0% { opacity:0; } 100% { opacity:1; } } increase the ease-out time if you want it to load slower
Even simplier solution (still with [one line inline] javascript): Use this as the body tag: Note that body. or this. did not work for me. Only the long ; querySelector allow the use of classList.remove (Linux Chromium) <body class="onload" onload="document.querySelector('body').classList.remove('onload')"> and add this line on top of your other css rules. body.onload *{ transform: none !important; } Take note that this can apply to opacity (as requested by OP [other posters] ) simply by using opacity as a transition trigger instead. (might even work on any other css ruling in the same fashion and you can use multiple class for explicity delay between triggering) The logic is the same. Enforce no transform (with :none !importanton all child element of body.onloadand once the document is loaded remove the class to trigger all transition on all elements as specified in your css. FIRST ANSWER BELOW (SEE EDIT ABOVE FOR SHORTER ANSWER) Here is a reverse solution: Make your html layout and set the css accordingly to your final result (with all the transformation you want). Set the transition property to your liking add a class (eg: waitload) to the elements you want to transform AFTER load. The CSS keyword !important is the key word here. Once the document is loaded, use JS to remove the class from the elements to to start transformation (and remove the transition: none override). Works with multiple transition on multiple elements. Did not try cross-browser compatibility. div { width: fit-content; } #rotated { transform: rotate(-50deg)/* any other transformation */ ; transition: 6s; } #translated { transform: translate(90px)/* any other transformation */ ; transition: 6s; } .waitload { transform: none !important; } <div id='rotated' class='waitload'> rotate after load </div> <div id='translated' class='waitload'> trasnlate after load </div> <script type="text/javascript"> document.addEventListener('DOMContentLoaded', init); function init() { [...document.querySelectorAll('.waitload')] .map(e => e.classList.remove('waitload')); } </script>
Similar to #Rolf's solution, but skip reference to external functions or playing with class. If opacity is to remain fixed to 1 once loaded, simply use inline script to directly change opacity via style. For example <body class="fadein" onload="this.style.opacity=1"> where CSS sytle "fadein" is defined per #Rolf,defining transition and setting opacity to initial state (i.e. 0) the only catch is that this does not work with SPAN or DIV elements, since they do not have working onload event
start it with hover of body than It will start when the mouse first moves on the screen, which is mostly within a second after arrival, the problem here is that it will reverse when out of the screen. html:hover #animateelementid, body:hover #animateelementid {rotate ....} thats the best thing I can think of: http://jsfiddle.net/faVLX/ fullscreen: http://jsfiddle.net/faVLX/embedded/result/ Edit see comments below: This will not work on any touchscreen device because there is no hover, so the user won't see the content unless they tap it. – Rich Bradshaw
Ok I have managed to achieve an animation when the page loads using only css transitions (sort of!): I have created 2 css style sheets: the first is how I want the html styled before the animation... and the second is how I want the page to look after the animation has been carried out. I don't fully understand how I have accomplished this but it only works when the two css files (both in the head of my document) are separated by some javascript as follows. I have tested this with Firefox, safari and opera. Sometimes the animation works, sometimes it skips straight to the second css file and sometimes the page appears to be loading but nothing is displayed (perhaps it is just me?) <link media="screen,projection" type="text/css" href="first-css-file.css" rel="stylesheet" /> <script language="javascript" type="text/javascript" src="../js/jQuery JavaScript Library v1.3.2.js"></script> <script type='text/javascript'> $(document).ready(function(){ // iOS Hover Event Class Fix if((navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i)) || (navigator.userAgent.match(/iPad/i))) { $(".container .menu-text").click(function(){ // Update class to point at the head of the list }); } }); </script> <link media="screen,projection" type="text/css" href="second-css-file.css" rel="stylesheet" /> Here is a link to my work-in-progress website: http://www.hankins-design.co.uk/beta2/test/index.html Maybe I'm wrong but I thought browsers that do not support css transitions should not have any issues as they should skip straight to the second css file without delay or duration. I am interested to know views on how search engine friendly this method is. With my black hat on I suppose I could fill a page with keywords and apply a 9999s delay on its opacity. I would be interested to know how search engines deal with the transition-delay attribute and whether, using the method above, they would even see the links and information on the page. More importantly I would really like to know why this is not consistent each time the page loads and how I can rectify this! I hope this can generate some views and opinions if nothing else!
If anyone else had problems doing two transitions at once, here's what I did. I needed text to come from top to bottom on page load. HTML <body class="existing-class-name" onload="document.body.classList.add('loaded')"> HTML <div class="image-wrapper"> <img src="db-image.jpg" alt="db-image-name"> <span class="text-over-image">DB text</span> </div> CSS .text-over-image { position: absolute; background-color: rgba(110, 186, 115, 0.8); color: #eee; left: 0; width: 100%; padding: 10px; opacity: 0; bottom: 100%; -webkit-transition: opacity 2s, bottom 2s; -moz-transition: opacity 2s, bottom 2s; -o-transition: opacity 2s, bottom 2s; transition: opacity 2s, bottom 2s; } body.loaded .text-over-image { bottom: 0; opacity: 1; } Don't know why I kept trying to use 2 transition declarations in 1 selector and (not really) thinking it would use both.
You could use custom css classes (className) instead of the css tag too. No need for an external package. import React, { useState, useEffect } from 'react'; import { css } from '#emotion/css' const Hello = (props) => { const [loaded, setLoaded] = useState(false); useEffect(() => { // For load setTimeout(function () { setLoaded(true); }, 50); // Browser needs some time to change to unload state/style // For unload return () => { setLoaded(false); }; }, [props.someTrigger]); // Set your trigger return ( <div css={[ css` opacity: 0; transition: opacity 0s; `, loaded && css` transition: opacity 2s; opacity: 1; `, ]} > hello </div> ); };
Not really, as CSS is applied as soon as possible, but the elements might not be drawn yet. You could guess a delay of 1 or 2 seconds, but this won't look right for most people, depending on the speed of their internet. In addition, if you want to fade something in for instance, it would require CSS that hides the content to be delivered. If the user doesn't have CSS3 transitions then they would never see it. I'd recommend using jQuery (for ease of use + you may wish to add animation for other UAs) and some JS like this: $(document).ready(function() { $('#id_to_fade_in') .css({"opacity":0}) // Set to 0 as soon as possible – may result in flicker, but it's not hidden for users with no JS (Googlebot for instance!) .delay(200) // Wait for a bit so the user notices it fade in .css({"opacity":1}); // Fade it back in. Swap css for animate in legacy browsers if required. }); Along with the transitions added in the CSS. This has the advantage of easily allowing the use of animate instead of the second CSS in legacy browsers if required.