Memory game
By Jani, 26 November, 2010

Memory game with html5 and css3

In this project I made the classic memory game where you have to turn cards and find pairs. The purpose of this project was to test out the basic HTML5 layout with the built in audio tag and some nifty animations with transition in CSS3. Therefore the game only works with modern webkit browsers like Safari and Chrome.

Let’s start with the HTML layout. Here I have used the following new HTML5 tags: doctype, header, section, footer and audio. The rest is pretty basic with an unordered list for the cards.

The reason for using two audio tags with different id’s is that I didn’t want any conflict if the user rapidly clicked on two cards. With one audio tag the sound was disrupted.

<!DOCTYPE html>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <link rel="stylesheet" type="text/css" href="css/style.css" />
        <script type="text/javascript" src="scripts/jquery-1.4.2.min.js"></script>
        <script type="text/javascript" src="scripts/game.js"></script>
        <audio id="flip-sound-1" autobuffer>
                <source src="sound/flip-sound.mp3">
        <audio id="flip-sound-2" autobuffer>
                <source src="sound/flip-sound.mp3">
                <h1>Memory game</h1>
                <h2>with  HTML5, CSS3 and jQuery</h2>
                        <li class="card">
                                <div class="front">
                                        <div class="grey"></div>
                                <div class="back"></div>
                <p><span class="num-turns">0</span> card<span class="plural">s</span> flipped in</p>
                <p><span class="time">0</span> seconds</p>

I’ve picked out the most interesting parts in the CSS that uses CSS3 for gradients, shadows and animations. No need to go through all the code.

First we need to initialize start values for the animation for every div in the card class. Here we set duration, easing and hide backface.

.card div {
        -webkit-transition-duration: .3s;
        -webkit-transition-timing-function: ease-out;
        -webkit-backface-visibility: hidden;

Here we style the front and back of the card with border radius, gradients, shadows etc.. Front class also gets a starting value of -180 degrees for the rotation. For back class we don’t need to apply any starting value for the rotation because the default value is 0 degrees, which is what we want.

.card .back, .card .front {
        position: absolute;
        top: 0px;
        left: 0px;
        width: 80px;
        height: 80px;
        background: #fff;
        -webkit-border-radius: 8px; -moz-border-radius: 8px; border-radius: 8px;

.card .front {
        z-index: 100;
        -webkit-transform: rotateY(-180deg);

.card .back {
        z-index: 200;
        -moz-box-shadow: 0 0 4px #323232; -webkit-box-shadow: 0 0 4px #323232; box-shadow: 0 0 4px #323232;

.card .back .graphic {
        position: absolute;
        top: 5px;
        left: 5px;
        width: 70px;
        height: 70px;
        background: -moz-linear-gradient(100% 100% 90deg, #bdeeee, #e0f0f1);
        background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#bdeeee), to(#e0f0f1));
        -webkit-border-radius: 8px; -moz-border-radius: 8px; border-radius: 8px;

As you may have noticed in the code above, front class doesn’t have any shadow applied. That’s because of one problem I encountered when both front and back of the card had a shadow. Somehow Chrome didn’t want to hide the backface so I got double set of shadows. Therefore this class below was set if users were using Safari to prevent two instances of shadows in Chrome.

.card.shadow_hack .front {
        -moz-box-shadow: 0 0 4px #323232; -webkit-box-shadow: 0 0 4px #323232; box-shadow: 0 0 4px #323232;

When users hover the back of a card we add a customhover class with jQuery which animates the card. We also show another shadow to make the illusion of lifting the card from the table.

.card.customhover .back {
        -webkit-transform: scale(1.1);
        -webkit-box-shadow: #666 0 5px 10px;

When card is clicked jQuery applies selected class on card and then CSS3 rotates the back object from 0 degrees to 180 degrees on the Y axis, and the front object rotates from -180 degrees to 0 degrees. Both sides of the cards needs to rotate 180 degrees to give a realistic animation.

.selected .back {
        z-index: 300;
        -webkit-transform: rotateY(180deg);

.selected .front {
        z-index: 400;
        -webkit-transform: rotateY(0deg);

To sum this up. I have encountered some problems in this project when trying to make the backface of the cards hidden. Maybe there is a workaround but Chrome didn’t seem to work well on that point. Chrome seems also to have difficulties to render graphic that is rotated. Graphics look allot smoother in Safari. I have also experienced that the sound may be out of sync sometimes.

Check out the demo.

Particle system #1 - Basic particles

Kinect Robot

Kinect Paint

Kinect Flight