CSS3 Card Trick: A Fun CSS3 Experiment

Sep 6 2010 by Alexander Dawson | 11 Comments

This tutorial is based on a simple animated experiment that showcases just one of the amazing things you can create using CSS. I’ve used no images and no scripting; everything’s done using HTML and CSS.

It goes without saying that since CSS3 is still not supported by all browsers, it might not work as intended; but I’ve coded this in such a way that it will degrade gracefully on non-CSS3 browsers, including IE (of course).

Experimenting on cutting-edge standards for the sake of innovation is an attribute that helps us learn, and perhaps by pushing the boundaries, we can improve our knowledge further.

Final Result

You can click on the preview image to see the demo. For optimum experience, use a WebKit browser like Google Chrome or Apple Safari.

Final Result

View Demo

Download Source

A Primer on Innovation

If you ask any self-taught professional, motivation and willingness to experiment are the two primary skills that feed their passion to becoming better designers and developers.

While memorizing every single element, property, function and attribute for every language is an option, knowing what they can do is even better.

Whether you are working out how to fix a browser bug, achieving a complex layout, or if you simply want to play around and see what you can come up with (like this example), the ability to hone your skills to match the situation puts you in a fantastic position for whatever the world may throw at you.

Now that the inspiring speech about the justification behind this fun experiment is over, it’s time we begin examining and reconstructing this example to display how everything came together to produce the final result.

Within this experiment we will be taking advantage of some cool CSS3 code (which you can use in other projects) such as border-radius, box-shadow along with the target and checked pseudo classes.

Oh, and if that wasn’t enough, we’re even going to use a few WebKit transformations to give Chrome and Safari (they support animations) a progressively-enhanced experience.

So what I hope will happen is that by going over the process of creating these CSS3 playing cards, you’ll have fun learning about these new CSS3 capabilities.

Fragments and Fieldsets

Like with all websites, we need to begin right at the beginning with some HTML that lays down the tracks for the experiment.

For the purpose of this example, we’ll keep the CSS and JavaScript used inline inside the document so that you can easily use the View Source feature in your web browser while studying the demo. But in production, I hope you will keep your CSS and JavaScript external.

In the code block, you will find:

  • An unordered list that will feature the various card suits
  • A paragraph of text which simply describes the experiment on the page
  • A (very complex) web form that will hold the stylistic variables which make up each of the cards
<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Playing Cards with CSS3!</title>
<style type="text/css">

</style>
<script type="text/javascript">

</script>
</head>
<body>
<ul>
  <li><a title="Select Spades" href="#spades">&#9824;</a></li>
  <li><a class="fire" title="Select Hearts" href="#hearts">&#9829;</a></li>
  <li><a title="Select Clubs" href="#clubs">&#9827;</a></li>
  <li><a class="fire" title="Select Diamonds" href="#diamonds">&#9830;</a>
  </li>
</ul>
<form action="">
  <fieldset id="spades">
    <input class="card" id="spade" type="radio" name="spade" value="spade" />
    <label class="base" for="spade" title="This is the Ace of Spades!">
      <span><em>A</em>&#9824;</span><strong>&#9824;</strong><em>A</em>&#9824;
    </label>
    <input id="cancel1" type="reset" name="spade" value="cancel" checked="checked" />
    <label class="close" for="cancel1">Spades</label>
  </fieldset>
  <fieldset id="hearts">
    <input class="card" id="heart" type="radio" name="heart" value="heart" />
    <label class="base fire" for="heart" title="This is the Ace of Hearts!">
      <span><em>A</em>&#9829;</span><strong>&#9829;</strong><em>A</em>&#9829;
    </label>
    <input id="cancel2" type="reset" name="heart" value="cancel" checked="checked" />
    <label class="close" for="cancel2">Hearts</label>
  </fieldset>
  <fieldset id="clubs">
    <input class="card" id="club" type="radio" name="club" value="club" />
    <label class="base" for="club" title="This is the Ace of Clubs!">
      <span><em>A</em>&#9827;</span><strong>&#9827;</strong><em>A</em>&#9827;
    </label>
    <input id="cancel3" type="reset" name="club" value="cancel" checked="checked" />
    <label class="close" for="cancel3">Clubs</label>
  </fieldset>
  <fieldset id="diamonds">
    <input class="card" id="diamond" type="radio" name="diamond" value="diamond" />
    <label class="base fire" for="diamond" title="This is the Ace of Diamonds!">
      <span><em>A</em>&#9830;</span><strong>&#9830;</strong><em>A</em>&#9830;
    </label>
    <input id="cancel4" type="reset" name="diamond" value="cancel" checked="checked" />
    <label class="close" for="cancel4">Diamonds</label>
  </fieldset>
</form>
<p>Select an option above to change the suit displayed!</p>
</body>          
</html>

Unicode Characters for the Card Suits

While much of the HTML above is straightforward, there is something worth mentioning for its value in our discussion. Within both the list and the form, you will notice that there are a lot of strange Unicode escape characters (such as &#9830;) which are embedded at various points.

When you view the page in your browser, you will notice that these characters represent each suit (spades, hearts, clubs and diamonds) and therefore we can give the cards their appearance without any images.

The list has one mention for each icon, and each form has 3 for each (for the corners and centerpiece).

With the HTML finished, you should see the list, table and text (plus those cool characters).

What’s With The Web Form?

You may be curious about the monstrous HTML web form. The justification for such code is simply due to the way the CSS3 will work with the elements. While the list element uses simple fragment links (attached to the frameset container for each card), each card — when it appears — contains two input elements with associated labels.

The first label contains a mixture of span and em elements (to give the card value in the corners) and a strong element (for the big central character).

The second label simply acts as a reset mechanism for the special effects, i.e. when a WebKit browser is being used.

Laying the Foundations

Now that we have completed the HTML, it’s time to move onto the CSS. To begin, we will add in all the CSS content for the web page; and we also need to give our cards a bit of color.

The below code begins our journey into CSS3 by taking advantage of both the border-radius and box-shadow CSS properties (with a few compatibility tweaks).

IE Support

It’s worth noting that the filter property will not validate under W3C CSS standards due to it being a proprietary extension for Microsoft’s Internet Explorer; but as this is just for fun, the validation of the code is less important. This allows us to support Internet Explorer; that’s a good enough reason to break auto-validation in this case.

body { background: #DDDDDD; overflow: hidden; }
body .fire { color: #FF0000; }
p {
  background: #FFFFFF; border: 1px solid #CCCCCC;
  border-radius: 5px 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px;
  box-shadow: 5px 5px 5px #CCCCCC; -webkit-box-shadow: 5px 5px #CCCCCC; -moz-box-shadow: 5px 5px #CCCCCC;
  filter: progid:DXImageTransform.Microsoft.Shadow(color='#CCCCCC', Direction=135, Strength=5);
  font-size: 25px;
  text-align: center;
  height: 30px;
  width: 600px;
  margin: -35px -300px;
  padding: 10px 15px;
  position: absolute;
  bottom: 50px;
  left: 50%;
  z-index: 99;
}

Using the above code, you should see a lovely looking paragraph on your page!

Navigation, Simplified!

Next on the list is the navigation. For our playing card experiment, we shall be making use of anchor fragments that will show and hide each of the cards (as required).

While the code you’ll see next doesn’t contain the CSS3 that will activate the navigation (we’ll get to that later), you will notice the code that not only floats the navigation to the top-right hand side of the screen, but also adds the same cool border-radius and box-shadow effects.

When you refresh the page after plugging in this code, you should see that the links are now highly visible and make use of our awesome Unicode characters.

ul {
  background: #FFFFFF; border: 1px solid #CCCCCC;
  background:-moz-linear-gradient(top, #FFFFFF, #DDDDDD); background:-webkit-gradient(linear,0 0, 0 100%, from(#FFFFFF), to(#DDDDDD));
  border-radius: 5px 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px;
  box-shadow: 5px 5px 5px #CCCCCC; -webkit-box-shadow: 5px 5px #CCCCCC; -moz-box-shadow: 5px 5px #CCCCCC;
  filter: progid:DXImageTransform.Microsoft.Shadow(color='#CCCCCC', Direction=135, Strength=5);
  font-size: 50px;
  margin: 0;
  padding: 0 15px;
  position: absolute;
  right: 20px;
  top: 15px;
  z-index: 99;
}
ul li {
  display: inline;
  list-style-type: none;
}
ul li a {
  color: #000000;
  display: block;
  float: left;
  padding: 0 10px;
  text-decoration: none;
}

Now we have the list hovering and ready for action (along with that paragraph).

Styling the Aces

The most complicated part of the CSS is making the cards look like, well, like playing cards. Using the code that follows will get you the perfect and progressively enhancing design elements that make the final look possible.

Code to pay attention to includes:

  • The CSS3 linear gradient that fade the cards
  • The reversed gradient using the mask-image property on the center character (providing an even softer feel)
  • A span label effect which rotates the bottom right reference to make it upside down (just like real cards)

All simple but very effective.

.base {
  background: #FFFFFF;
  border: 1px solid #CCCCCC;
  color: #000000;
  background:-moz-linear-gradient(top, #FFFFFF, #DDDDDD); background:-webkit-gradient(linear,0 0, 0 100%, from(#FFFFFF), to(#DDDDDD));
  border-radius: 5px 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px;
  box-shadow: 5px 5px 5px #CCCCCC; -webkit-box-shadow: 5px 5px #CCCCCC; -moz-box-shadow: 5px 5px #CCCCCC;
  filter: progid:DXImageTransform.Microsoft.Shadow(color='#CCCCCC', Direction=135, Strength=5);
  height: 360px;
  top: 50%;
  margin-top: -180px;
  width: 260px;
  left: 50%;
  margin-left: -130px;
  z-index: 9;
  cursor: pointer;
  font-size: 50px;
  text-decoration: none;
  padding: 15px 0 0 25px;
  position: absolute;
}
strong {
  font-size: 250px;
  position: absolute;
  left: 50%;
  top: 50%;
  margin-top: -160px;
  -webkit-mask-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0,0,0,0.4)), to(rgba(0,0,0,1)));
}
em {
  font-size: 40px;
  font-style: normal;
  display: block;
  margin-bottom: -15px;
}
label span {
  -webkit-transform: rotate(-180deg); -moz-transform: rotate(-180deg); -o-transform: rotate(-180deg); filter:
  progid:DXImageTransform.Microsoft.BasicImage(rotation=2);
  position: absolute;
  bottom: 15px;
  right: 25px;
}
#spades strong { margin-left: -68px; } #spades em { margin-left: 0; }
#hearts strong { margin-left: -70px; } #hearts em { margin-left: 1px; }
#clubs strong { margin-left: -80px; } #clubs em { margin-left: 3px; }
#diamonds strong { margin-left: -60px; } #diamonds em { margin-left: -2px; }

Note: Depending on the browser used, the effects may look different. Chrome, Safari both support all the fancy stuff, Firefox will have the background gradient (but the center character will look strong), and Opera and IE will have no "worn" effects!

With some clever coding, the playing cards should now look easy on the eyes.

Navigation and Animation

Using the code above, your cards should appear like they come from a proper deck of playing cards. Now that we have the cards, navigation, and paragraphs looking all pretty, it’s important that we get each of the cards appearing on demand. And we should also do something with the cancel and radio buttons that are hovering around behind the scenes.

What happens next is where things get really interesting for you WebKit users.

fieldset { display: none; }
fieldset:target { display: block; }
fieldset:target .card+label { -webkit-animation-name: scaler; -webkit-animation-duration: 1.75s; -webkit-animation-iteration-count: 1; }
fieldset:target .card:checked+label { -webkit-animation-name: effectx; -webkit-animation-duration: 3s; -webkit-transform: scale(0); }
.close {
  background: #DDDDDD; cursor: default;
  left: 0;
  top: 0;
  position: absolute;
  height: 100%;
  width: 100%;
  z-index: 1;
  text-indent: -999em;
}
@-webkit-keyframes scaler { from { -webkit-transform: scale(0); } to { -webkit-transform: scale(1); } }
@-webkit-keyframes effectx {
from { -webkit-transform: rotateX(0deg); }
to { -webkit-transform: scale3d(1.2, 1.2, 1.2) rotateX(-90deg) translateZ(500px) rotate(180deg); -webkit-animation-duration: 30s; }
}

Explaining the above code is very simple. With the anchor links, we are using fragment URLs to navigate between cards in the deck and therefore the target pseudo class hide and show the fieldset as its ID appears.

The .close class takes its place behind the card covering the full browser viewport so that upon clicking the page (once the card is hidden), you can restore the item back to its original position.

This is relative to the usage of radio buttons as we shall be using the CSS3 :checked pseudo to animate the content for WebKit browsers depending on the check state.

The animation and effects may not show, depending on your browser.

The main features that WebKit users will be excited about are the two card classes that trigger either the scaler keyframes which will make the card zoom in (from nowhere) or the effectx keyframes that will rotate and flip the card which makes it appear as if it’s being pushed over (and falling off the page).

We can also add some simple effects that work alongside the checked property to give some lovely experimental fun stuff that you can interact with (if you use Chrome or Safari). Other browsers will simply ignore the actions.

Note: With most WebKit animations, once the effect has run its course, it will be reset to a default point. Because this example required the effect to remain permanent (until directed by the user otherwise), I made use of the checked state pseudo and radio buttons to ensure the effects were held firmly in place.

Dealing with Internet Explorer

OK, so remember in the beginning when I said I’ve used no scripting? Well that’s only partially true.

Because IE doesn’t yet support all these things, we need to use JavaScript so that at least our IE users will have a decent experience.

Of course, if you don’t care about IE — after all, this is an experiment for cutting-edge browsers that support CSS3 — then, yes, this CSS3 experiment uses no scripting whatsoever.

Luckily, because IE — like other non-WebKit browsers — don’t support the CSS3 animated effects, the need to deal with the checked state (in CSS3) is moot since the effect will be non-functional anyway.

However, one thing that should be available is the target pseudo so that IE users can change the suit of the playing card.

Using a small bit of conditional JavaScript, we can replicate the effect with little impact on the browser. There’s also a fragment redirect in the script to help browsers load the first card.

function bootup(){
if (location.hash == "") { location.hash="#spades"; } var tds = document.getElementsByTagName("a"); direct();
  for( var x=0; x < tds.length; x++ ){tds[x].onclick = function(){setTimeout(direct, 1);};}
}
function direct(){
/*@cc_on @if (@_jscript_version > 5.6)
  var counted = document.getElementsByTagName("fieldset");
  for( var x=0; x < counted.length; x++ ){ counted[x].style.display = "none" } 
  document.getElementById(location.hash.substr(1)).style.display = "block";
@end @*/
}
window.onload=bootup;

The example should now be complete and have some neat special effects!

While the above code should be enough to get the basic effect working on the latest version of IE, its worth highlighting that I didn’t spend much time attempting to get the effect functional on really old browsers like IE6.

Because this is a proof-of-concept demonstration — and because it exists just to play with what’s available in up and coming standards — there was no incentive to try and fire the effects onto every browser.

It’s worth saying, however, that if you do intend on using any of this in a production site, you should support the browsers your visitors use.

Playful Innovation

Just a few years ago, the ability to produce such a textured playing card that looks like an image would not have been possible without the use of images. The animation effects, without scripting or Flash, would have been beyond most people’s dreams.

Our proof-of-concept shows the benefits of modern standards, and what the future is for us web designers and web developers.

The need to keep innovating and pushing our browsers to the limit is an important part of the web’s evolution.

As a web professional, I always try to spend time learning and examining my own abilities to see what unique solutions I can produce. Ideally, after reading this, you will be inspired to experiment on your own. Good luck and share your own experiments in the comments!

Related Content

About the Author

Alexander Dawson is a freelance web designer, author and recreational software developer specializing in web standards, accessibility and UX design. As well as running a business called HiTechy and writing, he spends time on Twitter, SitePoint’s forums and other places, helping those in need.

11 Comments

Kenneth van Rumste

September 6th, 2010

nice to see that it’s browser compatible with IE, in firefox it doesn’t animate as it should though…

never the less, nice job…

Rafael

September 6th, 2010

CSS3 is still under development and it isn’t very used unless you’re thinking on “border-radius”… That’s why web browsers don’t have the support yet.

Billy

September 6th, 2010

This is a great example of how CSS3 and HTML5 will take over Flash’s more simple applications.

mark

September 6th, 2010

animation works great on chrome :D

fyi, center suit is not centered with the card in Chrome 6 beta

Alexander Dawson

September 7th, 2010

Thanks for the comments guys, glad you enjoyed it.

@Kenneth van Rumste: Actually you’re wrong there, Firefox can’t showcase the animated effects because only webkit based browsers support CSS3 animated transitions. While I’d love Firefox to include such functionality, it’s only Chrome and Safari that have any support for such eye candy thus Firefox has to sit among the primitives!

Luke

September 7th, 2010

Great stuff!!!

Nathan Barry

September 7th, 2010

Though that is a good effect, part of it is ruined because of the shadow on the card. As the card falls away it shouldn’t maintain the same shadow it has when shown straight on.

Currently it is hard to determine how the card is rotating as it falls away. In this case you would be better off removing the shadows.

I posted an example of animated CSS3 a few months ago here: http://legendthemes.com/2010/05/14/3d-css-wordpress-theme/

Craig

September 9th, 2010

Nice CSS3 example, great share, Thanks!

Schalk Neethling

September 12th, 2010

Hey Alex,

Awesome tutorial, thanks so much. I am always in two minds when it comes to animation with CSS but nevertheless, this is really well done.

Schalk

Maxime

September 17th, 2010

Nice demonstration and clever use of the inputs behavior ;)
Well done

Leave a Comment

Subscribe to the comments on this article.