skip navigation

JavaScript: Controlling CSS Animations

This page presents a simple game of Concentration using JavaScript events and CSS transforms to provide real-time effects. The mechanics of the game are not so important, the aim is mainly to show how we can trigger animations using JavaScript events instead of just using the :hover event or keyframes.

The example below is working in WebKit browsers (Safari, Chrome, iPhone/iPad), Mozilla browsers (Firefox) and Opera. It may also work in Internet Explorer 10 though that has yet to be confirmed.

Working Example

Here you can see the final product. It's not flashy, but surprisingly smooth given how simple the code is. Just click on the card to the left to get started and read below for all the technical details:

[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]
[]

The goal of the game, as you probably already know, is to turn over two cards with the same value to make a pair. Once you've matched all eight pairs the game board will be back in the original state and you can start again with a new card order.

Setting up the table

The HTML code for this is actually very simple:

<div id="stage"> <div id="felt"> <div class="card" id="card_0"><img onclick="cardClick(0);" src="back.png"></div> <div class="card" id="card_1"><img onclick="cardClick(1);" src="back.png"></div> <div class="card" id="card_2"><img onclick="cardClick(2);" src="back.png"></div> ... <div class="card" id="card_15"><img onclick="cardClick(15);" src="back.png"></div> </div> </div>

These elements are styled using the following CSS:

<style type="text/css"> #stage { border: 1px solid #ccc; } #felt { position: relative; margin: 0 0 0 200px; height: 500px; background: green; } div.card { position: absolute; left: -140px; top: 100px; } </style>

This creates the layout you see above. The #stage element is just the outline box. The #felt element creates the green background and allows for the sixteen .card elements to be placed relative to it. The starting position for all sixteen cards is in a pile to the left of the #felt.

Transitions

Transitions are simply a way to have changes to CSS values affecting positioning or appearance carried out over a period of time rather than instantly.

In this case the main effect is that the cards will slide across the screen rather than just flicking instantly from one place to another. When clicked they will also change size smoothly.

Before CSS transitions became available such effects were only achievable using technologies such as Flash or complicated JavaScript libraries such as jQuery and MooTools.

The following additional CSS style is all we need to define our transitions:

<style type="text/css"> div.card { -webkit-transition: all 0.5s ease-in-out; } </style>

This means that every style change on the .card elements will take place smoothly over half a second. For more information you can read our article on Transition Timing Functions.

Shuffling, Dealing and Playing

To start with we define the board position of all sixteen cards relative to the #felt element to form a 4x4 grid. The start/end position to the left of the board is defined in the CSS.

Each card on the board is then assigned a value from the card_values array ranging from '1C' (ace of clubs) to '8H' (8 of hearts). The card images are named the same way.

From then it's just a matter of modifying the position (left, top) and zoom value (scale()) of the cards as the game is played. Because of the transition settings in the CSS these changes are seen as a smooth animation.

In the code below the code responsible for the animations has been highlighted:

<script type="text/javascript"> // Original JavaScript code by Chirp Internet: www.chirp.com.au // Please acknowledge use of this code by including this header. var card_value = ['1C','2C','3C','4C','5C','6C','7C','8C','1H','2H','3H','4H','5H','6H','7H','8H']; // set default positions var card_left = []; var card_top = []; for(var i=0; i < 16; i++) { card_left[i] = 70 + 100 * (i%4); card_top[i] = 15 + 120 * Math.floor(i/4); } var started = false; var cards_turned = 0; var matches_found = 0; var card1 = false; var card2 = false; function moveToPlace(id) { var el = document.getElementById("card_" + id); el.style["z-index"] = 1000; el.style["left"] = card_left[id] + "px"; el.style["top"] = card_top[id] + "px"; el.style["z-index"] = 0; } function hideCard(id) { var el = document.getElementById("card_" + id); el.firstChild.src = "back.png"; el.style["WebkitTransform"] = "scale(1.0)"; } function moveToPack(id) { hideCard(id); var el = document.getElementById("card_" + id); el.style["z-index"] = 1000; el.style["left"] = "-140px"; el.style["top"] = "100px"; el.style["z-index"] = 0; } // flip over card and check for match function showCard(id) { if(id === card1) return; var el = document.getElementById("card_" + id); el.firstChild.src = card_value[id] + ".png"; el.style["WebkitTransform"] = "scale(1.2)"; if(++cards_turned == 2) { card2 = id; // check whether both cards have the same value if(parseInt(card_value[card1]) == parseInt(card_value[card2])) { setTimeout("moveToPack(" + card1 + "); moveToPack(" + card2 + ");", 1000); if(++matches_found == 8) { // game over matches_found = 0; started = false; } } else { setTimeout("hideCard(" + card1 + "); hideCard(" + card2 + ");", 800); } card1 = card2 = false; cards_turned = 0; } else { card1 = id; } } function cardClick(id) { if(started) { showCard(id); } else { // shuffle and deal cards card_value.sort(function() { return Math.round(Math.random()) - 0.5; }); for(i=0; i < 16; i++) setTimeout("moveToPlace(" + i + ")", i * 100); started = true; } } </script>

expand code box

For some of the effects to work in other browsers you need to set not just the WebkitTransform property, but also MozTransform, OTransform and msTransform to the same value where it appears in the code.

Download Code

Here you can download the CSS and JavaScript used for the demonstration from the top of this page. There are some slight changes from the code presented - mainly to cater for more browsers:

If you have any problems or comments, or have managed to get something working in Internet Explorer, please let us know using the Feedback form below.

Related Articles

References

< JavaScript


Send Feedback

Send Your Feedback (will not be published) (optional) CAPTCHA refresh <- copy the digits from the image into this box

[top]