An easy-to-follow guide on making an interactive Guess the Picture game (code samples included)
Summarize
It's time for a guessing game, and we've prepared something interesting. Can you guess the object in the picture, given only a small part of it? Or perhaps you'd like to delegate this task to your recipients? Either way, you won't have to guess how to make such a game, as, in this article, we'll show you how to make an interactive Guess the Picture game. Let’s get started.
How this game works
The game itself is quite simple and resembles a short step-by-step quiz. There are three pictures, and you need to guess what they depict one by one by choosing from the options provided. You're only shown a partial image to make guessing more challenging. Once you answer correctly (or incorrectly), you'll see the full image, and the game will move on to the next picture. If guessing is difficult, there's a separate "show me more" button, which acts as a hint and reveals a slightly larger section of the picture. Once three pictures are correctly guessed, the game will display the final screen with a reward.
This simple game allows you to make your emails more unique by:
- creating riddles with images that can tease your new products, events, or promo campaigns;
- dedicating games to special occasions or milestones, allowing recipients to have fun with your emails during this period;
- providing promo codes, discounts, and other gifts to your audience through a gamified approach.
Different inboxes support different interactive technologies, so to reach as many recipients as possible, one email needs to include several versions of the same game working together.
In this guide, we show how this full email is built and how its parts work together, including:
- an AMP version of the game;
- a kinetic version built with HTML5 and CSS3;
- a fallback version for recipients whose email clients don’t support interactivity.
The HTML version contains the kinetic (HTML5 and CSS3) version, which serves as the main version and will be shown when the email client supports HTML5 and CSS3, with a fallback for subscribers whose email clients don’t support kinetic content. The AMP version will be shown if the recipient’s email client supports AMP; it will override the HTML version.
AMP version
Let’s start creating our game with the AMP version. Add a one-column structure as a foundation for your future game. Select it and then set the “Include in” option to “AMP HTML” only, so it’s visible only in AMP HTML.
After that, add an HTML block into this structure and paste this code.
<style amp-custom>
.guess-image-amp .screen { text-align: center; display: flex; justify-content: space-between; align-items: flex-start; } .guess-image-amp .image { width: 260px; height: 260px; background-repeat: no-repeat; background-position: bottom center; border: 1px solid gray; background-size: 200%; transition-duration: 4s; } .guess-image-amp .image-1 { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_ad2d67391b1b95bc58fac20025cf77e63639e7f01ffe4d48b1d3d16c225076c0/images/img01.jpg) } .guess-image-amp .image-2 { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_ad2d67391b1b95bc58fac20025cf77e63639e7f01ffe4d48b1d3d16c225076c0/images/img02.png) } .guess-image-amp .image-3 { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_ad2d67391b1b95bc58fac20025cf77e63639e7f01ffe4d48b1d3d16c225076c0/images/img03.png) } .guess-image-amp .anim { background-size: 105%; } .guess-image-amp .anim2 { background-size: 155%; } .guess-image-amp .show-all { background-size: 95%; transition-duration: .5s; } .guess-image-amp .buttons { width: 50%; } .guess-image-amp .btn { display: inline-block; background: none; border: 0; outline: 0; font-size: 16px; padding: 8px; cursor: pointer; font-weight: bold; } .guess-image-amp .btn:hover, .guess-image-amp .btn-bg:hover { opacity: 0.8; } .guess-image-amp .btn-bg { display: inline-block; margin-top: 15px; font-size: 14px; padding: 5px 10px; cursor: pointer; background-color: #efefef; border: 1px solid #cccccc; color: #000000; } .guess-image-amp .btn-more { margin-top: 15px; font-size: 14px; padding: 5px 10px; cursor: pointer; } .guess-image-amp .result { padding: 15px 0; } .guess-image-amp .result p { font-size: 16px; } .guess-image-amp .finish-text { padding: 10px 0; } @media only screen and (max-width: 600px) { .guess-image-amp .screen { display: block; } .guess-image-amp .buttons { width: 100%; } .guess-image-amp .image { margin: 0 auto; } }
</style>
<div class="guess-image-amp">
<h2 style="padding-bottom:20px">
What is it?
</h2>
<div class="screen-1 screen">
<div id="image-1" class="image image-1"></div>
<div class="buttons">
<div>
<p>
<button type="button" class="btn">
A lamp
</button>
</p>
<p>
<button type="button" class="btn">
A table
</button>
</p>
<p>
<button type="button" class="btn">
A vase
</button>
</p>
<p>
<button type="button" class="btn-bg">
I don't know, show me more.
</button>
</p>
</div>
<div class="result result-true">
<p style="color:green">
You are right!
</p>
<p>
<button type="button" class="btn-bg">
Next
</button>
</p>
</div>
<div class="result result-false">
<p style="color:red">
No. It is a vase.
</p>
<p>
<button type="button" class="btn-bg">
Next
</button>
</p>
</div>
</div>
</div>
<div class="screen-4 screen">
<div class="finish-text">
<h2 style="padding-bottom:15px">
Congratulations! 🎉
</h2>
<p style="padding-bottom:10px">
You've earned a <b>15%</b> discount on your next purchase. Enjoy your reward and thank you for playing!
</p>
<p style="padding-bottom:10px">
Use the code <b>WIN15</b> at checkout to claim your discount.
</p>
</div>
</div>
</div>
You’ll see a basic structure. The game consists of three steps, but right now we only have the first step and the final message. We'll analyze the first step in detail and then add the rest.
The first step is to make the answer buttons work. To do this, add the following code to the incorrect answers:
on="tap:AMP.setState({result1: 0}),image-1.toggleClass(class='show-all', force=true)"
Then add the following code to the correct answer:
on="tap:AMP.setState({result1: 1}),image-1.toggleClass(class='show-all', force=true)"
Paste the codes inside the angle brackets highlighted below after the button tag.
There are several important elements in this code:
- on="tap:" is the "click" event handler;
- AMP.setState({ })" is a special AMP syntax for creating variables;
- result1 is a variable into which we assign the values 0 if the answer is incorrect or 1 if it’s correct;
- image-1.toggleClass(class='show-all', force=true) means that the element with the ID image-1 (the container containing the image) is given the class "show-all" to show the full image (the number 1 indicates that this is the image in the first riddle).
The div block containing responses needs to be updated with this code:
[hidden]="result1 != null."
This will hide it when the result1 variable is set to anything other than null. This happens after clicking on any answer (the code is described above).
Next, add the following attributes to the “I don't know, show me more” button:
[hidden]="anim1 == 1" on="tap:AMP.setState({anim1: 1})"
These attributes include:
- [hidden]="anim1 == 1", which hides the button as soon as the variable equals 1, in our case, after clicking it;
- anim1, which is needed not only to hide the button itself but also to add an animation class to the image (the number 1 indicates that this variable is used in the first riddle).
As a result, the entire block will look like this:
<div [hidden]="result1 != null">
<p>
<button on="tap:AMP.setState({result1: 0}),image-1.toggleClass(class='show-all', force=true)" type="button" class="btn">
A lamp
</button>
</p>
<p>
<button on="tap:AMP.setState({result1: 0}),image-1.toggleClass(class='show-all', force=true)" type="button" class="btn">
A table
</button>
</p>
<p>
<button on="tap:AMP.setState({result1: 1}),image-1.toggleClass(class='show-all', force=true)" type="button" class="btn">
A vase
</button>
</p>
<p>
<button [hidden]="anim1 == 1" type="button" on="tap:AMP.setState({anim1: 1})" class="btn-bg">
I don't know, show me more.
</button>
</p>
</div>
Next, we need to add animation to the image. The block with id="image-1" requires these attributes:
[class]="anim1 == 1 ? 'image image-1 anim' : 'image image-1'"
So, the whole line will look like this:
<div id="image-1" [class]="anim1 == 1 ? 'image image-1 anim' : 'image image-1'" class="image image-1"></div>
The styles for animating the image are already in the code and look like this:
Next, we move on to the block with the result class. We have two results: one for the correct answer (the result-true class) and one for the incorrect answer (the result-false class).
The block with the result-true class requires [hidden]="result1 != 1", while the result-false block requires hidden [hidden]="result1 != 0". Here, the hidden attribute hides these blocks by default, and the [hidden] attribute specifies the display conditions. If the result1 variable is 1, the correct answer message will be shown; if 0, the incorrect answer message will be shown. These variables are set when clicking on the answer options.
These blocks also contain "Next" buttons, which display the next riddle. For this to work as intended, you need to add on="tap:AMP.setState({screen:1})". Here, the screen variable is set to the riddle number this button refers to; in this example, it's the first riddle.
After all the changes, both blocks look like this:
<div hidden [hidden]="result1 != 1" class="result result-true">
<p style="color:green">
You are right!
</p>
<p>
<button on="tap:AMP.setState({screen:1})" type="button" class="btn-bg">
Next
</button>
</p>
</div>
<div hidden [hidden]="result1 != 0" class="result result-false">
<p style="color:red">
No. It is a vase.
</p>
<p>
<button type="button" on="tap:AMP.setState({screen:1})" class="btn-bg">
Next
</button>
</p>
</div>
After this, you need to add this code to the block with the screen-1 class to hide the first step (paste the code after the div tag):
[hidden]="screen >=1"
The block with the first riddle is ready. The next two blocks are created in the same way. But to save time, simply insert the following code before the final message:
<div hidden [hidden]="screen !=1" class="screen-2 screen">
<div [class]="anim2 == 1 ? 'image image-2 anim2' : 'image image-2'" id="image-2" class="image image-2"></div>
<div class="buttons">
<div [hidden]="result2 != null">
<p>
<button on="tap:AMP.setState({result2: 0}),image-2.toggleClass(class='show-all', force=true)" type="button" class="btn">
A table
</button>
</p>
<p>
<button type="button" on="tap:AMP.setState({result2: 1}),image-2.toggleClass(class='show-all', force=true)" class="btn">
A lamp
</button>
</p>
<p>
<button type="button" on="tap:AMP.setState({result2: 0}),image-2.toggleClass(class='show-all', force=true)" class="btn">
An easel
</button>
</p>
<p>
<button [hidden]="anim2 == 1" type="button" on="tap:AMP.setState({anim2: 1})" class="btn-bg">
I don't know, show me more.
</button>
</p>
</div>
<div hidden [hidden]="result2 != 1" class="result result-true">
<p style="color:green">
You are right!
</p>
<p>
<button type="button" on="tap:AMP.setState({screen:2})" class="btn-bg">
Next
</button>
</p>
</div>
<div [hidden]="result2 != 0" hidden class="result result-false">
<p style="color:red">
No. It is a lamp.
</p>
<p>
<button on="tap:AMP.setState({screen:2})" type="button" class="btn-bg">
Next
</button>
</p>
</div>
</div>
</div>
<div [hidden]="screen !=2" hidden class="screen-3 screen">
<div id="image-3" [class]="anim3 == 1 ? 'image image-3 anim2' : 'image image-3'" class="image image-3"></div>
<div class="buttons">
<div [hidden]="result3 != null">
<p>
<button type="button" on="tap:AMP.setState({result3: 0}),image-3.toggleClass(class='show-all', force=true)" class="btn">
A sofa
</button>
</p>
<p>
<button type="button" on="tap:AMP.setState({result3: 1}),image-3.toggleClass(class='show-all', force=true)" class="btn">
An armchair
</button>
</p>
<p>
<button type="button" on="tap:AMP.setState({result3: 0}),image-3.toggleClass(class='show-all', force=true)" class="btn">
A table
</button>
</p>
<p>
<button [hidden]="anim3 == 1" type="button" on="tap:AMP.setState({anim3: 1})" class="btn-bg">
I don't know, show me more.
</button>
</p>
</div>
<div hidden [hidden]="result3 != 1" class="result result-true">
<p style="color:green">
You are right!
</p>
<p>
<button type="button" on="tap:AMP.setState({screen:3})" class="btn-bg">
Done
</button>
</p>
</div>
<div hidden [hidden]="result3 != 0" class="result result-false">
<p style="color:red">
No. It is an armchair.
</p>
<p>
<button type="button" on="tap:AMP.setState({screen:3})" class="btn-bg">
Done
</button>
</p>
</div>
</div>
</div>
The last thing we need to do is add the display conditions for the end-of-game message. Add the following attributes to the block with the "screen-4" class:
hidden [hidden]="screen <3"
There are three riddles in our game, so we hide the block until the screen variable equals 3.
The last thing we need to do is change the "What is it?" title at the very beginning of the game. It also needs to have the [hidden] attribute added to it, so it's hidden after the game ends:
<h2 [hidden]="screen >=3" style="padding-bottom: 20px">
What is it?
</h2>
If you want to change the images for the riddle, replace these links with your own.
Changing texts is also simple, as all you need to do is replace them here with your own copy.
The same goes for the final message.
This completes the creation of the AMP version. Here is the full AMP version code so that you can check whether you have done everything correctly according to the guide:
<style amp-custom>
.guess-image-amp .screen { text-align: center; display: flex; justify-content: space-between; align-items: flex-start; } .guess-image-amp .image { width: 260px; height: 260px; background-repeat: no-repeat; background-position: bottom center; border: 1px solid gray; background-size: 200%; transition-duration: 4s; } .guess-image-amp .image-1 { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_ad2d67391b1b95bc58fac20025cf77e63639e7f01ffe4d48b1d3d16c225076c0/images/img01.jpg) } .guess-image-amp .image-2 { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_ad2d67391b1b95bc58fac20025cf77e63639e7f01ffe4d48b1d3d16c225076c0/images/img02.png) } .guess-image-amp .image-3 { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_ad2d67391b1b95bc58fac20025cf77e63639e7f01ffe4d48b1d3d16c225076c0/images/img03.png) } .guess-image-amp .anim { background-size: 105%; } .guess-image-amp .anim2 { background-size: 155%; } .guess-image-amp .show-all { background-size: 95%; transition-duration: .5s; } .guess-image-amp .buttons { width: 50%; } .guess-image-amp .btn { display: inline-block; background: none; border: 0; outline: 0; font-size: 16px; padding: 8px; cursor: pointer; font-weight: bold; } .guess-image-amp .btn:hover, .guess-image-amp .btn-bg:hover { opacity: 0.8; } .guess-image-amp .btn-bg { display: inline-block; margin-top: 15px; font-size: 14px; padding: 5px 10px; cursor: pointer; background-color: #efefef; border: 1px solid #cccccc; color: #000000; } .guess-image-amp .btn-more { margin-top: 15px; font-size: 14px; padding: 5px 10px; cursor: pointer; } .guess-image-amp .result { padding: 15px 0; } .guess-image-amp .result p { font-size: 16px; } .guess-image-amp .finish-text { padding: 10px 0; } @media only screen and (max-width: 600px) { .guess-image-amp .screen { display: block; } .guess-image-amp .buttons { width: 100%; } .guess-image-amp .image { margin: 0 auto; } }
</style>
<div class="guess-image-amp">
<h2 [hidden]="screen >=3" style="padding-bottom: 20px">
What is it?
</h2>
<div class="screen-1 screen" [hidden]="screen >=1">
<div id="image-1" [class]="anim1 == 1 ? 'image image-1 anim' : 'image image-1'" class="image image-1"></div>
<div class="buttons">
<div [hidden]="result1 != null">
<p>
<button on="tap:AMP.setState({result1: 0}),image-1.toggleClass(class='show-all', force=true)" type="button" class="btn">
A lamp
</button>
</p>
<p>
<button on="tap:AMP.setState({result1: 0}),image-1.toggleClass(class='show-all', force=true)" type="button" class="btn">
A table
</button>
</p>
<p>
<button on="tap:AMP.setState({result1: 1}),image-1.toggleClass(class='show-all', force=true)" type="button" class="btn">
A vase
</button>
</p>
<p>
<button [hidden]="anim1 == 1" type="button" on="tap:AMP.setState({anim1: 1})" class="btn-bg">
I don't know, show me more.
</button>
</p>
</div>
<div hidden [hidden]="result1 != 1" class="result result-true">
<p style="color:green">
You are right!
</p>
<p>
<button on="tap:AMP.setState({screen:1})" type="button" class="btn-bg">
Next
</button>
</p>
</div>
<div hidden [hidden]="result1 != 0" class="result result-false">
<p style="color:red">
No. It is a vase.
</p>
<p>
<button type="button" on="tap:AMP.setState({screen:1})" class="btn-bg">
Next
</button>
</p>
</div>
</div>
</div>
<div hidden [hidden]="screen !=1" class="screen-2 screen">
<div [class]="anim2 == 1 ? 'image image-2 anim2' : 'image image-2'" id="image-2" class="image image-2"></div>
<div class="buttons">
<div [hidden]="result2 != null">
<p>
<button on="tap:AMP.setState({result2: 0}),image-2.toggleClass(class='show-all', force=true)" type="button" class="btn">
A table
</button>
</p>
<p>
<button type="button" on="tap:AMP.setState({result2: 1}),image-2.toggleClass(class='show-all', force=true)" class="btn">
A lamp
</button>
</p>
<p>
<button type="button" on="tap:AMP.setState({result2: 0}),image-2.toggleClass(class='show-all', force=true)" class="btn">
An easel
</button>
</p>
<p>
<button [hidden]="anim2 == 1" type="button" on="tap:AMP.setState({anim2: 1})" class="btn-bg">
I don't know, show me more.
</button>
</p>
</div>
<div hidden [hidden]="result2 != 1" class="result result-true">
<p style="color:green">
You are right!
</p>
<p>
<button type="button" on="tap:AMP.setState({screen:2})" class="btn-bg">
Next
</button>
</p>
</div>
<div [hidden]="result2 != 0" hidden class="result result-false">
<p style="color:red">
No. It is a lamp.
</p>
<p>
<button on="tap:AMP.setState({screen:2})" type="button" class="btn-bg">
Next
</button>
</p>
</div>
</div>
</div>
<div [hidden]="screen !=2" hidden class="screen-3 screen">
<div id="image-3" [class]="anim3 == 1 ? 'image image-3 anim2' : 'image image-3'" class="image image-3"></div>
<div class="buttons">
<div [hidden]="result3 != null">
<p>
<button type="button" on="tap:AMP.setState({result3: 0}),image-3.toggleClass(class='show-all', force=true)" class="btn">
A sofa
</button>
</p>
<p>
<button type="button" on="tap:AMP.setState({result3: 1}),image-3.toggleClass(class='show-all', force=true)" class="btn">
An armchair
</button>
</p>
<p>
<button type="button" on="tap:AMP.setState({result3: 0}),image-3.toggleClass(class='show-all', force=true)" class="btn">
A table
</button>
</p>
<p>
<button [hidden]="anim3 == 1" type="button" on="tap:AMP.setState({anim3: 1})" class="btn-bg">
I don't know, show me more.
</button>
</p>
</div>
<div hidden [hidden]="result3 != 1" class="result result-true">
<p style="color:green">
You are right!
</p>
<p>
<button type="button" on="tap:AMP.setState({screen:3})" class="btn-bg">
Done
</button>
</p>
</div>
<div hidden [hidden]="result3 != 0" class="result result-false">
<p style="color:red">
No. It is an armchair.
</p>
<p>
<button type="button" on="tap:AMP.setState({screen:3})" class="btn-bg">
Done
</button>
</p>
</div>
</div>
</div>
<div class="screen-4 screen" hidden [hidden]="screen <3">
<div class="finish-text">
<h2 style="padding-bottom:15px">
Congratulations! 🎉
</h2>
<p style="padding-bottom:10px">
You've earned a <b>15%</b> discount on your next purchase. Enjoy your reward and thank you for playing!
</p>
<p style="padding-bottom:10px">
Use the code <b>WIN15</b> at checkout to claim your discount.
</p>
</div>
</div>
</div>
Kinetic version built with HTML5 and CSS3
Now, let’s move on to the kinetic or interactive HTML version, built with HTML5 and CSS3. Add another empty one-column structure below our AMP version. Select it and set the “Include in” option to “HTML” only.
After that, add an HTML block to this structure and paste this code:
<style>
.guess-image-html .screen { text-align: center; display: flex; justify-content: space-between; align-items: flex-start; } .guess-image-html .image { width: 260px; height: 260px; background-repeat: no-repeat; background-position: bottom center; border: 1px solid gray; background-size: 200%; transition-duration: 4s; } .guess-image-html .image-1 { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_ad2d67391b1b95bc58fac20025cf77e63639e7f01ffe4d48b1d3d16c225076c0/images/img01.jpg) } .guess-image-html .image-2 { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_ad2d67391b1b95bc58fac20025cf77e63639e7f01ffe4d48b1d3d16c225076c0/images/img02.png) } .guess-image-html .image-3 { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_ad2d67391b1b95bc58fac20025cf77e63639e7f01ffe4d48b1d3d16c225076c0/images/img03.png) } .guess-image-html .buttons { width: 50%; } .guess-image-html .btn { display: inline-block; background: none; border: 0; outline: 0; font-size: 16px; padding: 8px; cursor: pointer; font-weight: bold; } .guess-image-html .btn:hover, .guess-image-html .btn-bg:hover { opacity: 0.8; } .guess-image-html .btn-bg { display: inline-block; margin-top: 15px; font-size: 14px; padding: 5px 10px; cursor: pointer; background-color: #efefef; border: 1px solid #cccccc; color: #000000; } .guess-image-html .result { padding: 15px 0; } .guess-image-html .result p { font-size: 16px; } .guess-image-html .finish-text { padding: 10px 0; } @media only screen and (max-width: 600px) { .guess-image-html .screen { display: block; } .guess-image-html .buttons { width: 100%; } .guess-image-html .image { margin: 0 auto; } } .guess-image-html .screen-2, .guess-image-html .screen-3, .guess-image-html .screen-4, .guess-image-html .result { display: none; } #image-1-next:checked~* .screen-2, #image-2-next:checked~* .screen-3, #image-3-next:checked~* .screen-4 { display: flex; } #image-1-next:checked~* .screen-1, #image-2-next:checked~* .screen-2, #image-3-next:checked~* .screen-3, #image-3-next:checked~* .hide { display: none !important; } #image-1-help:checked~* .image-1 { background-size: 105%; } #image-2-help:checked~* .image-2, #image-3-help:checked~* .image-3 { background-size: 155%; } .image-1-input:checked~* .image-1, .image-2-input:checked~* .image-2, .image-3-input:checked~* .image-3 { background-size: 95% !important; transition-duration: .5s; } #image-1-help:checked~* .screen-1 .btn-more, #image-2-help:checked~* .screen-2 .btn-more, #image-3-help:checked~* .screen-3 .btn-more, .image-1-input:checked~* .screen-1 .answer-block, .image-2-input:checked~* .screen-2 .answer-block, .image-3-input:checked~* .screen-3 .answer-block { display: none; } #image-1-right:checked~* .screen-1 .result-true, #image-2-right:checked~* .screen-2 .result-true, #image-3-right:checked~* .screen-3 .result-true { display: block; } #image-1-wrong:checked~* .screen-1 .result-false, #image-2-wrong:checked~* .screen-2 .result-false, #image-3-wrong:checked~* .screen-3 .result-false { display: block; }
</style>
<div class="guess-image-html">
<input type="radio" id="image-1-right" name="image-1" class="image-1-input" style="display:none">
<input type="radio" id="image-1-wrong" name="image-1" class="image-1-input" style="display:none">
<input type="radio" id="image-2-right" name="image-2" class="image-2-input" style="display:none">
<input type="radio" id="image-2-wrong" name="image-2" class="image-2-input" style="display:none">
<input name="image-3" type="radio" id="image-3-right" class="image-3-input" style="display:none">
<input type="radio" id="image-3-wrong" name="image-3" class="image-3-input" style="display:none">
<input type="checkbox" id="image-1-help" name="help" style="display:none">
<input type="checkbox" id="image-2-help" name="help" style="display:none">
<input type="checkbox" id="image-3-help" name="help" style="display:none">
<input type="checkbox" id="image-1-next" name="next" style="display:none">
<input name="next" type="checkbox" id="image-2-next" style="display:none">
<input type="checkbox" id="image-3-next" name="next" style="display:none">
<div>
<h2 class="hide" style="padding-bottom:20px">
What is it?
</h2>
<div class="screen-1 screen">
<div class="image image-1"></div>
<div class="buttons">
<div class="answer-block">
<p>
<label for="image-1-wrong" class="btn">
A lamp
</label>
</p>
<p>
<label for="image-1-wrong" class="btn">
A table
</label>
</p>
<p>
<label for="image-1-right" class="btn">
A vase
</label>
</p>
<p>
<label for="image-1-help" class="btn-bg btn-more">
I don't know, show me more.
</label>
</p>
</div>
<div class="result result-true">
<p style="color:green;font-size:16px">
You are right!
</p>
<p>
<label for="image-1-next" class="btn-bg">
Next
</label>
</p>
</div>
<div class="result result-false">
<p style="color:red;font-size:16px">
No. It is a vase.
</p>
<p>
<label for="image-1-next" class="btn-bg">
Next
</label>
</p>
</div>
</div>
</div>
<div class="screen-2 screen">
<div class="image image-2"></div>
<div class="buttons">
<div class="answer-block">
<p>
<label for="image-2-wrong" class="btn">
A table
</label>
</p>
<p>
<label for="image-2-right" class="btn">
A lamp
</label>
</p>
<p>
<label for="image-2-wrong" class="btn">
An easel
</label>
</p>
<p>
<label for="image-2-help" class="btn-bg btn-more">
I don't know, show me more.
</label>
</p>
</div>
<div class="result result-true">
<p style="color:green;font-size:16px">
You are right!
</p>
<p>
<label for="image-2-next" class="btn-bg">
Next
</label>
</p>
</div>
<div class="result result-false">
<p style="font-size:16px;color:red">
No. It is a lamp.
</p>
<p>
<label for="image-2-next" class="btn-bg">
Next
</label>
</p>
</div>
</div>
</div>
<div class="screen-3 screen">
<div class="image image-3"></div>
<div class="buttons">
<div class="answer-block">
<p>
<label for="image-3-wrong" class="btn">
A sofa
</label>
</p>
<p>
<label for="image-3-right" class="btn">
An armchair
</label>
</p>
<p>
<label for="image-3-wrong" class="btn">
A table
</label>
</p>
<p>
<label for="image-3-help" class="btn-bg btn-more">
I don't know, show me more.
</label>
</p>
</div>
<div class="result result-true">
<p style="color:green;font-size:16px">
You are right!
</p>
<p>
<label for="image-3-next" class="btn-bg">
Next
</label>
</p>
</div>
<div class="result result-false">
<p style="font-size:16px;color:red">
No. It is an armchair.
</p>
<p>
<label for="image-3-next" class="btn-bg">
Next
</label>
</p>
</div>
</div>
</div>
<div class="screen-4 screen">
<div class="finish-text">
<h2 style="padding-bottom:15px">
Congratulations! 🎉
</h2>
<p style="padding-bottom:10px">
You've earned a <b>15%</b> discount on your next purchase. Enjoy your reward and thank you for playing!
</p>
<p style="padding-bottom:10px">
Use the code <b>WIN15</b> at checkout to claim your discount.
</p>
</div>
</div>
</div>
</div>
The HTML version has a similar structure, but all interactivity is achieved using input tags linked to label tags using the for="" attribute.
The inputs are placed at the very beginning. Don't move them, as we used the CSS selector "~" in the styles, which is tightly bound to the code structure, and if the layout changes, the game may stop working.
All buttons have been replaced with label tags.
In the styles, the display of the puzzle steps and results looks like this. As soon as the input corresponding to the next button is selected, the next block is shown, and the previous one is hidden:
The styles for the help button that shows part of the image look like this:
The display message for the correct and incorrect answers looks like this:
To change images to your own, replace these links.
Replacing texts is also easy; all you need to do is change them here (all texts look like this).
The same goes for the final message in your game.
Fallback version
The final thing we need to do to complete creating our game is a fallback version. A fallback version is required for recipients whose email clients don’t support HTML5 and CSS3 — or AMP. It will have a layout similar to our mechanics, but without interactivity. Clicking on elements will open the web version of the email. In this example, the fallback will be an image of the game.
Our fallback version will look like the first riddle in the game.
All actions will take place in the kinetic HTML block created above. Insert the following code between the </style> tag and <div class="guess-image-html">:
<!--[if !mso]><!-- -->
<input type="checkbox" id="fallback_ctrl" checked class="fallback_ctrl" style="mso-hide:all;display:none !important">
<!--<![endif]-->
<!-- FALLBACK -->
<span id="fallback" class="fallback">
<table width="100%">
<tbody>
<tr>
<td style="padding-bottom:20px">
<h2>
What is it?
</h2>
</td>
</tr>
<tr>
<td width="45%" align="center" style="border:1px solid gray">
<a href="https://viewstripo.email/bbb995f1-24df-470d-86ce-9dd79cc930981759230084951?type=amphtml" target="_blank"><img src="https://zlnfb.stripocdn.email/content/guids/CABINET_de38de4cec6d94795ba3367c7311279a2735446a573a817f1ef70e2eef5f2c43/images/imgfallback_MtE.jpg" width="260" height="260" class="adapt-img"></a>
</td>
<td valign="top">
<table width="100%" align="center">
<tbody>
<tr>
<td align="center" style="padding-bottom:10px">
<p>
<a href="https://viewstripo.email/bbb995f1-24df-470d-86ce-9dd79cc930981759230084951?type=amphtml" target="_blank" style="font-weight:bold;color:#333333;text-decoration:none;font-size:16px">A lamp</a>
</p>
</td>
</tr>
<tr>
<td align="center" style="padding-bottom:10px">
<p>
<a href="https://viewstripo.email/bbb995f1-24df-470d-86ce-9dd79cc930981759230084951?type=amphtml" target="_blank" style="color:#333333;text-decoration:none;font-size:16px;font-weight:bold">A table</a>
</p>
</td>
</tr>
<tr>
<td align="center" style="padding-bottom:10px">
<p>
<a href="https://viewstripo.email/bbb995f1-24df-470d-86ce-9dd79cc930981759230084951?type=amphtml" target="_blank" style="font-weight:bold;color:#333333;text-decoration:none;font-size:16px">A vase</a>
</p>
</td>
</tr>
<tr>
<td align="center" style="padding-bottom:10px;padding-top:10px;padding-left:10px;padding-right:10px">
<p>
<a href="https://viewstripo.email/bbb995f1-24df-470d-86ce-9dd79cc930981759230084951?type=amphtml" target="_blank" style="font-size:14px;padding-top:5px;padding-left:10px;text-decoration:none;display:inline-block;padding-right:10px;background-color:#efefef;padding-bottom:5px;border:1px solid #cccccc;color:#000000">I don't know, show me more.</a>
</p>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</span>
<!-- /FALLBACK -->
<!--[if !mso]><!-- -->
<!-- INTERACTIVE ELEMENT -->
<div class="container" style="mso-hide:all;display:none">
In addition, at the very end of the code, insert this piece:
</div><!-- /INTERACTIVE ELEMENT -->
<!--<![endif]-->
To change images and links (both when clicking on images and answer buttons), replace them here.
The last thing left to do is to add styles to display only the version suitable for the recipient’s email client. Copy these styles at the end of the style tag:
/* --- */ @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; } }
Let's take a closer look at the layout. Our fallback has the following line:
<!--[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.
<span id="fallback" class="fallback"></span> is the block containing all the 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, but the main thing is to use a layout that'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.
While these styles don’t have clear rules for each email client, there’s 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
We have finished creating the game. Here is the full HTML code, including the kinetic version, based on HTML5 and CSS3 та static fallback:
<style>
.guess-image-html .screen { text-align: center; display: flex; justify-content: space-between; align-items: flex-start; } .guess-image-html .image { width: 260px; height: 260px; background-repeat: no-repeat; background-position: bottom center; border: 1px solid gray; background-size: 200%; transition-duration: 4s; } .guess-image-html .image-1 { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_ad2d67391b1b95bc58fac20025cf77e63639e7f01ffe4d48b1d3d16c225076c0/images/img01.jpg) } .guess-image-html .image-2 { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_ad2d67391b1b95bc58fac20025cf77e63639e7f01ffe4d48b1d3d16c225076c0/images/img02.png) } .guess-image-html .image-3 { background-image: url(https://zlnfb.stripocdn.email/content/guids/CABINET_ad2d67391b1b95bc58fac20025cf77e63639e7f01ffe4d48b1d3d16c225076c0/images/img03.png) } .guess-image-html .buttons { width: 50%; } .guess-image-html .btn { display: inline-block; background: none; border: 0; outline: 0; font-size: 16px; padding: 8px; cursor: pointer; font-weight: bold; } .guess-image-html .btn:hover, .guess-image-html .btn-bg:hover { opacity: 0.8; } .guess-image-html .btn-bg { display: inline-block; margin-top: 15px; font-size: 14px; padding: 5px 10px; cursor: pointer; background-color: #efefef; border: 1px solid #cccccc; color: #000000; } .guess-image-html .result { padding: 15px 0; } .guess-image-html .result p { font-size: 16px; } .guess-image-html .finish-text { padding: 10px 0; } @media only screen and (max-width: 600px) { .guess-image-html .screen { display: block; } .guess-image-html .buttons { width: 100%; } .guess-image-html .image { margin: 0 auto; } } .guess-image-html .screen-2, .guess-image-html .screen-3, .guess-image-html .screen-4, .guess-image-html .result { display: none; } #image-1-next:checked~* .screen-2, #image-2-next:checked~* .screen-3, #image-3-next:checked~* .screen-4 { display: flex; } #image-1-next:checked~* .screen-1, #image-2-next:checked~* .screen-2, #image-3-next:checked~* .screen-3, #image-3-next:checked~* .hide { display: none !important; } #image-1-help:checked~* .image-1 { background-size: 105%; } #image-2-help:checked~* .image-2, #image-3-help:checked~* .image-3 { background-size: 155%; } .image-1-input:checked~* .image-1, .image-2-input:checked~* .image-2, .image-3-input:checked~* .image-3 { background-size: 95% !important; transition-duration: .5s; } #image-1-help:checked~* .screen-1 .btn-more, #image-2-help:checked~* .screen-2 .btn-more, #image-3-help:checked~* .screen-3 .btn-more, .image-1-input:checked~* .screen-1 .answer-block, .image-2-input:checked~* .screen-2 .answer-block, .image-3-input:checked~* .screen-3 .answer-block { display: none; } #image-1-right:checked~* .screen-1 .result-true, #image-2-right:checked~* .screen-2 .result-true, #image-3-right:checked~* .screen-3 .result-true { display: block; } #image-1-wrong:checked~* .screen-1 .result-false, #image-2-wrong:checked~* .screen-2 .result-false, #image-3-wrong:checked~* .screen-3 .result-false { display: block; } /* --- */ @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 type="checkbox" id="fallback_ctrl" checked class="fallback_ctrl" style="mso-hide:all;display:none !important">
<!--<![endif]-->
<!-- FALLBACK -->
<span id="fallback" class="fallback">
<table width="100%">
<tbody>
<tr>
<td style="padding-bottom:20px">
<h2>
What is it?
</h2>
</td>
</tr>
<tr>
<td width="45%" align="center" style="border:1px solid gray">
<a href="https://viewstripo.email/bbb995f1-24df-470d-86ce-9dd79cc930981759230084951?type=amphtml" target="_blank"><img src="https://zlnfb.stripocdn.email/content/guids/CABINET_de38de4cec6d94795ba3367c7311279a2735446a573a817f1ef70e2eef5f2c43/images/imgfallback_MtE.jpg" width="260" height="260" class="adapt-img"></a>
</td>
<td valign="top">
<table width="100%" align="center">
<tbody>
<tr>
<td align="center" style="padding-bottom:10px">
<p>
<a href="https://viewstripo.email/bbb995f1-24df-470d-86ce-9dd79cc930981759230084951?type=amphtml" target="_blank" style="font-weight:bold;color:#333333;text-decoration:none;font-size:16px">A lamp</a>
</p>
</td>
</tr>
<tr>
<td align="center" style="padding-bottom:10px">
<p>
<a href="https://viewstripo.email/bbb995f1-24df-470d-86ce-9dd79cc930981759230084951?type=amphtml" target="_blank" style="color:#333333;text-decoration:none;font-size:16px;font-weight:bold">A table</a>
</p>
</td>
</tr>
<tr>
<td align="center" style="padding-bottom:10px">
<p>
<a href="https://viewstripo.email/bbb995f1-24df-470d-86ce-9dd79cc930981759230084951?type=amphtml" target="_blank" style="font-weight:bold;color:#333333;text-decoration:none;font-size:16px">A vase</a>
</p>
</td>
</tr>
<tr>
<td align="center" style="padding-bottom:10px;padding-top:10px;padding-left:10px;padding-right:10px">
<p>
<a href="https://viewstripo.email/bbb995f1-24df-470d-86ce-9dd79cc930981759230084951?type=amphtml" target="_blank" style="font-size:14px;padding-top:5px;padding-left:10px;text-decoration:none;display:inline-block;padding-right:10px;background-color:#efefef;padding-bottom:5px;border:1px solid #cccccc;color:#000000">I don't know, show me more.</a>
</p>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</span>
<!-- /FALLBACK -->
<!--[if !mso]><!-- -->
<!-- INTERACTIVE ELEMENT -->
<div class="container" style="mso-hide:all;display:none">
<div class="guess-image-html">
<input type="radio" id="image-1-right" name="image-1" class="image-1-input" style="display:none">
<input type="radio" id="image-1-wrong" name="image-1" class="image-1-input" style="display:none">
<input type="radio" id="image-2-right" name="image-2" class="image-2-input" style="display:none">
<input type="radio" id="image-2-wrong" name="image-2" class="image-2-input" style="display:none">
<input name="image-3" type="radio" id="image-3-right" class="image-3-input" style="display:none">
<input type="radio" id="image-3-wrong" name="image-3" class="image-3-input" style="display:none">
<input type="checkbox" id="image-1-help" name="help" style="display:none">
<input type="checkbox" id="image-2-help" name="help" style="display:none">
<input type="checkbox" id="image-3-help" name="help" style="display:none">
<input type="checkbox" id="image-1-next" name="next" style="display:none">
<input name="next" type="checkbox" id="image-2-next" style="display:none">
<input type="checkbox" id="image-3-next" name="next" style="display:none">
<div>
<h2 class="hide" style="padding-bottom:20px">
What is it?
</h2>
<div class="screen-1 screen">
<div class="image image-1"></div>
<div class="buttons">
<div class="answer-block">
<p>
<label for="image-1-wrong" class="btn">
A lamp
</label>
</p>
<p>
<label for="image-1-wrong" class="btn">
A table
</label>
</p>
<p>
<label for="image-1-right" class="btn">
A vase
</label>
</p>
<p>
<label for="image-1-help" class="btn-bg btn-more">
I don't know, show me more.
</label>
</p>
</div>
<div class="result result-true">
<p style="color:green;font-size:16px">
You are right!
</p>
<p>
<label for="image-1-next" class="btn-bg">
Next
</label>
</p>
</div>
<div class="result result-false">
<p style="color:red;font-size:16px">
No. It is a vase.
</p>
<p>
<label for="image-1-next" class="btn-bg">
Next
</label>
</p>
</div>
</div>
</div>
<div class="screen-2 screen">
<div class="image image-2"></div>
<div class="buttons">
<div class="answer-block">
<p>
<label for="image-2-wrong" class="btn">
A table
</label>
</p>
<p>
<label for="image-2-right" class="btn">
A lamp
</label>
</p>
<p>
<label for="image-2-wrong" class="btn">
An easel
</label>
</p>
<p>
<label for="image-2-help" class="btn-bg btn-more">
I don't know, show me more.
</label>
</p>
</div>
<div class="result result-true">
<p style="color:green;font-size:16px">
You are right!
</p>
<p>
<label for="image-2-next" class="btn-bg">
Next
</label>
</p>
</div>
<div class="result result-false">
<p style="font-size:16px;color:red">
No. It is a lamp.
</p>
<p>
<label for="image-2-next" class="btn-bg">
Next
</label>
</p>
</div>
</div>
</div>
<div class="screen-3 screen">
<div class="image image-3"></div>
<div class="buttons">
<div class="answer-block">
<p>
<label for="image-3-wrong" class="btn">
A sofa
</label>
</p>
<p>
<label for="image-3-right" class="btn">
An armchair
</label>
</p>
<p>
<label for="image-3-wrong" class="btn">
A table
</label>
</p>
<p>
<label for="image-3-help" class="btn-bg btn-more">
I don't know, show me more.
</label>
</p>
</div>
<div class="result result-true">
<p style="color:green;font-size:16px">
You are right!
</p>
<p>
<label for="image-3-next" class="btn-bg">
Next
</label>
</p>
</div>
<div class="result result-false">
<p style="font-size:16px;color:red">
No. It is an armchair.
</p>
<p>
<label for="image-3-next" class="btn-bg">
Next
</label>
</p>
</div>
</div>
</div>
<div class="screen-4 screen">
<div class="finish-text">
<h2 style="padding-bottom:15px">
Congratulations! 🎉
</h2>
<p style="padding-bottom:10px">
You’ve earned a <b>15%</b> discount on your next purchase. Enjoy your reward and thank you for playing!
</p>
<p style="padding-bottom:10px">
Use the code <b>WIN15</b> at checkout to claim your discount.
</p>
</div>
</div>
</div>
</div>
</div>
<!-- /INTERACTIVE ELEMENT -->
<!--<![endif]-->
If you want to save time, you can use this complete version, where all the elements are already combined. To create your own version, you need to make some tweaks under the hood to change the images and the final message.
Wrapping up
It’s a simple game with a simple creation process. Nothing more, nothing less. But the uniqueness and engagement it can bring to your newsletter cannot be overestimated. Set any images you want, create fun riddles, and promote your business using the power of interactivity that is easy to create and edit.