JSFiddle - React, Tailwind, and code Playground

HTML

<div id="hoge"></div>
<br>
<div id="huga"></div>

CSS

div {
    width: 100px;
    height: 100px;
    background-color: blue;
}

#hoge:hover {
    background-color: red;
    -webkit-transition: 1s;
    -moz-transition: 1s;
    -ms-transition: 1s;
    -o-transition: 1s;
    transition: 1s;
}

#huga:hover {
    -webkit-animation-name: hugaHover;
    -moz-animation-name: hugaHover;
    -o-animation-name: hugaHover;
    animation-name: hugaHover;

    -webkit-animation-duration: 1s;
    -moz-animation-duration: 1s;
    -o-animation-duration: 1s;
    animation-duration: 1s;

    -webkit-animation-fill-mode: forwards;
    -moz-animation-fill-mode: forwards;
    -o-animation-fill-mode: forwards;
    animation-fill-mode: forwards;
}

@-webkit-keyframes hugaHover {
    from {
        background-color: blue;
    }
    to {
        background-color: red;
    } 
}

@-moz-keyframes hugaHover {
    from {
        background-color: blue;
    }
    to {
        background-color: red;
    } 
}

@-o-keyframes hugaHover {
    from {
        background-color: blue;
    }
    to {
        background-color: red;
    } 
}

@keyframes hugaHover {
    from {
        background-color: blue;
    }
    to {
        background-color: red;
    } 
}

JavaScript

var cssEvtWrap = CSSEventWrapper();

// transition
var hoge = document.getElementById('hoge');
var func = function(e){
    console.log(e.type);
	cssEvtWrap.onTransitionEnd.remove(hoge, func); 
    alert('transitionEvent removed');
}
cssEvtWrap.onTransitionEnd.add(hoge, func);

// animation
var huga = document.getElementById('huga');
var funcA = function(e){
    console.log(e.type);
	cssEvtWrap.onAnimationStart.remove(huga, funcA);
    cssEvtWrap.onAnimationEnd.add(huga, funcB);
}
var funcB = function(e){
	console.log(e.type);
    cssEvtWrap.onAnimationEnd.remove(huga, funcB);
    alert('animationEvent removed');
}
cssEvtWrap.onAnimationStart.add(huga, funcA);


/*
	_@ノ"
*/

function CSSEventWrapper(){
	
	// 使い回し
	var add = function(element, callback, useCapture){
		this.eventNameArray.forEach(function(v,i,a){
			element.addEventListener(v, callback, !!useCapture);
		});
	}
	
	var remove = function(element, callback, useCapture){
		this.eventNameArray.forEach(function(v,i,a){
			element.removeEventListener(v, callback, !!useCapture);
		});
	}
	
	// animationstart
	var onAnimationStart = {
		add: add,
		remove: remove,
		eventNameArray: ['webkitAnimationStart', 'MSAnimationStart', 'oanimationstart', 'animationstart']
	}
	
	// animationend
	var onAnimationEnd = {
		add: add,
		remove: remove,
		eventNameArray: ['webkitAnimationEnd', 'MSAnimationEnd', 'oanimationend', 'animationend']
	}
	
	// animationiteration
	var onAnimationIteration = {
		add: add,
		remove: remove,
		eventNameArray: ['webkitAnimationIteration', 'MSAnimationIteration', 'oanimationiteration', 'animationiteration']
	}
	
	// transitionend
	var onTransitionEnd = {
		add: add,
		remove: remove,
		eventNameArray: ['webkitTransitionEnd', 'MSTransitionEnd', 'oTransitionEnd', 'otransitionend', 'transitionend']
	}
	
	return {
		onAnimationStart: 		onAnimationStart,
	    onAnimationEnd: 		onAnimationEnd,
	    onAnimationIteration:	onAnimationIteration,
	    onTransitionEnd: 		onTransitionEnd
	}
}