DEV Community

Cover image for Create Random Cards With Pure CSS
Paul Mercieca
Paul Mercieca

Posted on

Create Random Cards With Pure CSS

There was no JavaScript, Sass, or other external scripts or preprocessors used in the development of these cards.

Every time you click on a card, it draws a different one; it may be a King of Hearts, an Ace of Spades, a 9 of diamonds, or any other card in a regular deck of cards.

HTML
<input type="checkbox" id="card_01" checked>
<label for="card_01">
  <div class="cardWrapper">
    <div class="cardRandom"></div>
  </div>
</label>
<input type="checkbox" id="card_02" checked>
<label for="card_02">
  <div class="cardWrapper">
    <div class="cardRandom"></div>
  </div>
</label>
<a href="https://uxdesign.cc/creating-randomness-with-pure-css-a990dafcd569" target="_blank" class="linkElement">Read <i>"Creating randomness with pure CSS"</i></a>
Enter fullscreen mode Exit fullscreen mode
CSS
body {
  background-color: #ececec;
  transform-style: preserve-3d;
  perspective: 2000px;
  display: flex;
  justify-content: center;
}

label .cardWrapper {
  position: relative;
  height: 40vmin;
  width: calc(40vmin / 1.4);
  background-color: royalblue;
  background-image: repeating-linear-gradient(
      120deg,
      rgba(255, 0, 0, 0.5),
      rgba(255, 0, 0, 0.5) 1px,
      transparent 1px,
      transparent 60px
    ),
    repeating-linear-gradient(
      60deg,
      rgba(255, 0, 0, 0.5),
      rgba(255, 0, 0, 0.5) 1px,
      transparent 1px,
      transparent 60px
    ),
    linear-gradient(
      60deg,
      rgba(0, 0, 0, 0.1) 25%,
      transparent 25%,
      transparent 75%,
      rgba(0, 0, 0, 0.1) 75%,
      rgba(0, 0, 0, 0.1)
    ),
    linear-gradient(
      120deg,
      rgba(0, 0, 0, 0.1) 25%,
      transparent 25%,
      transparent 75%,
      rgba(0, 0, 0, 0.1) 75%,
      rgba(0, 0, 0, 0.1)
    );
  background-size: 70px 120px;
  margin: calc(40vmin / 10);
  border-radius: calc(40vmin / 20);
  box-shadow: 0 calc(40vmin / 40) calc(40vmin / 10) 0 rgba(0, 0, 0, 0.2);
  overflow: hidden;
  float: left;
  transition: transform 200ms linear, box-shadow 100ms linear;
  transform: rotateY(0deg);
}

input:checked + label .cardWrapper {
  transform: rotateY(180deg);
}

.cardRandom {
  width: 100%;
  height: 100%;
  background-color: white;
  opacity: 1;
  cursor: pointer;
  transition: opacity 1ms linear 100ms;
}

.cardWrapper:hover {
  filter: brightness(0.98);
}

input:focus + label .cardWrapper {
  box-shadow: 0 0 calc(40vmin / 100) 0 rgba(0, 0, 0, 0.5);
}

input:checked + label .cardRandom {
  opacity: 0;
}

.cardRandom::before {
  content: "";
  position: absolute;
  width: 100%;
  height: 100%;
  background-image: url(https://assets.codepen.io/2722301/cards.jpg);
  background-size: cover;
  animation: randomCard 1000ms steps(51, end) infinite;
  animation-play-state: paused;
  transform: rotate(180deg);
}

input:checked + label .cardRandom::before {
  animation-play-state: running;
}

input {
  height: 0;
  width: 0;
  border: none;
  outline: none;
  display: none;
}

@keyframes randomCard {
  0% {
    background-position: 0 0;
  }
  100% {
    background-position: 100% 0;
  }
}

.linkElement {
  position: absolute;
  bottom: -40px;
  font-family: sans-serif;
  color: #4069e1;
  text-decoration: none;
}

.linkElement:hover {
  filter: hue-rotate(-45deg);
}
Enter fullscreen mode Exit fullscreen mode

First and foremost, there is no built-in “random” function in CSS, no Math.random() equivalent, and no way to generate a random number or color at all.

So what is happening here?

Since we don't have a random feature to regulate elements in CSS, they can't act randomly, but they can appear to act randomly by using an elaborate type of animation.

The cards in the preceding example animate quickly through the various states, and the user's click on each card pauses the animation, causing the card to flip at each of the various states.

The user can click on the cards at any time, but the animation is so fast that it serves as a random seed for our interaction; for example, these cards loop through all 52 states in less than one second.

This trick is particularly useful if you can conceal the mechanism itself, such as our flipped cards, since the consumer would never think to time it, unlike a slot machine, which can be pulled at precisely the right time.

Even if the user would try to time it, the animation between the different states is so fast it’s almost impossible to time correctly.

HTML
<input type="checkbox">
Enter fullscreen mode Exit fullscreen mode
CSS
input::after {
  content: "";
  position: absolute;
  width: 200px;
  height: 200px;
  background-color: red;
  cursor: pointer;
  animation: randomAnim 1000ms steps(1, end) infinite;
  top: 50%;
  left: 50%;
  margin-top: -100px;
  margin-left: -100px;
}
@keyframes randomAnim {
  0% {
    background-color: red;
  }
  50% {
    background-color: blue;
  }
}

input:checked::after {
  animation-play-state: paused;
}

input {
  height: 0;
  width: 0;
  border: none;
  outline: none;
}
Enter fullscreen mode Exit fullscreen mode

Why using random in pure CSS?

This way of randomizing has a few key advantages:

  1. it’s fun and whimsical.
  2. As a CSS developer, you don’t always have access to the JavaScript code and using this trick, you don’t have to.
  3. It’s not a well-known method, which means neither your teammates nor your users will understand what’s going on, users won’t be able to game this system as easily and as a bonus — you can drive other developers in your team crazy trying to debug it.

Top comments (0)