Create a random playing card generator with JavaScript
Tags: javascript, tutorial
Published: 2020-09-03 07:42:47

In this tutorial we’ll be using JavaScript to generate a deck of playing cards and then select a random card from that deck. We’ll then output the random card in the browser and add some CSS so it looks like an actual playing card. If you’re interested in building card games using JavaScript this is a good starting point before moving onto more elaborate games.

{% codepen https://codepen.io/michaelburrows/pen/ZEWXZYy %}

Let’s get started by creating a `index.html` file with the following markup:

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Random Playing Card</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>    
    <script src="script.js"></script>
  </body>
</html>
```

Then create a `script.js` file and add a `deckBuilder` function that we’ll use to generate an array containing the values for 52 playing cards:

```javascript
function deckBuilder() {
  // ...
}
```

Inside `deckBuilder` define the values and suits used in a deck of playing cards:

```javascript
const values = [ "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", ];
const suits = ["Hearts", "Diamonds", "Spades", "Clubs"];
```

Next loop through the `suits` array whilst also looping through the `values` array and push the combined data into the `cards` array:

```javascript
const cards = [];
for (let s = 0; s < suits.length; s++) {
  for (let v = 0; v < values.length; v++) {
    const value = values[v];
    const suit = suits[s];
    cards.push({ value, suit });
  }
}
return cards;
```

We now have a function that creates an array with the suit/value combination for 52 playing cards structured as follows:

```javascript
0: {value: "A", suit: "Hearts"}
1: {value: "2", suit: "Hearts"}
2: {value: "3", suit: "Hearts"}
```

Next we’ll create the `randomCard` function passing it the cards array:

```javascript
function randomCard(cards) { 
  // ...
}
const cards = deckBuilder();
randomCard(cards);
```

Inside the `randomCard` function we’ll generate a random number between 0 and 51 (not 52 as array indexes start at 0) and get the data from the `cards` array at that index. This data is then stored in variables to make it easier to work with later:

```javascript
const random = Math.floor(Math.random() * 51);  
const cardValue = cards[random].value;
const cardSuit = cards[random].suit;
```
As there are [HTML character entities](https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references) for each of the playing card suits (♥/♦/♠/♣) we can output these onto our playing card without having to use images. Because the entity code for diamonds is truncated we need to also truncate the `"Diamonds"` string, the other suits entity codes match the strings (`&hearts; &spades; &clubs;`) so all we need todo is convert them to lowercase.

```javascript
let entity;
cardSuit === "Diamonds" ? (entity = "&diams;") : (entity = "&" + cardSuit.toLowerCase() + ";");
```

Finally we can render the random card into the HTML page. If you look at the [final design](https://codepen.io/michaelburrows/pen/ZEWXZYy) for this project you’ll see why `cardValue` and `entity` have been repeated.

```javascript
const card = document.createElement("div");
card.classList.add("card", cardSuit.toLowerCase());
card.innerHTML = 
'<span class="card-value-suit top">' + cardValue + entity + '</span>' + 
'<span class="card-suit">' + entity + '</span>' + 
'<span class="card-value-suit bot">' + cardValue + entity + '</span>';
document.body.appendChild(card);
```

With the functionality complete we can add some CSS to our random playing card.

Create a file called `style.css` and add the following to create the basic playing card shape:

```css
.card {  
  position: relative;
  width: 105px;
  height: 150px;
  border-radius: 5px;
  border: 1px solid #ccc;
  box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.25);
}
```

Because `.card` is positioned relatively we can use absolute positioning for the top and bottom text. We’ll also rotate the text at the bottom 180 degrees just like a real playing card.

```css
.card-value-suit {
  display: inline-block;
  position: absolute;
}
.card-value-suit.top {
  top: 5px;
  left: 5px;
}
.card-value-suit.bot {
  transform: rotate(180deg);
  bottom: 5px;
  right: 5px;
}
.card-suit {
  font-size: 50px;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  left: 25%;
}
```

And finally we’ll add the colors for each of the suits:

```css
.card.spades,
.card.clubs {
  color: black;
}
.card.hearts,
.card.diamonds {
  color: red;
}
```