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...