├── LICENSE
├── README.md
├── cssanimevent.js
├── cssanimevent.min.js
└── example
├── index.css
├── index.html
├── index.js
└── index.scss
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2013 Peter Mescalchin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CSS animation event
2 |
3 | A very small (approx **800 bytes** minified and gzipped) cross browser compatible library to handle CSS3 animation and transition DOM events with a fall back pattern for unsupported browsers.
4 |
5 | Tested successfully with CSS animation/transition supported browsers of:
6 |
7 | - Google Chrome
8 | - Mozilla Firefox
9 | - Opera (12.10+)
10 | - IE10+
11 |
12 | Library supports Internet Explorer IE9 and above, a final version with IE8 support is [tagged here](https://github.com/magnetikonline/css-animation-event/tree/ie8-final).
13 |
14 | - [Why?](#why)
15 | - [Usage](#usage)
16 | - [Example](#example)
17 | - [Methods](#methods)
18 | - [onAnimationEnd(element,handler[,data])](#onanimationendelementhandlerdata)
19 | - [cancelAnimationEnd(element)](#cancelanimationendelement)
20 | - [onTransitionEnd(element,handler[,data])](#ontransitionendelementhandlerdata)
21 | - [cancelTransitionEnd(element)](#canceltransitionendelement)
22 | - [animationSupport()](#animationsupport)
23 | - [transitionSupport()](#transitionsupport)
24 | - [addAnimation{Start|Iteration|End}(element,handler)](#addanimationstartiterationendelementhandler)
25 | - [removeAnimation{Start|Iteration|End}(element,handler)](#removeanimationstartiterationendelementhandler)
26 | - [addTransitionEnd(element,handler)](#addtransitionendelementhandler)
27 | - [removeTransitionEnd(element,handler)](#removetransitionendelementhandler)
28 |
29 | ## Why?
30 |
31 | The CSS3 [animation](https://www.w3.org/TR/css3-animations/) and [transition](https://www.w3.org/TR/css3-transitions/) modules both provide useful DOM events which can be used to track the current state of an animation or transition - extremely useful for chaining future application logic as they progress and complete.
32 |
33 | Whilst support for these events is (thankfully) provided in virtually every browser that offers CSS [animations](https://caniuse.com/#feat=css-animation) and [transitions](https://caniuse.com/#feat=css-transitions), as a front-end developer you are still left with the issue of coding alternative program flows where support isn't available and therefore won't fire your animation/transition event handlers.
34 |
35 | Consider the following example:
36 |
37 | ```css
38 | #movethis {
39 | /* leaving out browser prefixes for brevity */
40 | height: 100px;
41 | transition: height 1.5s ease-in;
42 | }
43 |
44 | #movethis.nowmove {
45 | height: 300px;
46 | }
47 | ```
48 |
49 | ```js
50 | // determineCSSTransitionSupport() would determine if browser supports CSS transitions
51 | var supportCSSTransitions = determineCSSTransitionSupport();
52 |
53 | // move our element
54 | var moveThisEl = document.getElementById('movethis');
55 | moveThisEl.className += ' nowmove';
56 |
57 | // code around no transition support
58 | if (supportCSSTransitions) {
59 | moveThisEl.addEventListener('transitionend',nextUIStep,false);
60 | } else {
61 | nextUIStep();
62 | }
63 |
64 | function nextUIStep() {
65 | // the transition ended, keep going
66 | }
67 | ```
68 |
69 | Having to continually make the decision to utilise DOM animation/transition events vs. a graceful fallback (via `supportCSSTransitions` in example above) throughout your UI code soon becomes clumsy and error prone.
70 |
71 | ## Usage
72 |
73 | [CSSAnimEvent](cssanimevent.js) manages the above situation in a different way, relying on the fact that CSS transitions by design fall back gracefully with unsupported browsers handling element CSS property changes as instant, with a zero transition time.
74 |
75 | Methods `onAnimationEnd(element,handler)` and `onTransitionEnd(element,handler)` simply mimic this behaviour by instantaneously calling the given `handler` for browsers that don't provide animation and/or transition support.
76 |
77 | Rewriting the above JavaScript example we can now do:
78 |
79 | ```js
80 | // move our element
81 | var moveThisEl = document.getElementById('movethis');
82 | moveThisEl.className += ' nowmove';
83 |
84 | // browsers supporting CSS transitions will call nextUIStep() after the transition ends
85 | // ...otherwise it will be called as window.setTimeout(nextUIStep)
86 | CSSAnimEvent.onTransitionEnd(moveThisEl,nextUIStep);
87 |
88 | function nextUIStep() {
89 | // the transition ended, keep going
90 | }
91 | ```
92 |
93 | One caveat to be aware of, both `onAnimationEnd()` and `onTransitionEnd()` create 'one shot' event handlers and should be called *just after* CSS updates have been applied to the element, allowing instant delegation back to the given callback handler for unsupported browsers.
94 |
95 | Internally `CSSAnimEvent` attaches singular `animationend` and `transitionend` event handlers to the `
` element and delegates to given callbacks as required.
96 |
97 | Using CSS `animation/@keyframes` is *slightly* more work since animated elements will never reach their intended keyframe target within unsupported browsers, but a little CSS/JavaScript can handle this situation:
98 |
99 | ```css
100 | @keyframes myanimation {
101 | /* prior animation steps in here */
102 |
103 | 100% {
104 | background: #f00;
105 | height: 300px;
106 | }
107 | }
108 |
109 | #movethis {
110 | height: 100px;
111 | }
112 |
113 | #movethis.nowmove {
114 | animation: myanimation 1s linear 1 forwards;
115 | }
116 |
117 | #movethis.finish {
118 | /* faux the target of myanimation for older browsers */
119 | background: #f00;
120 | height: 300px;
121 | }
122 | ```
123 |
124 | ```js
125 | // move our element
126 | var moveThisEl = document.getElementById('movethis');
127 | moveThisEl.className += ' nowmove';
128 |
129 | CSSAnimEvent.onAnimationEnd(moveThisEl,nextUIStep);
130 |
131 | function nextUIStep(el) {
132 | // faux the animation target, by adding 'finish' class to element
133 | el.className += ' finish';
134 |
135 | // keep going
136 | }
137 | ```
138 |
139 | ## Example
140 |
141 | View a very [basic example of this in action](https://magnetikonline.github.io/css-animation-event/) using animation and transition chaining.
142 |
143 | For capable browsers the tweens will run as expected - alternatively the DOM elements will update instantly from start to finish, via the same event handler execution flow.
144 |
145 | As a small bonus, `CSSAnimEvent` also adds a handy CSS styling hook; `cssanimactive`, which can be used for specific styling which is applied *only* during the animation/transition period.
146 |
147 | ```html
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 | ```
157 |
158 | The [example](https://magnetikonline.github.io/css-animation-event/) uses this CSS styling hook to provide a red border to each box during it's animation/transition period.
159 |
160 | ## Methods
161 |
162 | All methods are under a `window.CSSAnimEvent` namespace.
163 |
164 | ### `onAnimationEnd(element,handler[,data])`
165 |
166 | - Adds a 'one shot' event handler to the given DOM `element`, with `handler` executing either upon `animationend` or instantaneously if CSS animation support not detected.
167 | - The `handler` will be passed `element` that fired the event and an optional `data` payload as a second parameter.
168 | - The given DOM element will be decorated with a CSS class `cssanimactive`, removed upon animation completion which can be used as a CSS styling hook.
169 |
170 | ### `cancelAnimationEnd(element)`
171 |
172 | Cancel a 'one shot' event handler set by `onAnimationEnd()` on the given DOM `element`.
173 |
174 | ### `onTransitionEnd(element,handler[,data])`
175 |
176 | - Adds a 'one shot' event handler to the given DOM `element`, with `handler` executing either upon `transitionend` or instantaneously if CSS transition support not detected.
177 | - The `handler` will be passed `element` that fired the event and an optional `data` payload as a second parameter.
178 | - The given DOM element will be decorated with a CSS class `cssanimactive`, removed upon transition completion which can be used as a CSS styling hook.
179 |
180 | ### `cancelTransitionEnd(element)`
181 |
182 | Cancel a 'one shot' event handler set by `onTransitionEnd()` on the given DOM `element`.
183 |
184 | ### `animationSupport()`
185 |
186 | Returns `true` if CSS animation support is detected.
187 |
188 | ### `transitionSupport()`
189 |
190 | Returns `true` if CSS transition support is detected.
191 |
192 | ### `addAnimation{Start|Iteration|End}(element,handler)`
193 |
194 | - Add `animation{start|iteration|end}` native event handlers to DOM elements.
195 | - Provides a handy cross browser wrapper having done browser detection for you. Does **not** provide faux event firing for non-supported browsers.
196 | - Returns `true` where supported, `false` otherwise.
197 |
198 | ### `removeAnimation{Start|Iteration|End}(element,handler)`
199 |
200 | - Remove `animation{start|iteration|end}` native event handlers for above.
201 | - Returns `true` where supported, otherwise `false`.
202 |
203 | ### `addTransitionEnd(element,handler)`
204 |
205 | - Add `transitionend` native event handlers to DOM elements.
206 | - Provides a handy cross browser wrapper having done browser detection for you. Does **not** provide faux event firing for non-supported browsers.
207 | - Returns `true` on success/support, `false` otherwise.
208 |
209 | ### `removeTransitionEnd(element,handler)`
210 |
211 | - Remove `transitionend` native event handlers for above.
212 | - Returns `true` where supported, otherwise `false`.
213 |
--------------------------------------------------------------------------------
/cssanimevent.js:
--------------------------------------------------------------------------------
1 | (function(win,documentElement,undefined) {
2 |
3 | 'use strict';
4 |
5 | var ELEMENT_HANDLER_ID_ATTRIBUTE = 'picohCSSAnimID',
6 | CLASS_NAME_ANIM_ACTIVE = 'cssanimactive',
7 | HANDLER_TYPE_INDEX_ANIMATION = 0,
8 | HANDLER_TYPE_INDEX_TRANSITION = 1,
9 | HANDLER_ID_LENGTH = 3,
10 | HANDLER_ID_START_CHAR = 97, // character 'a'
11 | HANDLER_ID_END_CHAR = 122, // character 'z'
12 | isDetected,
13 | animationEventTypeStart,
14 | animationEventTypeIteration,
15 | animationEventTypeEnd,
16 | transitionEventTypeEnd,
17 | handlerCollection = [undefined,undefined];
18 |
19 | function detectCapabilities() {
20 |
21 | // if already detected support then exit
22 | if (isDetected) {
23 | return;
24 | }
25 |
26 | isDetected = true;
27 |
28 | // list of animation/transition style properties per browser engine and matching event names
29 | // note: non-prefixed properties are intentionally checked first
30 | var ANIMATION_DETECT_COLLECTION = {
31 | animation: ['animationstart','animationiteration','animationend'],
32 | webkitAnimation: ['webkitAnimationStart','webkitAnimationIteration','webkitAnimationEnd']
33 | },
34 | TRANSITION_DETECT_COLLECTION = {
35 | transition: 'transitionend',
36 | webkitTransition: 'webkitTransitionEnd'
37 | };
38 |
39 | function detectEventType(detectCollection) {
40 |
41 | var styleNameList = Object.keys(detectCollection);
42 |
43 | while (styleNameList.length) {
44 | var styleNameItem = styleNameList.shift()
45 | if (documentElement.style[styleNameItem] !== undefined) {
46 | // found capability
47 | return detectCollection[styleNameItem];
48 | }
49 | }
50 |
51 | // no match
52 | }
53 |
54 | // determine if animation and transition support available
55 | animationEventTypeEnd = detectEventType(ANIMATION_DETECT_COLLECTION);
56 | if (animationEventTypeEnd) {
57 | // animation support detected - split out event types from collection
58 | animationEventTypeStart = animationEventTypeEnd[0];
59 | animationEventTypeIteration = animationEventTypeEnd[1];
60 | animationEventTypeEnd = animationEventTypeEnd[2];
61 | }
62 |
63 | transitionEventTypeEnd = detectEventType(TRANSITION_DETECT_COLLECTION);
64 | }
65 |
66 | function eventAdd(obj,type,handler) {
67 |
68 | obj.addEventListener(type,handler,false);
69 | return true;
70 | }
71 |
72 | function eventRemove(obj,type,handler) {
73 |
74 | obj.removeEventListener(type,handler,false);
75 | return true;
76 | }
77 |
78 | function getElHandlerCollectionID(handlerTypeIndex,el) {
79 |
80 | // look for ID as a custom property of the DOM element
81 | var handlerID = el[ELEMENT_HANDLER_ID_ATTRIBUTE];
82 |
83 | return (
84 | (handlerID !== undefined) &&
85 | (handlerCollection[handlerTypeIndex][handlerID] !== undefined)
86 | )
87 | // found handler ID in collection
88 | ? handlerID
89 | // not found
90 | : false;
91 | }
92 |
93 | function removeElHandlerItem(handlerTypeIndex,el,handlerID) {
94 |
95 | // if handlerID already given, no need to find again for element
96 | handlerID = handlerID || getElHandlerCollectionID(handlerTypeIndex,el);
97 |
98 | if (handlerID !== false) {
99 | // found element in collection, now remove
100 | delete handlerCollection[handlerTypeIndex][handlerID];
101 | delete el[ELEMENT_HANDLER_ID_ATTRIBUTE];
102 |
103 | el.className = (
104 | (' ' + el.className + ' ').
105 | replace(' ' + CLASS_NAME_ANIM_ACTIVE + ' ',' ')
106 | ).trim();
107 | }
108 | }
109 |
110 | function onEndProcess(eventTypeEnd,handlerTypeIndex,el,handler,data) {
111 |
112 | if (!eventTypeEnd) {
113 | // no animation/transition support - call handler right away
114 | return setTimeout(function() { handler(el,data); });
115 | }
116 |
117 | if (!handlerCollection[handlerTypeIndex]) {
118 | // setup end handler
119 | handlerCollection[handlerTypeIndex] = {};
120 | eventAdd(documentElement,eventTypeEnd,function(event) {
121 |
122 | // ensure event returned a target element
123 | if (event.target) {
124 | // get the element handler list ID - skip over if not found
125 | var targetEl = event.target,
126 | handlerID = getElHandlerCollectionID(handlerTypeIndex,targetEl);
127 |
128 | if (handlerID !== false) {
129 | // execute handler then remove from handler list
130 | var handlerItem = handlerCollection[handlerTypeIndex][handlerID];
131 | removeElHandlerItem(handlerTypeIndex,targetEl,handlerID);
132 | handlerItem[0](targetEl,handlerItem[1]);
133 | }
134 | }
135 | });
136 | }
137 |
138 | // remove possible existing end handler associated to element
139 | removeElHandlerItem(handlerTypeIndex,el);
140 |
141 | // generate new, unique handler ID
142 | var handlerID;
143 | while (!handlerID || handlerCollection[handlerTypeIndex][handlerID]) {
144 | handlerID = '';
145 | while (handlerID.length < HANDLER_ID_LENGTH) {
146 | // append characters between [a-z] to a total of HANDLER_ID_LENGTH
147 | handlerID += String.fromCharCode(
148 | Math.floor(Math.random() * (HANDLER_ID_END_CHAR - HANDLER_ID_START_CHAR)) +
149 | HANDLER_ID_START_CHAR
150 | );
151 | }
152 | }
153 |
154 | // add element to handler list and a 'animation active' class identifier to the target element
155 | el[ELEMENT_HANDLER_ID_ATTRIBUTE] = handlerID;
156 | handlerCollection[handlerTypeIndex][handlerID] = [handler,data];
157 | el.className = el.className.trim() + ' ' + CLASS_NAME_ANIM_ACTIVE;
158 | }
159 |
160 | win.CSSAnimEvent = {
161 | animationSupport: function() {
162 |
163 | detectCapabilities();
164 | return !!animationEventTypeEnd;
165 | },
166 |
167 | transitionSupport: function() {
168 |
169 | detectCapabilities();
170 | return !!transitionEventTypeEnd;
171 | },
172 |
173 | addAnimationStart: function(el,handler) {
174 |
175 | detectCapabilities();
176 |
177 | return (animationEventTypeStart)
178 | ? eventAdd(el,animationEventTypeStart,handler)
179 | : false;
180 | },
181 |
182 | removeAnimationStart: function(el,handler) {
183 |
184 | detectCapabilities();
185 |
186 | return (animationEventTypeStart)
187 | ? eventRemove(el,animationEventTypeStart,handler)
188 | : false;
189 | },
190 |
191 | addAnimationIteration: function(el,handler) {
192 |
193 | detectCapabilities();
194 |
195 | return (animationEventTypeIteration)
196 | ? eventAdd(el,animationEventTypeIteration,handler)
197 | : false;
198 | },
199 |
200 | removeAnimationIteration: function(el,handler) {
201 |
202 | detectCapabilities();
203 |
204 | return (animationEventTypeIteration)
205 | ? eventRemove(el,animationEventTypeIteration,handler)
206 | : false;
207 | },
208 |
209 | addAnimationEnd: function(el,handler) {
210 |
211 | detectCapabilities();
212 |
213 | return (animationEventTypeEnd)
214 | ? eventAdd(el,animationEventTypeEnd,handler)
215 | : false;
216 | },
217 |
218 | removeAnimationEnd: function(el,handler) {
219 |
220 | detectCapabilities();
221 |
222 | return (animationEventTypeEnd)
223 | ? eventRemove(el,animationEventTypeEnd,handler)
224 | : false;
225 | },
226 |
227 | addTransitionEnd: function(el,handler) {
228 |
229 | detectCapabilities();
230 |
231 | return (transitionEventTypeEnd)
232 | ? eventAdd(el,transitionEventTypeEnd,handler)
233 | : false;
234 | },
235 |
236 | removeTransitionEnd: function(el,handler) {
237 |
238 | detectCapabilities();
239 |
240 | return (transitionEventTypeEnd)
241 | ? eventRemove(el,transitionEventTypeEnd,handler)
242 | : false;
243 | },
244 |
245 | onAnimationEnd: function(el,handler,data) {
246 |
247 | detectCapabilities();
248 |
249 | onEndProcess(
250 | animationEventTypeEnd,
251 | HANDLER_TYPE_INDEX_ANIMATION,
252 | el,handler,data
253 | );
254 | },
255 |
256 | cancelAnimationEnd: function(el) {
257 |
258 | removeElHandlerItem(HANDLER_TYPE_INDEX_ANIMATION,el);
259 | },
260 |
261 | onTransitionEnd: function(el,handler,data) {
262 |
263 | detectCapabilities();
264 |
265 | onEndProcess(
266 | transitionEventTypeEnd,
267 | HANDLER_TYPE_INDEX_TRANSITION,
268 | el,handler,data
269 | );
270 | },
271 |
272 | cancelTransitionEnd: function(el) {
273 |
274 | removeElHandlerItem(HANDLER_TYPE_INDEX_TRANSITION,el);
275 | }
276 | };
277 | })(window,document.documentElement);
278 |
--------------------------------------------------------------------------------
/cssanimevent.min.js:
--------------------------------------------------------------------------------
1 | (function(v,q,h){function d(){function a(b){for(var a=Object.keys(b);a.length;){var d=a.shift();if(q.style[d]!==h)return b[d]}}if(!r){r=!0;if(f=a({animation:["animationstart","animationiteration","animationend"],webkitAnimation:["webkitAnimationStart","webkitAnimationIteration","webkitAnimationEnd"]}))k=f[0],l=f[1],f=f[2];e=a({transition:"transitionend",webkitTransition:"webkitTransitionEnd"})}}function m(a,b,c){a.addEventListener(b,c,!1);return!0}function n(a,b,c){a.removeEventListener(b,c,!1);return!0}
2 | function t(a,b){var c=b.picohCSSAnimID;return c!==h&&g[a][c]!==h?c:!1}function p(a,b,c){c=c||t(a,b);!1!==c&&(delete g[a][c],delete b.picohCSSAnimID,b.className=(" "+b.className+" ").replace(" cssanimactive "," ").trim())}function u(a,b,c,d,f){if(!a)return setTimeout(function(){d(c,f)});g[b]||(g[b]={},m(q,a,function(a){if(a.target){a=a.target;var c=t(b,a);if(!1!==c){var d=g[b][c];p(b,a,c);d[0](a,d[1])}}}));p(b,c);for(var e;!e||g[b][e];)for(e="";3>e.length;)e+=String.fromCharCode(Math.floor(25*Math.random())+
3 | 97);c.picohCSSAnimID=e;g[b][e]=[d,f];c.className=c.className.trim()+" cssanimactive"}var r,k,l,f,e,g=[h,h];v.CSSAnimEvent={animationSupport:function(){d();return!!f},transitionSupport:function(){d();return!!e},addAnimationStart:function(a,b){d();return k?m(a,k,b):!1},removeAnimationStart:function(a,b){d();return k?n(a,k,b):!1},addAnimationIteration:function(a,b){d();return l?m(a,l,b):!1},removeAnimationIteration:function(a,b){d();return l?n(a,l,b):!1},addAnimationEnd:function(a,b){d();return f?m(a,
4 | f,b):!1},removeAnimationEnd:function(a,b){d();return f?n(a,f,b):!1},addTransitionEnd:function(a,b){d();return e?m(a,e,b):!1},removeTransitionEnd:function(a,b){d();return e?n(a,e,b):!1},onAnimationEnd:function(a,b,c){d();u(f,0,a,b,c)},cancelAnimationEnd:function(a){p(0,a)},onTransitionEnd:function(a,b,c){d();u(e,1,a,b,c)},cancelTransitionEnd:function(a){p(1,a)}}})(window,document.documentElement);
5 |
--------------------------------------------------------------------------------
/example/index.css:
--------------------------------------------------------------------------------
1 | /* line 24, example.scss */
2 | input {
3 | font-size: 100%;
4 | margin: 0; }
5 |
6 | /* line 29, example.scss */
7 | body,
8 | input {
9 | color: #000;
10 | font-family: sans-serif; }
11 |
12 | /* line 35, example.scss */
13 | body {
14 | background: #fff;
15 | font-size: 62.5%;
16 | line-height: 1;
17 | margin-left: 20px;
18 | margin-right: 20px; }
19 |
20 | /* line 43, example.scss */
21 | h1 {
22 | font-size: 3em;
23 | margin: 0 0 20px;
24 | white-space: nowrap; }
25 |
26 | /* line 49, example.scss */
27 | p {
28 | margin: 0 0 15px; }
29 |
30 | /* line 53, example.scss */
31 | ul {
32 | margin: 0 0 15px 15px;
33 | padding: 0; }
34 |
35 | /* line 58, example.scss */
36 | p,
37 | ul > li {
38 | font-size: 1.3em;
39 | line-height: 1.4; }
40 | /* line 63, example.scss */
41 | p > code,
42 | ul > li > code {
43 | font-family: monospace;
44 | font-size: 100%; }
45 |
46 | /* line 69, example.scss */
47 | a {
48 | color: #555; }
49 |
50 | /* line 74, example.scss */
51 | .boxanimation,
52 | .boxtransition1,
53 | .boxtransition2 {
54 | border: 1px solid #000;
55 | height: 100px;
56 | left: 20px;
57 | position: absolute;
58 | top: 260px;
59 | width: 100px; }
60 | /* line 85, example.scss */
61 | .boxanimation.cssanimactive,
62 | .boxtransition1.cssanimactive,
63 | .boxtransition2.cssanimactive {
64 | border: 2px solid #f00; }
65 |
66 | /* line 91, example.scss */
67 | .boxanimation {
68 | background: #b2382d; }
69 | /* line 94, example.scss */
70 | .boxanimation.move {
71 | -webkit-animation: boxanimation 1s ease-in-out 0s 3 alternate forwards;
72 | animation: boxanimation 1s ease-in-out 0s 3 alternate forwards; }
73 | /* line 99, example.scss */
74 | .boxanimation.complete {
75 | background: #e89041;
76 | top: 500px; }
77 | @-webkit-keyframes boxanimation {
78 | 20% {
79 | left: 40px;
80 | top: 310px; }
81 | 40% {
82 | left: 140px;
83 | top: 400px; }
84 | 60% {
85 | background: #ffc787; }
86 | 100% {
87 | background: #e89041;
88 | top: 500px; } }
89 | @keyframes boxanimation {
90 | 20% {
91 | left: 40px;
92 | top: 310px; }
93 | 40% {
94 | left: 140px;
95 | top: 400px; }
96 | 60% {
97 | background: #ffc787; }
98 | 100% {
99 | background: #e89041;
100 | top: 500px; } }
101 | /* line 129, example.scss */
102 | .boxtransition1,
103 | .boxtransition2 {
104 | background: #f2df7e;
105 | left: 160px;
106 | -webkit-transition: background 0.5s linear, top 0.5s ease-in;
107 | transition: background 0.5s linear, top 0.5s ease-in; }
108 | /* line 135, example.scss */
109 | .boxtransition1.move,
110 | .boxtransition2.move {
111 | background: #314a59;
112 | top: 500px; }
113 |
114 | /* line 141, example.scss */
115 | .boxtransition2 {
116 | left: 300px; }
117 |
--------------------------------------------------------------------------------
/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | CSS animation event example
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
CSS animation event example
24 |
25 |
26 |
Upon start first box will start animating, followed by transitions of box two and three.
27 |
Box animations and transitions chained using CSSAnimEvent methods of onAnimationEnd() and onTransitionEnd().
28 |
For browsers not supporting CSS3 animations or transitions, faux end callbacks will be fired by cssanimevent.js.
29 |
Open browser developer console for further debug output.