CodePen

HTML

            
              <div class="count"></div>

<script id="count-template" type="text/template">
 <span class="current top <%= currentSize %>"><%= time %></span>
 <span class="next top <%= nextSize %>"><%= nextTime %></span>
 <span class="current bottom <%= currentSize %>"><%= time %></span>
 <span class="next bottom <%= nextSize %>"><%= nextTime %></span>
</script>

            
          
!

↑ Insert the most common viewport meta tag

CSS

            
              // animation vars
$duration: 0.35s
$bounce: cubic-bezier(0.375, 1.495, 0.610, 0.780)

// dimensions
$height: 300px
$width: 200px

.count
	box-shadow: 0 10px 5px -5px rgba(#000, 0.2)
	height: $height
	left: 50%
	line-height: $height
	margin: -($height / 2) 0 0 -($width / 2)
	+perspective(500px)
	position: absolute
	text-align: center
	top: 50%
	+translateZ(0)
	width: $width

	// the basic "card"
	//    there are four of these: top current, top next, bottom current, and bottom next
	span
		background: #202020
		color: #f8f8f8
		display: block
		font-size: 250px
		left: 0
		position: absolute
		top: 0
		text-shadow: 0 1px 0 (#000 + 40), 0 2px 0 (#000 + 30), 0 3px 0 (#000 + 20), 0 4px 0 (#000 + 10), 0 5px 0 #000, 0 0 10px rgba(#000, 0.8)
		+transform-origin(0, 150px, 0)
		width: 100%

		// the dividing line in the center
		&:before
			border-bottom: 2px solid #000
			content: ''
			left: 0
			position: absolute
			width: 100%

		// a shadow fill that adds some convexity on the card surfaces
		&:after
			box-shadow: inset 0 0 60px rgba(#000, 0.35)
			content: ''
			height: 100%
			left: 0
			position: absolute
			top: 0
			width: 100%

	// two-digit numbers get the 'small' class
	.small
		font-size: 175px

	.top
		// top card sit above the bottom ones, so if we give them the same
		//   border radius they'll create some crunchiness.
		//   instead, go one pixel smaller
		border-top-left-radius: 11px
		border-top-right-radius: 11px

		// creating a light shine on the top of the card
		box-shadow: inset 0 2px rgba(#000, 0.9), inset 0 3px 0 rgba(#fff, 0.4)

		// top cards are only 50% height, and overflow-hidden
		//   so they only show the top of their number
		height: 50%
		overflow: hidden

		&:before
			bottom: 0

		&:after
			// top card needs to get darker as it curves downward
			+background(linear-gradient(rgba(#000, 0), rgba(#000, 0.15)))
			border-top-left-radius: 11px
			border-top-right-radius: 11px

	.bottom
		// bottom cards are 100% height, but their top half is hidden by "top" cards
		//   this was the best way I could think of to show the bottom cards in half, but
		//   there's probably another way using display: table-cell and vertical-align.
		//   ew.
		border-radius: 10px
		height: 100%

		&:before
			top: 50%

		&:after
			border-radius: 10px
			+background(linear-gradient(rgba(#fff, 0.1), rgba(#fff, 0.1) 50%, rgba(#fff, 0)))

	// styles that only apply when counting "down"
	&.down
		.top
			// use a higher number than the bottoms to prevent crunchy border radiuses
			border-top-left-radius: 11px
			border-top-right-radius: 11px
			height: 50%

			&.current
				// required to prevent safari bug: https://bugs.webkit.org/show_bug.cgi?id=61824
				+transform-style(flat)
				z-index: 3

			&.next
				// when counting down, the next top card is rotated towards the user (and invisible)
				+transform(rotate3d(1, 0, 0, -90deg))
				z-index: 4

		.bottom
			border-radius: 10px

			&.current
				z-index: 2

			&.next
				z-index: 1

		&.changing
			.bottom.current
				box-shadow: 0 75px 5px -20px rgba(#000, 0.3)
				+transform(rotate3d(1, 0, 0, 90deg))

				// the current bottom card rotates up to hide itself, and reveal the next one
				+transition(transform $duration ease-in, box-shadow $duration ease-in)

		&.changing,
		&.changed
			.top.next
				// and the next top card rotates into view (after $duration)
				+transition(transform $duration ease-out $duration)
				+transform(none)

	&.up
		.top
			height: 50%

			&.current
				z-index: 4

			&.next
				z-index: 3

		.bottom
			&.current
				z-index: 1

			&.next
				box-shadow: 0 75px 5px -20px rgba(#000, 0.3)

				// when counting "up", the next bottom card begins pointed at the user...
				+transform(rotate3d(1, 0, 0, 90deg))
				z-index: 2

		&.changing
			.top.current
				// and the current top card does the rotating
				+transform(rotate3d(1, 0, 0, -90deg))

				// when the card is "dropping" it should be faster
				+transition(transform $duration * 0.75 ease-in, box-shadow $duration * 0.75 ease-in)

		&.changing,
		&.changed
			.bottom.next
				box-shadow: 0 0 0 0 rgba(#000, 0)

				// add a little bounce at the moment the card finishes falling
				+transition(box-shadow $duration / 2 $bounce $duration, transform $duration $bounce $duration)
				+transform(rotate3d(1, 0, 0, 0))

	&.changed
		.top.current,
		.bottom.current
			display: none

// presentation styles
@import url(http://fonts.googleapis.com/css?family=Oswald)

html,
body
	height: 100%
	width: 100%

body
	background: #202020 url(http://cl.ly/image/040I101f1i0I/planes.jpg) 50% 50%
	background-origin: 50% 50%
	+background-size(cover)
	font-family: 'Oswald'

            
          
!
? ?
? ?
Must be a valid URL.
+ add another resource
via CSS Lint

JS

            
              // underscore loaded

Countdown = function() {
	_(this).bindAll('update', 'executeAnimation', 'finishAnimation');
	this.setVars.apply(this, arguments);
	this.update();
};

Countdown.prototype = {
	duration: 1000,

	setVars: function(time, el, template) {
		this.max = time;
		this.time = time;
		this.el = el;
		this.template = _(template.innerHTML).template();
		this.delta = -1;
	},

	update: function() {
		this.checkTime();
		this.setSizes();

		this.setupAnimation();
		_(this.executeAnimation).delay(20);
		_(this.finishAnimation).delay(this.duration * 0.9);

		_(this.update).delay(this.duration);
	},

	checkTime: function() {
		this.time += this.delta;

		if (this.time === 0) this.delta = 1;
		if (this.time === this.max) this.delta = -1;

		this.delta === 1 ? this.toggleDirection('up', 'down') : this.toggleDirection('down', 'up');

		this.nextTime = this.time + this.delta;
	},

	toggleDirection: function(add, remove) {
		this.el.classList.add(add);
		this.el.classList.remove(remove);
	},

	setSizes: function() {
		this.currentSize = this.getSize(this.time);
		this.nextSize = this.getSize(this.nextTime);
	},

	getSize: function(time) {
		return time > 9 ? 'small' : '';
	},

	setupAnimation: function() {
		this.el.innerHTML = this.template(this);
		this.el.classList.remove('changed');
	},

	executeAnimation: function() {
		this.el.classList.add('changing');
	},

	finishAnimation: function() {
		this.el.classList.add('changed');
		this.el.classList.remove('changing');
	}
};

new Countdown(
	12,
	document.querySelector('.count'),
	document.querySelector('#count-template')
);

            
          
!
Must be a valid URL.
+ add another resource
via JS Hint
Loading ..................