Colorful Flip Clock Countdown

by Federico Tibaldo

HTML

<div class="container" id="flip-countdown-target">

	<div class="counter" id="days">
		<div class="layers">
			<div class="top blue"><p></p></div>
			<div class="bottom blue"><p></p></div>
			<div class="top red"><p></p></div>
			<div class="bottom red"><p></p></div>
			<div class="top yellow"><p></p></div>
			<div class="bottom yellow"><p></p></div>
		</div>
		<p class="description">Days</p>
    </div>

	<div class="counter" id="hours">
        <div class="layers">
			<div class="top blue"><p></p></div>
			<div class="bottom blue"><p></p></div>
			<div class="top red"><p></p></div>
			<div class="bottom red"><p></p></div>
			<div class="top yellow"><p></p></div>
			<div class="bottom yellow"><p></p></div>
		</div>
		<p class="description">Hours</p>
    </div>

	<div class="counter" id="minutes">
        <div class="layers">
			<div class="top blue"><p></p></div>
			<div class="bottom blue"><p></p></div>
			<div class="top red"><p></p></div>
			<div class="bottom red"><p></p></div>
			<div class="top yellow"><p></p></div>
			<div class="bottom yellow"><p></p></div>
		</div>
		<p class="description">Minutes</p>
    </div>
	
    <div class="counter" id="seconds">
        <div class="layers">
			<div class="top blue"><p></p></div>
			<div class="bottom blue"><p></p></div>
			<div class="top red"><p></p></div>
			<div class="bottom red"><p></p></div>
			<div class="top yellow"><p></p></div>
			<div class="bottom yellow"><p></p></div>
		</div>
		<p class="description">Seconds</p>
	</div>

</div>

SCSS

.blue {
    color: white;
    &.top {
        background-color: pink;
    }
    &.bottom {
        background-color: pink;
    }
}

.red {
    color: white;
    &.top {
        background-color: pink;
    }
    &.bottom {
        background-color: pink;
    }
}

.yellow {
    color: #333;
    &.top {
        background-color: #FFEB3B;
    }
    &.bottom {
        background-color: #FDD835;
    }
}

.container {
    text-align: center;
    width: 500px;
    .counter {
        display: inline-block;
		margin: 0 8px;
		.layers {
			position: relative;
			width: 6rem;
			height: 6rem;
			-webkit-transform-style: preserve-3d;
			-moz-transform-style: preserve-3d;
			.top,
			.bottom {
				position: absolute;
				width: 100%;
				height: 50%;
				overflow: hidden;
				p {
					position: relative;
					margin: 0;
					font-family: arial;
					font-size: 2rem;
					font-weight: bold;
					line-height: 3rem;
				}
			}
			.top {
				border-radius: 15px 15px 0 0;
				transform-origin: bottom center;
				top: 0%;
				&.next {
					transform: translateZ(-1px) scaleY(1);
				}
				&.current {
					transform: translateZ(0px) scaleY(1);
				}
				&.previous {
					transform: translateZ(0px) scaleY(0);
					transition: transform 0.05s cubic-bezier(0.600, 0.040, 0.980, 0.335); /* circ ease-in */
				}
				&.hidden {
					transform: translateZ(0px) scaleY(0);
				}
				p {
					top: 50%;
				}
			}
			.bottom {
				border-radius: 0 0 15px 15px;
				transform-origin: top center;
				top: 50%;
				&.next {
					transform: translateZ(1px) scaleY(0);
				}
				&.current {
					transform: translateZ(0px) scaleY(1);
					transition: transform 0.05s cubic-bezier(0.075, 0.820, 0.165, 1.000); /* circ ease-out */
				}
				&.previous {
					transform: translateZ(-1px) scaleY(1);
				}
				&.hidden {
					transform: translateZ(0px) scaleY(0);
				}
				p {
					bottom: 50%;
				}
			}
		}
		.description {
			font-family: arial;
			margin: 0;
			text-transform: uppercase;
			font-size:...

JavaScript

var Layer = {
	filterClassName: function(el) {
		return el.className.split(' ').filter(function(el) {
			return el != 'previous' && el != 'current' && el != 'next' && el != 'hidden';
		}).join(' ');
	},
	setNext: function() {
		this.top.className = this.filterClassName(this.top) + ' next';
		this.bottom.className = this.filterClassName(this.bottom) + ' next';
	},
	setCurrent: function() {
		this.top.className = this.filterClassName(this.top) + ' current';
		this.bottom.className = this.filterClassName(this.bottom) + ' current';
	},
	setPrevious: function() {
		this.top.className = this.filterClassName(this.top) + ' previous';
		this.bottom.className = this.filterClassName(this.bottom) + ' previous';
	},
	setHidden: function() {
		this.top.className = this.filterClassName(this.top) + ' hidden';
		this.bottom.className = this.filterClassName(this.bottom) + ' hidden';
	},
	setValue: function(value) {
		this.top.children[0].innerHTML = value;
		this.bottom.children[0].innerHTML = value;
		return this;
	}
}

var Counter = {
	init: function(element, colors, value, isNegativeAllowed, max = NaN, nextCounter = null) {
		this.index = 0;
		this.element = element;
		this.colors = colors;
		this.value = value;
		this.isNegativeAllowed = isNegativeAllowed;
		if(!isNegativeAllowed) {
			this.max = max;
			this.nextCounter = nextCounter;
		}
		this.layers = new Array(colors.length);
		for(let i = 0; i < this.layers.length; i++) {
			this.layers[i] = Object.create(Layer);
		}
		Array.prototype.forEach.call(
			element.children[0].children,
			el => {
				for(let i = 0; i < colors.length; i++) {
					if(el.classList.contains(colors[i])) {
						if(el.classList.contains('top'))
							this.layers[i].top = el;
						else if(el.classList.contains('bottom'))
							this.layers[i].bottom = el;
						break;
					}
				}
			}
		);
		this.getCurrent().setValue(this.value).setCurrent();
		this.getNext().setNext();
		this.getPrevious().setHidden();
	},
	getCurrent: function() {
		return...