14 October 2025

An easy-to-follow guide on making an interactive Shake It game (code samples included)

Anton Diduh Content writer & Video content creator at Stripo
Rolenko Liubov Web Designer/HTML Coder at Stripo

Summarize

ChatGPT Perplexity

In this article, we'll show you in detail how to create an interactive game called Shake It. We'll break down the game creation process into AMP, kinetic, and fallback with all the necessary code samples for you to create your own game.

Remember those glass balls in toy stores, which, if you shake them, result in a whole snowstorm of small snowflakes inside? Little colorful worlds dedicated to any occasion or a festive. Now, imagine that on top of all this, these balls contain discounts and promo codes for your email newsletter subscribers. All that's left is to add the interactive game to your email.

We've created a simple guide that includes everything you need to easily add this game to your email.

How this game works

First, let's discuss how this game actually works and how you can apply it to your marketing strategies. At its core, it's a simple game where, when you press a button, an animation appears as if you've shaken the ball and snowflakes have started flying inside. 

After pressing the "Stop" button, one of several random results appears. The recipient can try shaking the ball again by pressing the "Try Again" button and stop it by pressing the "Stop" button. That's basically the whole game.

It looks cute and is easy to play, but it also brings a lot of changes to the way you run your email campaigns:

  • grant random discounts or promo codes to recipients for later use;
  • create seasonal promotions for your products, where each result the ball displays promotes a different brand or item;
  • raise overall engagement and bring a fun aspect to your emails, making them more interactive;
  • and more.

In this article, we will show you in detail how to create a full-fledged game that will include the following:

  • AMP version of the game;
  • Kinetic version, built with HTML5 and CSS3;
  • fallback version for email clients that do not support interactivity.

So, let's start our creation process.

AMP version

As we do with all of our interactive content, we start with an empty one-column structure in the template. Insert it, then select it and specify that it be included only in AMP HTML.

Once it's done, add the HTML block to it.

We've prepared a platform for our future game. Now, paste this code in your HTML block.

<style amp-custom>
    .shake-it-amp {
        text-align: center;
    }
 
    .shake-it-amp .snow-ball {
        display: flex;
        width: 220px;
        height: 220px;
        position: relative;
        justify-content: center;
        margin: 0 auto;
        border-radius: 50%;
        border: 6px solid #addbea;
        overflow: hidden;
        background-color: #d9eff6;
    }
 
    .shake-it-amp .glare {
        width: 100%;
        height: 100%;
        position: absolute;
    }
 
    .shake-it-amp .glare-1 {
        background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/glare1.png);
        background-repeat: no-repeat;
        background-position: 10px 10px;
        background-size: 62% 72%;
    }
 
    .shake-it-amp .glare-2 {
        background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/glare2.png);
        background-repeat: no-repeat;
        background-position: bottom center;
        background-size: 87% auto;
    }
 
    .shake-it-amp .anim {
        width: 100%;
        height: 100%;
        background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/merry_christmas_sticker.gif);
        background-repeat: no-repeat;
        background-position: center center;
        background-size: cover;
        position: absolute;
    }
 
    .shake-it-amp .result-img {
        width: 100%;
        height: 100%;
        background-repeat: no-repeat;
        background-position: center 55%;
        background-size: 60% auto;
        position: absolute;
    }
 
    .shake-it-amp .result-img-1 {
        background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/result2.png);
    }
 
    .shake-it-amp .result-img-2 {
        background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/result4.png);
    }
 
    .shake-it-amp .result-img-3 {
        background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/result3.png);
    }
 
    .shake-it-amp .bottom {
        width: 240px;
        height: 77px;
        position: relative;
        margin: -20px auto 20px;
        background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/bottom.png);
        background-repeat: no-repeat;
        background-position: top center;
        background-size: contain;
    }
 
    .shake-it-amp .btn {
        display: inline-block;
        background-color: #fff;
        border: 2px solid #329CA0;
        border-radius: 16px;
        color: #329CA0;
        cursor: pointer;
        font-size: 18px;
        line-height: 28px;
        padding: 4px 32px;
    }
 
    .shake-it-amp .btn:hover {
        color: #fff;
        background-color: #329CA0;
    }
 
    .shake-it-amp .result>div {
        padding-top: 10px;
    }
 
    .shake-it-amp .result h4 {
        text-align: center;
    }
</style>
<div class="shake-it-amp">
  <div class="snow-ball">
    <div class="anim"></div>
    <div class="glare glare-2"></div>
    <div class="result-img"></div>
    <div class="glare glare-1"></div>
  </div>
  <div class="bottom"></div>
  <p>
    <button class="btn">
      Start
    </button>
  </p>
  <p>
    <button class="btn">
      Stop
    </button>
  </p>
</div>

It will look like this. This piece of code contains an animated ball and "Start" and "Stop" buttons.

Styles part

An important part of the code is the styles needed to create the blue ball in the code piece you just pasted. These styles look like this:

This ball contains background blocks with images featuring:

  • animation (<div class="anim"></div>);
  • snow (<div class="glare glare-2"></div>);
  • glare (<div class="glare glare-1"></div>);
  • images that will be displayed at the end, along with the result (<div class="result-img"></div>).

Also, below the ball block is a block with an image of a stand <div class="bottom"></div>.

To make our ball look like the example, we use separate images that are linked in the code. Here is a list of all resource links with images used for this game, which you can also use to recreate this game yourself:

Glare

Snow mound at the bottom of the ball

Stand

Animation

Result images

Interactive part

Now, let's make the snow animation so that it only displays during the period between pressing the "Start" and "Stop" buttons. To do this, you need to add hidden [hidden]="!active" to the block with the anim class to turn this:

Into this:

Thus, the animation is hidden by default thanks to the hidden attribute and will appear after the value of the active variable changes. The value of the active variable changes when the "Start" and "Stop" buttons are clicked. But for this to work, you need to add this code to these buttons:

 <p>
    <button on="tap:AMP.setState({ active: true })" class="btn">
      Start
    </button>
  </p>
  <p>
    <button on="tap:AMP.setState({ active: false })" class="btn">
      Stop
    </button>
  </p>

Before adding, the code for the buttons looks like this:

Once added, they will look like this:

There are two important elements in this code:

  • on="tap:" is the "click" event handler;
  • AMP.setState({ }) is a special AMP syntax for creating variables. When the "Start" button is clicked, the active variable is set to true, and when the "Stop" button is clicked, it is set to false.

Now, let's implement game results and hide the extra buttons. According to the game logic, after pressing the "Stop" button, one of the three text blocks under the ball and an image in the ball are displayed. To bring this feature to life, add the following code at the very end of the game, before the </div> tag:

<div class="result">
    <div class="result-1">
      <h4 style="padding-bottom:5px;font-size:18px">
        You've scored some amazing discounts!
      </h4>
      <h4 style="padding-bottom:15px;font-size:18px">
        <b>15% OFF</b> on your next order.
      </h4>
      <h4 style="font-size:16px;padding-bottom:15px">
        Use the promo code <b>PRIZE1</b> on our <a href="https://stripo.email/" target="_blank" style="font-size:16px">website</a>.
      </h4>
      <p style="font-size:13px;padding-top:5px;padding-bottom:25px">
        Make sure to use your winnings soon! These discounts can be used together or on separate purchases, so enjoy the savings while they last!
      </p>
      <p>
        <button class="btn">
          Try again
        </button>
      </p>
    </div>
    <div class="result-2">
      <h4 style="font-size:18px;padding-bottom:5px">
        You've scored some amazing discounts!
      </h4>
      <h4 style="font-size:18px;padding-bottom:15px">
        <b>Up to 30% OFF</b> on select items.
      </h4>
      <h4 style="font-size:16px;padding-bottom:15px">
        Use the promo code <b>PRIZE2</b> on our <a href="https://stripo.email/" target="_blank" style="font-size:16px">website</a>.
      </h4>
      <p style="font-size:13px;padding-top:5px;padding-bottom:25px">
        Make sure to use your winnings soon! These discounts can be used together or on separate purchases, so enjoy the savings while they last!
      </p>
      <p>
        <button class="btn">
          Try again
        </button>
      </p>
    </div>
    <div class="result-3">
      <h4 style="font-size:18px;padding-bottom:5px">
        You've scored some amazing discounts!
      </h4>
      <h4 style="font-size:18px;padding-bottom:15px">
        <b>15% OFF</b> your next purchase.
      </h4>
      <h4 style="font-size:16px;padding-bottom:15px">
        Use the promo code <b>PRIZE3</b> on our <a href="https://stripo.email/" target="_blank" style="font-size:16px">website</a>.
      </h4>
      <p style="padding-bottom:25px;font-size:13px;padding-top:5px">
        Make sure to use your winnings soon! These discounts can be used together or on separate purchases, so enjoy the savings while they last!
      </p>
      <p>
        <button class="btn">
          Try again
        </button>
      </p>
    </div>
  </div>

This code has now created the necessary foundation, essentially introducing our results into the game. Now we need to make them random.

To display a random outcome, we need a new variable that will hold a random number from one to three, as there are three outcomes in our example. We also need to add display conditions for the "Stop" button.

To randomize the result, you need to add num to the existing entry for the "Stop" button: floor(random() * floor(3) + 1). To hide the button by default, add hidden [hidden]="num!=null" to the tag containing the button. To avoid the hassle of manually adding these small pieces in place, here's the code for a finished button with all the elements for randomizing results. Just replace your current "Stop" button with this code:

<p hidden [hidden]="num!=null">
    <button on="tap:AMP.setState({active: false, num: floor(random() * floor(3)+1)})" class="btn">
      Stop
    </button>
  </p>

The [hidden]="num!=null" entry means the button will be hidden while num is anything but null. When the email is opened, the variables haven't been defined yet, and num doesn't exist.

However, as soon as the recipient clicks the "Start" button (or any other button, if there is one), all variables are created and num is assigned the value null. Therefore, the "Stop" button is displayed after clicking the "Start" button. Then, when the "Stop" button itself is clicked, num is set to a value from one to three, and the button is hidden again.

Now we need to add display conditions for the "Start" button. The idea here is quite simple, as we'll use the start variable to hide the button after it's clicked. To do this, replace the current "Start" button code with this:

<p [hidden]="start">
    <button on="tap:AMP.setState({active: true, start: true})" class="btn">
      Start
    </button>
  </p>

For everything to work properly, we need to use the num variable. We need to add the condition hidden [hidden]="num != 1" to each result. But instead of the value "1," we substitute "1," "2," and "3," respectively.

To do this, change part of the code from this line:

To this one:

Using the code from here:

<div class="result">
    <div hidden [hidden]="num != 1" class="result-1">
      <h4 style="padding-bottom:5px;font-size:18px">
        You've scored some amazing discounts!
      </h4>
      <h4 style="padding-bottom:15px;font-size:18px">
        <b>15% OFF</b> on your next order.
      </h4>
      <h4 style="font-size:16px;padding-bottom:15px">
        Use the promo code <b>PRIZE1</b> on our <a href="https://stripo.email/" target="_blank" style="font-size:16px">website</a>.
      </h4>
      <p style="font-size:13px;padding-top:5px;padding-bottom:25px">
        Make sure to use your winnings soon! These discounts can be used together or on separate purchases, so enjoy the savings while they last!
      </p>
      <p>
        <button class="btn">
          Try again
        </button>
      </p>
    </div>
    <div hidden [hidden]="num != 2" class="result-2">
      <h4 style="font-size:18px;padding-bottom:5px">
        You've scored some amazing discounts!
      </h4>
      <h4 style="font-size:18px;padding-bottom:15px">
        <b>Up to 30% OFF</b> on select items.
      </h4>
      <h4 style="font-size:16px;padding-bottom:15px">
        Use the promo code <b>PRIZE2</b> on our <a href="https://stripo.email/" target="_blank" style="font-size:16px">website</a>.
      </h4>
      <p style="font-size:13px;padding-top:5px;padding-bottom:25px">
        Make sure to use your winnings soon! These discounts can be used together or on separate purchases, so enjoy the savings while they last!
      </p>
      <p>
        <button class="btn">
          Try again
        </button>
      </p>
    </div>
    <div hidden [hidden]="num != 3" class="result-3">
      <h4 style="font-size:18px;padding-bottom:5px">
        You've scored some amazing discounts!
      </h4>
      <h4 style="font-size:18px;padding-bottom:15px">
        <b>15% OFF</b> your next purchase.
      </h4>
      <h4 style="font-size:16px;padding-bottom:15px">
        Use the promo code <b>PRIZE3</b> on our <a href="https://stripo.email/" target="_blank" style="font-size:16px">website</a>.
      </h4>
      <p style="padding-bottom:25px;font-size:13px;padding-top:5px">
        Make sure to use your winnings soon! These discounts can be used together or on separate purchases, so enjoy the savings while they last!
      </p>
      <p>
        <button class="btn">
          Try again
        </button>
      </p>
    </div>
  </div>

Now, the results are already displayed as expected, but we need to make the image in the sphere change. We need to replace the block with the result-img class with the following code:

<div [class]="num == 1 ? 'result-img result-img-1' : num == 2 ? 'result-img result-img-2' : num == 3 ? 'result-img result-img-3' : 'result-img' " class="result-img"></div>

In the end, your result image line must look like this:

The idea is that depending on the num value, we add different classes to the result-img class: result-img-1, result-img-2, and so on. Each image has its own class, and they are all already defined in the styles section:

The last thing left to tweak is the "Try Again" buttons. The game mechanics work by not returning the recipient to the first screen with the "Start" button, but instead immediately launching the snow animation and displaying the "Stop" button.

To do this, you need to add the following code to all “Try Again” buttons (we have three of them):

<button on="tap:AMP.setState({ active: true,num: null})" class="btn">Try again</button>

 In the end, it all must look like this:

And it's done. To make sure that you did everything right, we leave the final code sample, so you can check it with your own creation.

Interactive game code

<style amp-custom>
  .shake-it-amp { text-align: center; } .shake-it-amp .snow-ball { display: flex; width: 220px; height: 220px; position: relative; justify-content: center; margin: 0 auto; border-radius: 50%; border: 6px solid #addbea; overflow: hidden; background-color: #d9eff6; } .shake-it-amp .glare { width: 100%; height: 100%; position: absolute; } .shake-it-amp .glare-1 { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/glare1.png); background-repeat: no-repeat; background-position: 10px 10px; background-size: 62% 72%; } .shake-it-amp .glare-2 { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/glare2.png); background-repeat: no-repeat; background-position: bottom center; background-size: 87% auto; } .shake-it-amp .anim { width: 100%; height: 100%; background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/merry_christmas_sticker.gif); background-repeat: no-repeat; background-position: center center; background-size: cover; position: absolute; } .shake-it-amp .result-img { width: 100%; height: 100%; background-repeat: no-repeat; background-position: center 55%; background-size: 60% auto; position: absolute; } .shake-it-amp .result-img-1 { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/result2.png); } .shake-it-amp .result-img-2 { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/result4.png); } .shake-it-amp .result-img-3 { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/result3.png); } .shake-it-amp .bottom { width: 240px; height: 77px; position: relative; margin: -20px auto 20px; background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/bottom.png); background-repeat: no-repeat; background-position: top center; background-size: contain; } .shake-it-amp .btn { display: inline-block; background-color: #fff; border: 2px solid #329CA0; border-radius: 16px; color: #329CA0; cursor: pointer; font-size: 18px; line-height: 28px; padding: 4px 32px; } .shake-it-amp .btn:hover { color: #fff; background-color: #329CA0; } .shake-it-amp .result>div { padding-top: 10px; } .shake-it-amp .result h4 { text-align: center; }
</style>
<div class="shake-it-amp esd-text">
  <div class="snow-ball">
    <div [hidden]="!active" hidden class="anim"></div>
    <div class="glare glare-2"></div>
    <div [class]="num == 1 ? &#39;result-img result-img-1&#39; : num == 2 ? &#39;result-img result-img-2&#39; : num == 3 ? &#39;result-img result-img-3&#39; : &#39;result-img&#39; " class="result-img"></div>
    <div class="glare glare-1"></div>
  </div>
  <div class="bottom"></div>
  <p [hidden]="start">
    <button on="tap:AMP.setState({active: true, start: true})" class="btn">
      Start
    </button>
  </p>
  <p [hidden]="num!=null" hidden>
    <button on="tap:AMP.setState({active: false, num: floor(random() * floor(3)+1)})" class="btn">
      Stop
    </button>
  </p>
  <div class="result">
    <div [hidden]="num != 1" hidden class="result-1">
      <h4 style="font-size:18px;padding-bottom:5px">
        You've scored some amazing discounts!
      </h4>
      <h4 style="font-size:18px;padding-bottom:15px">
        <b>15% OFF</b> on your next order.
      </h4>
      <h4 style="font-size:16px;padding-bottom:15px">
        Use the promo code <b>PRIZE1</b> on our <a href="https://stripo.email/" target="_blank" style="font-size:16px">website</a>.
      </h4>
      <p style="padding-bottom:25px;font-size:13px;padding-top:5px">
        Make sure to use your winnings soon! These discounts can be used together or on separate purchases, so enjoy the savings while they last!
      </p>
      <p>
        <button on="tap:AMP.setState({ active: true,num: null})" class="btn">
          Try again
        </button>
      </p>
    </div>
    <div [hidden]="num != 2" hidden class="result-2">
      <h4 style="padding-bottom:5px;font-size:18px">
        You've scored some amazing discounts!
      </h4>
      <h4 style="font-size:18px;padding-bottom:15px">
        <b>Up to 30% OFF</b> on select items.
      </h4>
      <h4 style="font-size:16px;padding-bottom:15px">
        Use the promo code <b>PRIZE2</b> on our <a href="https://stripo.email/" target="_blank" style="font-size:16px">website</a>.
      </h4>
      <p style="font-size:13px;padding-top:5px;padding-bottom:25px">
        Make sure to use your winnings soon! These discounts can be used together or on separate purchases, so enjoy the savings while they last!
      </p>
      <p>
        <button on="tap:AMP.setState({ active: true,num: null})" class="btn">
          Try again
        </button>
      </p>
    </div>
    <div [hidden]="num != 3" hidden class="result-3">
      <h4 style="font-size:18px;padding-bottom:5px">
        You've scored some amazing discounts!
      </h4>
      <h4 style="font-size:18px;padding-bottom:15px">
        <b>15% OFF</b> your next purchase.
      </h4>
      <h4 style="font-size:16px;padding-bottom:15px">
        Use the promo code <b>PRIZE3</b> on our <a href="https://stripo.email/" target="_blank" style="font-size:16px">website</a>.
      </h4>
      <p style="padding-bottom:25px;font-size:13px;padding-top:5px">
        Make sure to use your winnings soon! These discounts can be used together or on separate purchases, so enjoy the savings while they last!
      </p>
      <p>
        <button on="tap:AMP.setState({ active: true,num: null})" class="btn">
          Try again
        </button>
      </p>
    </div>
  </div>
</div>

Kinetic version built with HTML5 and CSS3

Now it's time to create a kinetic version of the game, also known as interactive HTML, built with HTML5 & CSS3. We start by adding another empty one-column structure. Select it, and pick an “Include in HTML only” option to make a foundation for our HTML game version.

This whole version is needed if recipients' email providers don't have AMP support yet, and thanks to specifications inside the code, they will see this version.

After that, we drop in this structure HTML block and paste the following code in this block:

<style>
  .shake-it-html { text-align: center; } .shake-it-html .snow-ball { display: flex; width: 220px; height: 220px; position: relative; justify-content: center; margin: 0 auto; border-radius: 50%; border: 6px solid #addbea; overflow: hidden; background-color: #d9eff6; } .shake-it-html .glare { width: 100%; height: 100%; position: absolute; } .shake-it-html .glare-1 { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/glare1.png); background-repeat: no-repeat; background-position: 10px 10px; background-size: 62% 72%; } .shake-it-html .glare-2 { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/glare2.png); background-repeat: no-repeat; background-position: bottom center; background-size: 87% auto; } .shake-it-html .anim { display: none; width: 100%; height: 100%; background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/merry_christmas_sticker.gif); background-repeat: no-repeat; background-position: center center; background-size: cover; position: absolute; } .shake-it-html .result-img { width: 100%; height: 100%; background-repeat: no-repeat; background-position: center 55%; background-size: 60% auto; position: absolute; } .shake-it-html .bottom { width: 240px; height: 77px; position: relative; margin: -20px auto 20px; background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/bottom.png); background-repeat: no-repeat; background-position: top center; background-size: contain; } .shake-it-html .btn { display: inline-block; background-color: #fff; border: 2px solid #329CA0; border-radius: 16px; color: #329CA0; cursor: pointer; font-size: 18px; line-height: 28px; padding: 4px 32px; } .shake-it-html .btn:hover { color: #fff; background-color: #329CA0; } .shake-it-html .result>div { display: none; padding-top: 10px; } .shake-it-html .result h4 { text-align: center; } .shake-it-html .stop-btn { display: none; } #start-input:checked~* .stop-btn-1 { display: block; } #start-input:checked~* .start-btn { display: none; } #start-input:checked~* .anim, #stop-input-1:checked~#again-input-1:checked~* .anim, #stop-input-2:checked~#again-input-2:checked~* .anim { display: block; } #stop-input-1:checked~* .anim, #stop-input-2:checked~* .anim, #stop-input-3:checked~* .anim { display: none; } #stop-input-1:checked~* .stop-btn-1, #stop-input-2:checked~* .stop-btn-2, #stop-input-3:checked~* .stop-btn-3 { display: none !important; } #stop-input-1:checked~* .result-1, #stop-input-2:checked~* .result-2, #stop-input-3:checked~* .result-3 { display: block; } #stop-input-1:checked~* .result-img { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/result2.png); } #stop-input-2:checked~#again-input-1:checked~* .result-img { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/result4.png); } #stop-input-3:checked~#again-input-2:checked~* .result-img { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/result3.png); } #again-input-1:checked~* .result-img, #stop-input-2:checked~#again-input-2:checked~* .result-img { background-image: none } #again-input-1:checked~* .result-1, #again-input-2:checked~* .result-2 { display: none; } #again-input-1:checked~* .stop-btn-2, #again-input-2:checked~* .stop-btn-3 { display: block; } #again-input-1:checked~* .stop-btn-1, #again-input-2:checked~* .stop-btn-2 { display: none !important; }
</style>
<div class="shake-it-html">
  <input type="radio" name="start" id="start-input" style="display:none">
  <input id="stop-input-1" type="radio" name="stop" style="display:none">
  <input id="stop-input-2" type="radio" name="stop" style="display:none">
  <input name="stop" id="stop-input-3" type="radio" style="display:none">
  <input id="again-input-1" type="checkbox" name="again" style="display:none">
  <input id="again-input-2" type="checkbox" name="again" style="display:none">
  <div>
    <div class="snow-ball">
      <div class="anim"></div>
      <div class="glare glare-2"></div>
      <div class="result-img"></div>
      <div class="glare glare-1"></div>
    </div>
    <div class="bottom"></div>
    <div class="result">
      <div class="result-1">
        <h4 style="padding-bottom:5px;font-size:18px">
          You've scored some amazing discounts!
        </h4>
        <h4 style="padding-bottom:15px;font-size:18px">
          <b>15% OFF</b> on your next order.
        </h4>
        <h4 style="font-size:16px;padding-bottom:15px">
          Use the promo code <b>PRIZE1</b> on our <a href="https://stripo.email/" target="_blank" style="font-size:16px">website</a>.
        </h4>
        <p style="padding-top:5px;padding-bottom:25px;font-size:13px">
          Make sure to use your winnings soon! These discounts can be used together or on separate purchases, so enjoy the savings while they last!
        </p>
        <p>
          <label for="again-input-1" class="btn">
            Try again
          </label>
        </p>
      </div>
      <div class="result-2">
        <h4 style="font-size:18px;padding-bottom:5px">
          You've scored some amazing discounts!
        </h4>
        <h4 style="font-size:18px;padding-bottom:15px">
          <b>Up to 30% OFF</b> on select items.
        </h4>
        <h4 style="padding-bottom:15px;font-size:16px">
          Use the promo code <b>PRIZE2</b> on our <a target="_blank" href="https://stripo.email/" style="font-size:16px">website</a>.
        </h4>
        <p style="font-size:13px;padding-top:5px;padding-bottom:25px">
          Make sure to use your winnings soon! These discounts can be used together or on separate purchases, so enjoy the savings while they last!
        </p>
        <p>
          <label for="again-input-2" class="btn">
            Try again
          </label>
        </p>
      </div>
      <div class="result-3">
        <h4 style="padding-bottom:5px;font-size:18px">
          You've scored some amazing discounts!
        </h4>
        <h4 style="font-size:18px;padding-bottom:15px">
          <b>15% OFF</b> your next purchase.
        </h4>
        <h4 style="font-size:16px;padding-bottom:15px">
          Use the promo code <b>PRIZE3</b> on our <a href="https://stripo.email/" target="_blank" style="font-size:16px">website</a>.
        </h4>
        <p style="padding-top:5px;padding-bottom:25px;font-size:13px">
          Make sure to use your winnings soon! These discounts can be used together or on separate purchases, so enjoy the savings while they last!
        </p>
      </div>
    </div>
    <p class="start-btn">
      <label for="start-input" class="btn">
        Start
      </label>
    </p>
    <p class="stop-btn stop-btn-1">
      <label for="stop-input-1" class="btn">
        Stop
      </label>
    </p>
    <p class="stop-btn stop-btn-2">
      <label for="stop-input-2" class="btn">
        Stop
      </label>
    </p>
    <p class="stop-btn stop-btn-3">
      <label for="stop-input-3" class="btn">
        Stop
      </label>
    </p>
  </div>
</div>

The HTML version has a similar structure, but all interactivity is achieved using input tags and their associated labels. In this version, we can't use random number generation, so we added multiple "Stop" buttons to display all messages sequentially.

The example has three different messages, so the code contains three "Stop" buttons. Instead of button tags, we insert label tags and link them to specific inputs using the for="" attribute. This attribute specifies the ID of the associated input tag.

As a result, we have one "Start" button and three "Stop" buttons, each differing only in the numbers "1," "2," and "3."

The necessary button inputs are placed at the very beginning of the code.

Very important. Don't move them or delete the <div> tag that follows them. This is because the styles use the CSS selector "~," which is tightly bound to the code structure, and if the layout changes, the game can stop working.

Styles part

Now, let's cover the styles section. All "Stop" buttons are hidden from the recipient by default. After pressing the "Start" button, the game displays the first "Stop" button and hides the "Start" button itself.

The styles also indicate that after clicking each of the “Stop” buttons, it should be hidden.

The next thing worth mentioning is the "Try Again" buttons. If the recipient presses the first "Try Again" button, the game displays a second "Stop" button to get a second result. After the second press, a third button appears, and so on.

Now, let's talk about the styles for the snow animation. The animation is displayed after the recipient clicks the "Start" button, and then after they click the "Try Again" button. It stops after they click the "Stop" button.

Since all the "Stop" buttons in our example are radio buttons, they are only clicked once and remain pressed. Therefore, we specify both the "Stop" button ID and the "Try Again" button ID to display the animation a second and third time. The same applies to the images below.

The final step is displaying the results and their images. Depending on which “Stop” button the recipient presses (first, second, or third), they will see the corresponding result and image.

Fallback version

For email clients that don't support HTML5 and CSS3 or AMP, you need to create an additional block with code. The fallback version will be shown automatically if the recipient's email provider does not support both AMP and HTML5 and CSS3.

It will have a design similar to our mechanics but without interactivity. Clicking on the elements will lead to the web version of the email. In this case, the fallback version for this game will include an image of our ball only.

We continue to work on the block with interactive HTML, which we made above. Paste the following code between the </style> and <div class="shake-it-html"> tags:

 
<!--[if !mso]><!-- -->
<input id="fallback_ctrl" checked type="checkbox" class="fallback_ctrl" style="display:none !important;mso-hide:all">
<!--<![endif]-->
<!-- FALLBACK -->
<span id="fallback" class="fallback">
  <table width="100%">
    <tbody>
      <tr align="center">
        <td>
          <a href="https://viewstripo.email/06b655e9-2a43-4b23-b7f4-81b26be124d21743755097686?type=amphtml" target="_blank"><img width="240" height="294" src="https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/snowbal.png" alt="" style="display:inline-block"></a>
        </td>
      </tr>
    </tbody>
  </table>
</span>
<!-- /FALLBACK -->
<!--[if !mso]><!-- -->
<!-- INTERACTIVE ELEMENT -->
<div class="container" style="display:none;mso-hide:all">

Additionally, at the end of the entire code, you also need to insert this small piece of code:

</div><!-- /INTERACTIVE ELEMENT -->
<!--<![endif]-->

If you want to replace the link with your own and change the image, you can insert new links here:

Now we need to add styles to display only the version appropriate for the email client. The styles should be added to the style tag at the very end.

    /* --- */
    @media screen and (-webkit-min-device-pixel-ratio: 0) {
        input.fallback_ctrl:checked~.container {
            display: block !important;
        }
 
        input.fallback_ctrl:checked~#fallback {
            display: none !important;
        }
    }
 
    [owa] .container {
        display: none !important;
    }
 
    [class~="x_container"] {
        display: none !important;
    }
 
    [id~="x_fallback"] {
        display: block !important;
    }
 
    @media screen and (max-width: 600px) {
        body[data-outlook-cycle] #fallback {
            display: block !important;
        }
 
        body[data-outlook-cycle] .container {
            display: none !important;
        }
    }

There is an important piece of code in the fallback version:

<!--[if !mso]><!--><input type="checkbox" id="fallback_ctrl" class="fallback_ctrl" style="display:none !important;mso-hide:all;" checked>

<!--<![endif]-->

This input is used to show or hide the fallback using styles. It's in the comments <!--[if !mso]><!--><!--<![endif]--> to ensure it's hidden in the Outlook Desktop client.

Also worth noting is the <span id="fallback" class="fallback"></span> block, which contains all of our fallback layout. It should have a simple, tabular layout suitable for Outlook. In our example, it's a table with links to the web version. You can create your own layout; just make sure it's understandable for Outlook.

The styles below are used to hide and show the fallback version. If you remove them or comment them out, the fallback version will be visible, and you can customize its design. But don't forget to re-enable these styles before sending the email.

These styles don't have clear rules for each email client, but there is a set of hacks that can be used to control the display:

  • styles that start with [owa] are used for Outlook;
  • the [class~="x_container"] styles are needed for Outlook in case [owa] does not work;
  • body[data-outlook-cycle] styles are needed for Outlook on iOS and Android mobile devices;
  • mso-hide:all; is used for Outlook.com.

The full code

Here is the full code of the game, including the interactive HTML part and the fallback version:

<style>
  .shake-it-html { text-align: center; } .shake-it-html .snow-ball { display: flex; width: 220px; height: 220px; position: relative; justify-content: center; margin: 0 auto; border-radius: 50%; border: 6px solid #addbea; overflow: hidden; background-color: #d9eff6; } .shake-it-html .glare { width: 100%; height: 100%; position: absolute; } .shake-it-html .glare-1 { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/glare1.png); background-repeat: no-repeat; background-position: 10px 10px; background-size: 62% 72%; } .shake-it-html .glare-2 { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/glare2.png); background-repeat: no-repeat; background-position: bottom center; background-size: 87% auto; } .shake-it-html .anim { display: none; width: 100%; height: 100%; background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/merry_christmas_sticker.gif); background-repeat: no-repeat; background-position: center center; background-size: cover; position: absolute; } .shake-it-html .result-img { width: 100%; height: 100%; background-repeat: no-repeat; background-position: center 55%; background-size: 60% auto; position: absolute; } .shake-it-html .bottom { width: 240px; height: 77px; position: relative; margin: -20px auto 20px; background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/bottom.png); background-repeat: no-repeat; background-position: top center; background-size: contain; } .shake-it-html .btn { display: inline-block; background-color: #fff; border: 2px solid #329CA0; border-radius: 16px; color: #329CA0; cursor: pointer; font-size: 18px; line-height: 28px; padding: 4px 32px; } .shake-it-html .btn:hover { color: #fff; background-color: #329CA0; } .shake-it-html .result>div { display: none; padding-top: 10px; } .shake-it-html .result h4 { text-align: center; } .shake-it-html .stop-btn { display: none; } #start-input:checked~* .stop-btn-1 { display: block; } #start-input:checked~* .start-btn { display: none; } #start-input:checked~* .anim, #stop-input-1:checked~#again-input-1:checked~* .anim, #stop-input-2:checked~#again-input-2:checked~* .anim { display: block; } #stop-input-1:checked~* .anim, #stop-input-2:checked~* .anim, #stop-input-3:checked~* .anim { display: none; } #stop-input-1:checked~* .stop-btn-1, #stop-input-2:checked~* .stop-btn-2, #stop-input-3:checked~* .stop-btn-3 { display: none !important; } #stop-input-1:checked~* .result-1, #stop-input-2:checked~* .result-2, #stop-input-3:checked~* .result-3 { display: block; } #stop-input-1:checked~* .result-img { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/result2.png); } #stop-input-2:checked~#again-input-1:checked~* .result-img { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/result4.png); } #stop-input-3:checked~#again-input-2:checked~* .result-img { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/result3.png); } #again-input-1:checked~* .result-img, #stop-input-2:checked~#again-input-2:checked~* .result-img { background-image: none } #again-input-1:checked~* .result-1, #again-input-2:checked~* .result-2 { display: none; } #again-input-1:checked~* .stop-btn-2, #again-input-2:checked~* .stop-btn-3 { display: block; } #again-input-1:checked~* .stop-btn-1, #again-input-2:checked~* .stop-btn-2 { display: none !important; } /* --- */ @media screen and (-webkit-min-device-pixel-ratio: 0) { input.fallback_ctrl:checked~.container { display: block !important; } input.fallback_ctrl:checked~#fallback { display: none !important; } } [owa] .container { display: none !important; } [class~="x_container"] { display: none !important; } [id~="x_fallback"] { display: block !important; } @media screen and (max-width: 600px) { body[data-outlook-cycle] #fallback { display: block !important; } body[data-outlook-cycle] .container { display: none !important; } }
</style>
<!--[if !mso]><!-- -->
<input id="fallback_ctrl" checked type="checkbox" class="fallback_ctrl" style="display:none !important;mso-hide:all">
<!--<![endif]-->
<!-- FALLBACK -->
<span id="fallback" class="fallback">
  <table width="100%">
    <tbody>
      <tr align="center">
        <td>
          <a href="https://viewstripo.email/06b655e9-2a43-4b23-b7f4-81b26be124d21743755097686?type=amphtml" target="_blank"><img width="240" height="294" src="https://zlnfb.stripocdn.email/content/guids/CABINET_3e19ffbc5b2e2d74f6037307a61d4cf638352ccb6c591a9cb61b34a551a21f55/images/snowbal.png" alt="" style="display:inline-block"></a>
        </td>
      </tr>
    </tbody>
  </table>
</span>
<!-- /FALLBACK -->
<!--[if !mso]><!-- -->
<!-- INTERACTIVE ELEMENT -->
<div class="container" style="display:none;mso-hide:all">
  <div class="shake-it-html">
    <input type="radio" name="start" id="start-input" style="display:none">
    <input id="stop-input-1" type="radio" name="stop" style="display:none">
    <input id="stop-input-2" type="radio" name="stop" style="display:none">
    <input name="stop" id="stop-input-3" type="radio" style="display:none">
    <input id="again-input-1" type="checkbox" name="again" style="display:none">
    <input id="again-input-2" type="checkbox" name="again" style="display:none">
    <div>
      <div class="snow-ball">
        <div class="anim"></div>
        <div class="glare glare-2"></div>
        <div class="result-img"></div>
        <div class="glare glare-1"></div>
      </div>
      <div class="bottom"></div>
      <div class="result">
        <div class="result-1">
          <h4 style="padding-bottom:5px;font-size:18px">
            You've scored some amazing discounts!
          </h4>
          <h4 style="padding-bottom:15px;font-size:18px">
            <b>15% OFF</b> on your next order.
          </h4>
          <h4 style="font-size:16px;padding-bottom:15px">
            Use the promo code <b>PRIZE1</b> on our <a href="https://stripo.email/" target="_blank" style="font-size:16px">website</a>.
          </h4>
          <p style="padding-top:5px;padding-bottom:25px;font-size:13px">
            Make sure to use your winnings soon! These discounts can be used together or on separate purchases, so enjoy the savings while they last!
          </p>
          <p>
            <label for="again-input-1" class="btn">
              Try again
            </label>
          </p>
        </div>
        <div class="result-2">
          <h4 style="font-size:18px;padding-bottom:5px">
            You've scored some amazing discounts!
          </h4>
          <h4 style="font-size:18px;padding-bottom:15px">
            <b>Up to 30% OFF</b> on select items.
          </h4>
          <h4 style="padding-bottom:15px;font-size:16px">
            Use the promo code <b>PRIZE2</b> on our <a target="_blank" href="https://stripo.email/" style="font-size:16px">website</a>.
          </h4>
          <p style="font-size:13px;padding-top:5px;padding-bottom:25px">
            Make sure to use your winnings soon! These discounts can be used together or on separate purchases, so enjoy the savings while they last!
          </p>
          <p>
            <label for="again-input-2" class="btn">
              Try again
            </label>
          </p>
        </div>
        <div class="result-3">
          <h4 style="padding-bottom:5px;font-size:18px">
            You've scored some amazing discounts!
          </h4>
          <h4 style="font-size:18px;padding-bottom:15px">
            <b>15% OFF</b> your next purchase.
          </h4>
          <h4 style="font-size:16px;padding-bottom:15px">
            Use the promo code <b>PRIZE3</b> on our <a href="https://stripo.email/" target="_blank" style="font-size:16px">website</a>.
          </h4>
          <p style="padding-top:5px;padding-bottom:25px;font-size:13px">
            Make sure to use your winnings soon! These discounts can be used together or on separate purchases, so enjoy the savings while they last!
          </p>
        </div>
      </div>
      <p class="start-btn">
        <label for="start-input" class="btn">
          Start
        </label>
      </p>
      <p class="stop-btn stop-btn-1">
        <label for="stop-input-1" class="btn">
          Stop
        </label>
      </p>
      <p class="stop-btn stop-btn-2">
        <label for="stop-input-2" class="btn">
          Stop
        </label>
      </p>
      <p class="stop-btn stop-btn-3">
        <label for="stop-input-3" class="btn">
          Stop
        </label>
      </p>
    </div>
  </div>
</div>
<!-- /INTERACTIVE ELEMENT -->
<!--<![endif]-->

Wrapping up

And that's pretty much it. Now you have a simple interactive game that can bring a sense of surprise and more engagement to your email newsletters, reaching all your audience, regardless of which email service they prefer. Use it, customize it, and upgrade your emails with interactivity to stand out from the competition and give your recipients an unforgettable experience.

Create exceptional emails with Stripo