My application generates animations dynamically in server code. For the element to be animated, I apply the animation styles in-line, like so (the element IDs are GUIDs with a letter prefix to prevent collision):
<div class="ScrollingDiv" style="width: 100%; height: 27px;">
<p id="p9a6960428d594935b2540b1f8466f47a" style="animation:scroll-p9a6960428d594935b2540b1f8466f47a 10s linear infinite; width: 131px; height: 27px; transform: translateX(640px); -moz-transform: translateX(640px); -webkit-transform: translateX(640px); -moz-animation: scroll-p9a6960428d594935b2540b1f8466f47a 10s linear infinite; -webkit-animation: scroll-p9a6960428d594935b2540b1f8466f47a 10s linear infinite;">
This is a test
</p>
</div>
and assign that as the InnerHtml of the container. I also generate on the server side the keyframes, like so:
#keyframes scroll-p9a6960428d594935b2540b1f8466f47a { 0% { transform: translateX(640px); } 100% { transform: translateX(-131px); } }
and put them in a hidden field on the form for the client to add to the style sheet using Eli Grey's approach in this post.
function pageLoad(sender, args) {
var oStyleSheet = document.styleSheets[0];
oStyleSheet.insertRule(rule, oStyleSheet.cssRules.length);
}
I've verified that the style and rules are working in this Fiddle but it's not working when I add them programmatically. I can watch in the debugger that oStyleSheet is getting a new entry in its cssRules property. Any ideas as to either a) why it's not working or b) (better yet) how I can debug this myself?
I didn't read all the way to the bottom of the answer I cited. Turns out that you have to stop then restart the animation for changes to the style sheet to take effect.
Related
As others have pointed out, CSS animations might get stuck or pause inadvertently because of performance issues, for example a busy JavaScript main thread, like CSS Animation, State change finish animation.
In the context of a webpage using existing third-party libraries or frameworks, we might have no control over the whole web app, so we cannot guarantee that the JavaScript behaves properly.
As there seems to be no way to increase an animation's priority over other browser tasks, and there seems to be no way to decrease the priority of browser tasks initiated by JavaScript so that CSS-initiated tasks are preferred either, and that may have unintended consequences as well, I want to focus on controlling the animation itself.
So, my questions are:
Is there a way to tell the browser, preferably using only CSS, that the animation should rather drop some frames to guarantee to reach the final state in time even if there are performance problems?
If so, can we use CSS animation syntax only, or do we need to use other techniques such as requestAnimationFrame() or complex libraries like GSAP?
Perhaps, there is something like a combination of animation-fill-mode and text-rendering: optimizeSpeed; but to control what to optimize when rendering animations, but I have searched and have not found anything helpful.
What I have tried so far:
.drawer {
position: fixed;
left: 100%;
transition: transform 3s;
background: blue;
}
.drawer.open {
transform: translateX(-400px);
animation-name: slidein;
animation-duration: 3s;
animation-fill-mode: forwards;
}
#keyframes slidein {
0% { transform: none; }
25% { transform: translateX(-100px); }
50% { transform: translateX(-200px); }
75% { transform: translateX(-300px); }
100%{ transform: translateX(-400px); }
}
<div class="drawer" id="drawer">drawer</div>
show drawer
Although, this is supposed to be a minimal reproducible example, the bug is hard to reproduce when taken out of context. Please try to use CPU throttling in developer tools to see what I mean.
.drawer {
position: fixed;
left: 100%;
transition: transform 3s;
background: blue;
}
.drawer.open {
transform: translateX(-400px);
animation-name: slidein;
animation-duration: 3s;
}
#keyframes slidein {
0% { transform: none; }
25% { transform: translateX(-100px); }
50% { transform: translateX(-200px); }
75% { transform: translateX(-300px); }
100% { transform: translateX(-400px); }
}
<div>
<div class="drawer open" id="drawer">drawer</div>
show drawer
</div>
I am building a subtitle editor that has customisation tools for toggling animations that can scale and move text. Each animation is atomic and has a CSS keyframe. Example of two animations:
#keyframes upward {
from {
transform: translateY(0px);
}
to {
transform: translateY(-30px);
}
}
#keyframes stretch {
from {
transform: scaleY(1);
}
to {
transform: scaleY(1.1);
}
}
Each subtitle uses a specific class, which has the above animations (this can be seen in the code below). Each animation has a checkbox in HTML, whose value JavaScript uses to toggle the animation-play-state property through a custom property (e.g. --happy-animation-stretch-state), which causes the animation to either pause or run.
.happy {
display: inline-block;
color: var(--happy-colour);
animation: upward var(--animation-duration), stretch var(--animation-duration);
animation-play-state: var(--happy-animation-upward-state), var(--happy-animation-stretch-state);
transition: 0.3s;
}
The problem is that only one of the animations works. I am not sure what is wrong?
EDIT: I managed to solve this by enwrapping the element I was trying to transform in multiple divs - one for each animation. Here is the original solution.
Can someone tell me anything about gate animation and zoom page transition from this Unicef web, I want to try to make this cool animation. At least give me "keyword" how to find it. Are those made with html5 ?
In the Unicef animation the developers are using a mix approach of JavaScript using GSAP JS library and CSS Transitions.
You can have a looks at their code in bundle.js and screen.css files using Chrome developer tools.
Generally you can use:
CSS Keyframe Animation
CSS Transitions
JavaScript vanilla or some libraries
Web Animation API
to animate DOM elements in your HTML page.
To help you to get started I have created a simple scale/zoom effect using CSS Keyframe Animation, but you can reach a similar effect using JavaScript libraries as jQuery, GSAP, Velocity or others.
For more complex animations I would suggest to use a specialized JS library as GSAP, if instead you need more simple, eyes catching animations you could consider also using some pre-made effects:
animate.css (CSS Keyframe Animation)
animatelo.js (Web Animation API) - disclaim I have created this library :)
It really depends of the complexity of you animation and your skill set.
#mario {
background: url(http://vignette1.wikia.nocookie.net/the-new-super-mario-bros/images/7/7e/200px-Mario_Nintendo.png/revision/latest?cb=20140505185215);
background-repeat: no-repeat;
width: 375px;
height: 375px;
-webkit-transform-origin: 0 0;
-ms-transform-origin: 0 0;
transform-origin: 0 0;
-webkit-animation: leaves 5s ease-in-out infinite alternate;
animation: marioAnim 5s ease-in-out infinite alternate;
}
#-webkit-keyframes marioAnim {
0% {
-webkit-transform: scale(1.0);
}
100% {
-webkit-transform: scale(2.0);
}
}
#keyframes leaves {
0% {
transform: scale(1.0);
}
100% {
transform: scale(2.0);
}
}
<div id="mario"></div>
What I am trying to do is depending on a variable I get, change the 100% rotate value in the keyframe to the new calculated value. I have no problem with using Javascript to do this, but I want it to be done in the External CSS, not inline, once changed I need to restart the animation for that time. Is this possible? If so, how? (NOTE ALL DONE CURRENTLY THROUGH BUTTON CLICK) this is not to be saved, only done to update the graphic with a new position.
.arrow {
-webkit-animation: rotate 3s linear 0 1;
animation: rotate 3s linear 0 1;
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
-webkit-animation-play-state: paused;
animation-play-state: paused;
visibility: visible !important;
}
#-webkit-keyframes rotate {
0% {
-webkit-transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
}
}
#keyframes rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
Any help will be much appreciated! I have been trying to find something that would work for about a week now.
It is possible to change keyframes on loaded stylesheets. Here you have a stack overflow answer from 2011. And here's a link to a recent blog post about it.
So, as adeneo mentioned, it is not possible to make javascript change an external style sheet.
The thing you can do is make 2 css classes and use javascript to change the class. This way you are not using inline styles.
Also, because you are changing the class, the animation will begin from the start - as you want it.
Dearest stackoverflowers,
I'm new to Angular JS and have read some stuff on how to animate the Angular way, still I'm very much confused on how to correctly implement it and what classes get added when and where. I feel like I had much more control over my animations with traditional jQuery (adding and removing classes). But maybe this is just because I'm used to it that way.
On pageload I want certain elements to animate in. So in my controller, on pageload, a variable (pageLoaded) gets set to true. And my surrounding content-wrapping div will have ng-show="pageLoaded".
This way I have successfully added an animation on the entire page using following CSS transitions/animations:
.page.ng-hide-add, .page.ng-hide-remove {
display:block!important;
}
.popup.ng-hide-add {
-webkit-animation: 450ms bounceInRight reverse;
}
.popup.ng-hide-remove {
-webkit-transform: translateX(100%);
-webkit-animation: 750ms bounceInRight;
}
But once I try to address child elements, the animations fail.
.page.ng-hide-add .child, .page.ng-hide-remove .child {
display:block!important;
}
.popup.ng-hide-add .child {
-webkit-animation: 450ms bounceInRight reverse;
}
.popup.ng-hide-remove .child {
-webkit-transform: translateX(100%);
-webkit-animation: 750ms bounceInRight;
}
Is this not supported by Angular? Or am I doing something wrong?
And if I understand correctly, no matter if you're using ng-hide, or ng-show..
the ng-hide classes should be used? Where they follow following logic:
ng-hide-remove/ng-hide-remove-active show the element
ng-hide-add/ng-hide-add-active hide the element
Can someone explain the difference between the regular and the active classes? How should they be used?
It seems that Angular scans the document for things to animate, I have found that when wanting to animate a child element. You have to set a transition on the parent for as long as you want the children to transition.
For example.
.page.ng-hide-add, .page.ng-hide-remove {
-webkit-transition: 1000ms;
}
.page.ng-hide-add .child, .page.ng-hide-remove .child {
display:block!important;
}
.popup.ng-hide-add .child h1 {
-webkit-animation: 450ms bounceInRight;
}
.popup.ng-hide-add .child h2 {
-webkit-animation: 750ms bounceInRight 250ms;
}
Angular will only add the 'animation' classes, if the HTML element with the NG-IF/NG-SHOW or ng-whatever element has a transition in the CSS specified for it.