<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: benjamin</title>
    <description>The latest articles on DEV Community by benjamin (@bdjang).</description>
    <link>https://dev.to/bdjang</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F936789%2F4bb3c874-a0cc-47e3-9ba1-78b0eff6458f.jpeg</url>
      <title>DEV Community: benjamin</title>
      <link>https://dev.to/bdjang</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bdjang"/>
    <language>en</language>
    <item>
      <title>Build an Interactive Quiz using ⚡AMP Email</title>
      <dc:creator>benjamin</dc:creator>
      <pubDate>Mon, 25 Mar 2024 04:00:21 +0000</pubDate>
      <link>https://dev.to/bdjang/build-an-interactive-quiz-in-amp-emai-1bjg</link>
      <guid>https://dev.to/bdjang/build-an-interactive-quiz-in-amp-emai-1bjg</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;Many news organizations create &lt;a href="https://www.nytimes.com/spotlight/news-quiz" rel="noopener noreferrer"&gt;weekly quizzes&lt;/a&gt; about recent events. These organizations usually send out an email containing a link to the quiz hosted on their website. This requires users to click on the link and navigate to a landing page to play the quiz.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Goal
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Instead of leaving the inbox to play the quiz in a web browser, is it possible to create a fully playable quiz within the email?&lt;/em&gt;&lt;/strong&gt; Yes, through the use of AMP email and the &lt;code&gt;amp-bind&lt;/code&gt; component, you can build an interactive quiz.&lt;/p&gt;

&lt;h2&gt;
  
  
  🛠️ Let's Start Building
&lt;/h2&gt;

&lt;p&gt;The following is a step by step guide for building a short, four question AMP quiz. Scroll to the bottom to view the AMP quiz demo ⏬&lt;/p&gt;




&lt;h2&gt;
  
  
  🏗️ AMP Boilerplate Template
&lt;/h2&gt;

&lt;p&gt;1). Start by setting up an &lt;a href="https://amp.dev/documentation/guides-and-tutorials/email/start/create_email?redirected#start-with-the-amp-email-boilerplate" rel="noopener noreferrer"&gt;AMP email template&lt;/a&gt; with the required &lt;code&gt;amp-bind&lt;/code&gt; &lt;a href="https://amp.dev/documentation/components/email/amp-bind" rel="noopener noreferrer"&gt;script&lt;/a&gt; in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; tag&lt;/p&gt;

&lt;p&gt;Below is a sample AMP email boilerplate:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="cp"&gt;&amp;lt;!doctype html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="err"&gt;⚡4&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt; &lt;span class="na"&gt;data-css-strict&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"utf-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;async&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.ampproject.org/v0.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;async&lt;/span&gt; &lt;span class="na"&gt;custom-element=&lt;/span&gt;&lt;span class="s"&gt;"amp-bind"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.ampproject.org/v0/amp-bind-0.1.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;style &lt;/span&gt;&lt;span class="na"&gt;amp4email-boilerplate&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;body&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;visibility&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;style &lt;/span&gt;&lt;span class="na"&gt;amp-custom&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello, I am an AMP EMAIL!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  ❓ Question ✅ Answer Modules
&lt;/h2&gt;

&lt;p&gt;2). Create the first quiz question and corresponding choices&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Question #1&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;How many boroughs make up New York City?&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;article&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"q1Question"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;
    Four
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;
    Five
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;
    Six
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;
    Seven
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff3fpbkylpsuxa5pglot0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff3fpbkylpsuxa5pglot0.png" alt="First question with corresponding choices"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3). Then create the answer module below the original choices. This module will reveal the player's correct or incorrect answer selection&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Question #1&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;How many boroughs make up New York City?&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;article&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"q1Question"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;
    Four
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;
    Five
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;
    Six
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;
    Seven
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;article&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"q1Answer"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;
    Four
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;
    Five
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;
    Six
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;
    Seven
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;4). Apply the &lt;code&gt;hidden&lt;/code&gt; attribute to hide the quiz answer module&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;article&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"q1Answer"&lt;/span&gt; &lt;span class="na"&gt;hidden&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
...
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In order to hide the question module and reveal the answer module after selecting a choice, we need to create an event handler that listens to this action.&lt;/p&gt;

&lt;p&gt;5). Use the &lt;code&gt;on&lt;/code&gt; attribute to create an &lt;a href="https://amp.dev/documentation/guides-and-tutorials/email/learn/amp-email-actions-and-events" rel="noopener noreferrer"&gt;event handler&lt;/a&gt; that hides the question module and reveals the answer module after "tapping" on one of the choices&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Question #1&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;How many boroughs make up New York City?&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;article&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"q1Question"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on=&lt;/span&gt;&lt;span class="s"&gt;"tap:q1Question.hide,q1Answer.show"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Four
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on=&lt;/span&gt;&lt;span class="s"&gt;"tap:q1Question.hide,q1Answer.show"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Five
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on=&lt;/span&gt;&lt;span class="s"&gt;"tap:q1Question.hide,q1Answer.show"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Six
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on=&lt;/span&gt;&lt;span class="s"&gt;"tap:q1Question.hide,q1Answer.show"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Seven
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The purpose of this event handler is to prevent users from answering the question again after making an initial selection.&lt;/p&gt;

&lt;p&gt;Now let's reveal the correct answer and indicate through CSS styling and classes whether the selected option was correct or incorrect ⬇️&lt;/p&gt;

&lt;p&gt;6). Use &lt;a href="https://amp.dev/documentation/components/email/amp-bind#defining-and-initializing-state-with-%3Camp-state%3E" rel="noopener noreferrer"&gt;&lt;code&gt;AMP.setState()&lt;/code&gt;&lt;/a&gt; to bind a &lt;code&gt;correct&lt;/code&gt; or &lt;code&gt;incorrect&lt;/code&gt; class to each of the options&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Question #1&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;How many boroughs make up New York City?&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;article&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"q1Question"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on=&lt;/span&gt;&lt;span class="s"&gt;"tap:q1Question.hide,q1Answer.show,AMP.setState({btn2Class: 'correct', btn1Class: 'incorrect'})"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Four
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on=&lt;/span&gt;&lt;span class="s"&gt;"tap:q1Question.hide,q1Answer.show,AMP.setState({btn2Class: 'correct'})"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Five
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on=&lt;/span&gt;&lt;span class="s"&gt;"tap:q1Question.hide,q1Answer.show,AMP.setState({btn2Class: 'correct', btn3Class: 'incorrect'})"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Six
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on=&lt;/span&gt;&lt;span class="s"&gt;"tap:q1Question.hide,q1Answer.show,AMP.setState({btn2Class: 'correct', btn4Class: 'incorrect'})"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Seven
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;7). Add the corresponding &lt;code&gt;[class]&lt;/code&gt; attribute to each of the options in the answer module&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Question #1&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;How many boroughs make up New York City?&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;article&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"q1Question"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on=&lt;/span&gt;&lt;span class="s"&gt;"tap:q1Question.hide,q1Answer.show,AMP.setState({btn2Class: 'correct', btn1Class: 'incorrect'})"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Four
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on=&lt;/span&gt;&lt;span class="s"&gt;"tap:q1Question.hide,q1Answer.show,AMP.setState({btn2Class: 'correct'})"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Five
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on=&lt;/span&gt;&lt;span class="s"&gt;"tap:q1Question.hide,q1Answer.show,AMP.setState({btn2Class: 'correct', btn3Class: 'incorrect'})"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Six
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on=&lt;/span&gt;&lt;span class="s"&gt;"tap:q1Question.hide,q1Answer.show,AMP.setState({btn2Class: 'correct', btn4Class: 'incorrect'})"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Seven
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;article&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"q1Answer"&lt;/span&gt; &lt;span class="na"&gt;hidden&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;[class]=&lt;/span&gt;&lt;span class="s"&gt;"btn1Class || ''"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Four
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;[class]=&lt;/span&gt;&lt;span class="s"&gt;"btn2Class || ''"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Five
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;[class]=&lt;/span&gt;&lt;span class="s"&gt;"btn3Class || ''"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Six
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;[class]=&lt;/span&gt;&lt;span class="s"&gt;"btn4Class || ''"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Seven
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;AMP.setState({btn2Class: 'correct', btn1Class: 'incorrect'})&lt;/code&gt; action will assign the &lt;code&gt;correct&lt;/code&gt; CSS class through the &lt;code&gt;[class]="btn2Class || ''"&lt;/code&gt; expression. It will also assign the &lt;code&gt;incorrect&lt;/code&gt; CSS class through the &lt;code&gt;[class]="btn1Class || ''"&lt;/code&gt; expression. The same logic applies to the rest of the buttons.&lt;/p&gt;

&lt;p&gt;8). Create the &lt;code&gt;correct&lt;/code&gt; and &lt;code&gt;incorrect&lt;/code&gt; classes and add the CSS styling&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="c"&gt;/* AMP.setState CLASSES */&lt;/span&gt;
&lt;span class="nc"&gt;.correct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#3beb57&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.incorrect&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ff3636&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Up to this point, we have created the first quiz question with four different options. When a user selects one of the options, the hidden answer module will reveal and the &lt;code&gt;correct&lt;/code&gt; and &lt;code&gt;incorrect&lt;/code&gt; class expression will render.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0kejcadh2yn7iij81emv.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0kejcadh2yn7iij81emv.gif" alt="AMP quiz question #1 demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  💯 Recording the Quiz Score
&lt;/h2&gt;

&lt;p&gt;Now let's use &lt;code&gt;amp-bind&lt;/code&gt; to track a user's quiz score as they answer each question.&lt;/p&gt;

&lt;p&gt;9). Use the &lt;code&gt;AMP.setState()&lt;/code&gt; action and the &lt;code&gt;[text]&lt;/code&gt; attribute to record and display a score. The state variable &lt;code&gt;quizScore&lt;/code&gt; will now update to the value of &lt;code&gt;1&lt;/code&gt; if the correct option is selected or &lt;code&gt;0&lt;/code&gt; for the incorrect options&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Question #1&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Your Score: &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;[text]=&lt;/span&gt;&lt;span class="s"&gt;"quizScore"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;0&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;How many boroughs make up New York City?&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;article&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"q1Question"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on=&lt;/span&gt;&lt;span class="s"&gt;"tap:q1Question.hide,q1Answer.show,AMP.setState({btn2Class: 'correct', btn1Class: 'incorrect', quizScore: 0})"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Four
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on=&lt;/span&gt;&lt;span class="s"&gt;"tap:q1Question.hide,q1Answer.show,AMP.setState({btn2Class: 'correct', quizScore: 1})"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Five
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on=&lt;/span&gt;&lt;span class="s"&gt;"tap:q1Question.hide,q1Answer.show,AMP.setState({btn2Class: 'correct', btn3Class: 'incorrect', quizScore: 0})"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Six
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on=&lt;/span&gt;&lt;span class="s"&gt;"tap:q1Question.hide,q1Answer.show,AMP.setState({btn2Class: 'correct', btn4Class: 'incorrect', quizScore: 0})"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Seven
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fui684mkkx927kwvmrbsf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fui684mkkx927kwvmrbsf.gif" alt="AMP score change demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ⏩ Next Quiz Question
&lt;/h2&gt;

&lt;p&gt;After a quiz question is answered, let's provide a way to move onto the next question.&lt;/p&gt;

&lt;p&gt;10). Create a "Next question" button within the hidden answer module&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;article&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"q1Answer"&lt;/span&gt; &lt;span class="na"&gt;hidden&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;[class]=&lt;/span&gt;&lt;span class="s"&gt;"btn1Class || ''"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Four
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;[class]=&lt;/span&gt;&lt;span class="s"&gt;"btn2Class || ''"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Five
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;[class]=&lt;/span&gt;&lt;span class="s"&gt;"btn3Class || ''"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Six
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;[class]=&lt;/span&gt;&lt;span class="s"&gt;"btn4Class || ''"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Seven
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;on=&lt;/span&gt;&lt;span class="s"&gt;"tap:q1Section.hide,q2Section.show"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Next question &lt;span class="ni"&gt;&amp;amp;#x2192;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;11). Then wrap the entire question #1 module (including the question and answer modules) in a &lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt; element. Wrap the entire question #2 module using the same method&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="c"&gt;&amp;lt;!-- QUESTION #1 --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"q1Section"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Question #1&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;How many boroughs make up New York City?&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
  ...
&lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- end question #1 --&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- QUESTION #2 --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"q2Section"&lt;/span&gt; &lt;span class="na"&gt;hidden&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Question #2&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;What is the largest park in NYC?&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
  ...
&lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- end question #2 --&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The "Next question" button with the &lt;code&gt;on="tap:q1Section.hide,q2Section.show"&lt;/code&gt; event will hide question #1 and display question #2.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3osrkyuxajfcb5t7kayh.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3osrkyuxajfcb5t7kayh.gif" alt="Next question demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Repeat these steps for questions #2 and #3 to finish building the quiz. Now the quiz is completed 🙌&lt;/p&gt;




&lt;h2&gt;
  
  
  🕹️ AMP Quiz Demo
&lt;/h2&gt;

&lt;p&gt;Below is a demo featuring a four question quiz with some added CSS styling.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;&lt;em&gt;NOTE: Copy &amp;amp; paste the HTML tab code into the &lt;a href="https://amp.gmail.dev/playground/" rel="noopener noreferrer"&gt;Gmail AMP Playground&lt;/a&gt; or the &lt;a href="https://playground.amp.dev/?mode=Responsive&amp;amp;runtime=amp4email#" rel="noopener noreferrer"&gt;amp.dev Playground&lt;/a&gt; for a more accurate demo experience!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/bdjang/embed/ZEZpxMx?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  🤔 Can We Automate?
&lt;/h2&gt;

&lt;p&gt;Once this AMP email quiz template is created, can weekly email sends be automated with new questions pulling in from a &lt;a href="https://amp.dev/documentation/guides-and-tutorials/email/learn/cors-in-email" rel="noopener noreferrer"&gt;CORS JSON endpoint&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;It is possible to pull in the text content (i.e. quiz questions and options to choose from), however, &lt;strong&gt;&lt;em&gt;the logic determining which option is correct and which options are incorrect are built into the &lt;code&gt;on&lt;/code&gt; attribute and event handler&lt;/em&gt;&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In other words, the position of the "correct" options will always stay the same for each question due to the inline nature of the AMP logic - only the text content will change&lt;/strong&gt;. This is not an ideal situation because users will eventually learn where the "correct" option is located regardless of the quiz question content.&lt;/p&gt;

&lt;p&gt;Currently, the only option with this particular AMP template is to &lt;em&gt;manually shuffle&lt;/em&gt; the &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt; elements to randomize the "correct" option 🙃.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExYnd2YndmMjF5dXZ5bzk2bzRzcHU5dDA0NWQ1MWZibmh5Z3lpNHMxOSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/3o6MbsNCPeLXgcNWDK/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExYnd2YndmMjF5dXZ5bzk2bzRzcHU5dDA0NWQ1MWZibmh5Z3lpNHMxOSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/3o6MbsNCPeLXgcNWDK/giphy.gif" alt="Manually randomize options"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;A fully interactive quiz can be built entirely inside of an email by using the &lt;code&gt;amp-bind&lt;/code&gt; component. Individual scores can also be tracked based on the user selections.&lt;/p&gt;

&lt;p&gt;Although there is no straightforward solution for automating this AMP quiz template, the fact that users can complete the quiz without leaving their inbox is a &lt;u&gt;&lt;strong&gt;clear win&lt;/strong&gt;&lt;/u&gt; 🏆.&lt;/p&gt;

</description>
      <category>email</category>
      <category>ampforemail</category>
      <category>html</category>
      <category>css</category>
    </item>
    <item>
      <title>🚫 Non-Image Approach to Data Viz in Email</title>
      <dc:creator>benjamin</dc:creator>
      <pubDate>Mon, 13 Mar 2023 00:48:51 +0000</pubDate>
      <link>https://dev.to/bdjang/non-image-approach-to-data-viz-in-email-o0k</link>
      <guid>https://dev.to/bdjang/non-image-approach-to-data-viz-in-email-o0k</guid>
      <description>&lt;p&gt;HTML emails have a limited toolbox for data visualization. Sophisticated tools such as &lt;a href="https://d3js.org/" rel="noopener noreferrer"&gt;D3.js&lt;/a&gt; are not available to use in email development. As a result, images have become the most common method for displaying data in emails.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This route comes with a number of disadvantages&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;not accessible to screen readers (unless the &lt;code&gt;&amp;lt;alt&amp;gt;&lt;/code&gt; tag is used properly)&lt;/li&gt;
&lt;li&gt;image auto-loading turned off prevents users from seeing data visuals&lt;/li&gt;
&lt;li&gt;not dark mode compatible&lt;/li&gt;
&lt;li&gt;contributes to total email load time especially when images are not optimized&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Is there an alternative way to display data in email templates that do not rely on images? Can emails feature clear, colorful, and engaging data visuals without images?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Yes, through the use of &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt; elements, you can create versatile horizontal bar charts, vertical bar charts, and progress bars. This method has distinct advantages and disadvantages compared to using images.&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Let's Build a Bar Chart Using &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt; Elements
&lt;/h3&gt;

&lt;p&gt;Start with a &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt; element and &lt;code&gt;&amp;lt;td&amp;gt;&lt;/code&gt; cells for the data bar name, data bar, and end label. In this chart example, the name and end label will be place outside the data bar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;table&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"600"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;Data bar #1&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Data bar name --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Data bar --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;Label #1&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- End label --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Define the &lt;code&gt;height&lt;/code&gt; and &lt;code&gt;width&lt;/code&gt; for each &lt;code&gt;&amp;lt;td&amp;gt;&lt;/code&gt; cell.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;table&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"600"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"background-color: #ffffff; height: 24px; width: 20%;"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"24"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"20%"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Data bar #1&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"background-color: #0dbd67; height: 24px; width: 65%;"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"24"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"65%"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"background-color: #ffffff; height: 24px; width: 15%;"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"24"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"15%"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Label #1&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F6575035%2F163897218-beb5f43c-50f9-4d1e-92b8-82ffa5e10beb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F6575035%2F163897218-beb5f43c-50f9-4d1e-92b8-82ffa5e10beb.png" alt="databar1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Adjust the width values to change the size of the data bar. Since all three columns are sharing the width percentage, make sure all &lt;code&gt;&amp;lt;td&amp;gt;&lt;/code&gt; cells add up to 100%.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;table&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"600"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"background-color: #ffffff; height: 24px; width: 20%;"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"24"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"20%"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Data bar #1&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"background-color: #0dbd67; height: 24px; width: 35%;"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"24"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"35%"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- The data bar width was reduced from 65% to 35%. The difference is added to the `&amp;lt;td&amp;gt;` cell below. --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"background-color: #ffffff; height: 24px; width: 45%;"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"24"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"45%"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Label #1&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To create a second data bar, nest the code within new &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;tr&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;td&amp;gt;&lt;/code&gt; elements. This will allow you to have more control over the spacing between each horizontal data bar. Adjust the spacing using padding within the outer &lt;code&gt;&amp;lt;td&amp;gt;&lt;/code&gt; cell.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"padding: 0 0 2px 0;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;table&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"600"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"background-color: #ffffff; height: 24px; width: 20%;"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"24"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"20%"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Data bar #1&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"background-color: #0dbd67; height: 24px; width: 35%;"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"24"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"35%"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"background-color: #ffffff; height: 24px; width: 45%;"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"24"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"45%"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Label #1&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"padding: 0 0 2px 0;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;table&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"600"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"background-color: #ffffff; height: 24px; width: 20%;"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"24"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"20%"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Data bar #2&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"background-color: #0d5fbd; height: 24px; width: 65%;"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"24"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"65%"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;td&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"background-color: #ffffff; height: 24px; width: 15%;"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"24"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"15%"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Label #2&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F6575035%2F163897313-4fa95403-3ad9-4c1a-982e-e11b32fc472c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F6575035%2F163897313-4fa95403-3ad9-4c1a-982e-e11b32fc472c.png" alt="databar2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now repeat the &lt;code&gt;&amp;lt;tr&amp;gt;&lt;/code&gt; sections for each individual data bar and adjust the &lt;code&gt;background-color&lt;/code&gt;, widths, and labels for each &lt;code&gt;&amp;lt;td&amp;gt;&lt;/code&gt; cell for this bar chart.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F6575035%2F224177769-686e143f-4253-4917-8df7-e760e17620b4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F6575035%2F224177769-686e143f-4253-4917-8df7-e760e17620b4.png" alt="barchart1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is one example of how &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt; elements can be used to create a horizontal bar chart.&lt;/p&gt;




&lt;h3&gt;
  
  
  Advantages of HTML/CSS Bar Charts
&lt;/h3&gt;

&lt;p&gt;Charts built using &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt; elements have a number of advantages over images:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;charts can be mobile responsive through the use of media queries and font-size adjustment&lt;/li&gt;
&lt;li&gt;load times of charts are faster compared to downloading images&lt;/li&gt;
&lt;li&gt;HTML/CSS coded charts use live text, numbers, and labels, which can be picked up by screen readers&lt;/li&gt;
&lt;li&gt;charts can be viewed without having to download any images&lt;/li&gt;
&lt;li&gt;can be dynamic. Since data bar widths, chart numbers, label text, and colors are coded in HTML/CSS, these fields can be set as variables within ESPs and dynamically rendered using updated JSON data&lt;/li&gt;
&lt;li&gt;charts are more compatible in dark mode compared to images&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages of HTML/CSS Bar Charts
&lt;/h3&gt;

&lt;p&gt;However, there are some disadvantages with coded bar charts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;only horizontal and vertical bar charts and progress bars can be created through this method. For more complicated charts (i.e. circle graphs, highly detailed, complex charts), images are the &lt;u&gt;only option&lt;/u&gt;
&lt;/li&gt;
&lt;li&gt;adds to overall email file weight which risks Gmail clipping if 102KB threshold is surpassed&lt;/li&gt;
&lt;li&gt;time consuming and complicated to code and build individual charts&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Images are not the only way to display clear, colorful, and engaging data visuals in email. Through the use of &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt; elements, emails can feature versatile horizontal and vertical bar charts, and progress bars.&lt;/p&gt;

</description>
      <category>email</category>
      <category>html</category>
      <category>css</category>
      <category>datavisualization</category>
    </item>
    <item>
      <title>Exploring Dark Mode in ⚡AMP Email</title>
      <dc:creator>benjamin</dc:creator>
      <pubDate>Wed, 02 Nov 2022 00:34:16 +0000</pubDate>
      <link>https://dev.to/bdjang/exploring-dark-mode-in-amp-email-5gm7</link>
      <guid>https://dev.to/bdjang/exploring-dark-mode-in-amp-email-5gm7</guid>
      <description>&lt;h2&gt;
  
  
  Purpose
&lt;/h2&gt;

&lt;p&gt;This post will investigate potential solutions for dark mode support in &lt;a href="https://amp.dev/about/email/" rel="noopener noreferrer"&gt;AMP email&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does AMP Email Support Dark Mode?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No, there is no dark mode support.&lt;/strong&gt; AMP email &lt;a href="https://amp.dev/documentation/guides-and-tutorials/learn/email-spec/amp-email-css/?format=email#media-features" rel="noopener noreferrer"&gt;does not support&lt;/a&gt; the &lt;code&gt;prefers-color-scheme&lt;/code&gt; media feature which is used to apply custom CSS styles for dark mode.&lt;/li&gt;
&lt;li&gt;Also, there are no default dark mode styles that automatically apply to AMP email templates. Users who set "dark mode" in their devices will view the same AMP template without any adjustments to the background color or fonts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Main Question
&lt;/h2&gt;

&lt;p&gt;🤔 Despite this current situation, can AMP email still support dark mode?&lt;/p&gt;

&lt;p&gt;✅ Yes, by leveraging specific AMP components including &lt;code&gt;amp-bind&lt;/code&gt;, &lt;strong&gt;light/dark mode color schemes can be selected and applied dynamically within the AMP email template&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  How could this look in 🖥️ Gmail desktop?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fstf77a272w5equ4d4jon.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fstf77a272w5equ4d4jon.gif" alt="Gmail desktop browser dark mode demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ...and in 📱 Gmail app for iOS?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwxwhfuypi25istgj0rlt.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwxwhfuypi25istgj0rlt.gif" alt="Gmail app for iOS dark mode demo"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🔩 Creating a Dark Mode Option in AMP Email
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;amp-bind&lt;/code&gt; &lt;a href="https://amp.dev/documentation/components/amp-bind/?format=email" rel="noopener noreferrer"&gt;component&lt;/a&gt; allows "elements to mutate in response to user actions or data changes via data binding and simple JS-like expressions".&lt;/p&gt;

&lt;p&gt;Through &lt;code&gt;amp-bind&lt;/code&gt; and the &lt;code&gt;AMP.setState()&lt;/code&gt; action, users can select a light or dark mode option from a dropdown menu and apply custom CSS styles to the AMP template. Let's begin.&lt;/p&gt;

&lt;p&gt;1). Start with the &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; HTML element to create a dropdown menu. Define a &lt;code&gt;value&lt;/code&gt; attribute for each &lt;code&gt;&amp;lt;option&amp;gt;&lt;/code&gt; tag&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;select&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"lightMode"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Light Mode&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"darkMode"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Dark Mode&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;2). Use the &lt;code&gt;on&lt;/code&gt; attribute to create an &lt;a href="https://amp.dev/documentation/guides-and-tutorials/learn/amp-email-actions-and-events/?format=email" rel="noopener noreferrer"&gt;event handler&lt;/a&gt; with a &lt;code&gt;change&lt;/code&gt; event&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;on=&lt;/span&gt;&lt;span class="s"&gt;"change:"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"lightMode"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Light Mode&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"darkMode"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Dark Mode&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;3). Then add the &lt;code&gt;AMP.setState()&lt;/code&gt; method to &lt;a href="https://amp.dev/documentation/components/amp-bind/?format=email#updating-state-variables-with-amp.setstate()" rel="noopener noreferrer"&gt;update the value&lt;/a&gt; of the &lt;code&gt;mode&lt;/code&gt; state variable with the option's value when a &lt;code&gt;change&lt;/code&gt; event occurs&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;on=&lt;/span&gt;&lt;span class="s"&gt;"change:AMP.setState({ mode: event.value })"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"lightMode"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Light Mode&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"darkMode"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Dark Mode&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;4). Create an &lt;code&gt;&amp;lt;amp-state&amp;gt;&lt;/code&gt; &lt;a href="https://amp.dev/documentation/components/amp-bind/?format=email#%3Camp-state%3E-specification" rel="noopener noreferrer"&gt;element&lt;/a&gt; with an &lt;code&gt;id&lt;/code&gt; of &lt;code&gt;colorScheme&lt;/code&gt;. Declare JSON data and add state names of &lt;code&gt;lightMode&lt;/code&gt; and &lt;code&gt;darkMode&lt;/code&gt; with a state variable of &lt;code&gt;style&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;amp-state&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"colorScheme"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lightMode&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;style&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lightStyles&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;darkMode&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;style&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;darkStyles&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/amp-state&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;5). Define CSS styles for the &lt;code&gt;lightStyles&lt;/code&gt; and &lt;code&gt;darkStyles&lt;/code&gt; classes. These styles will target the background and font colors&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt; &lt;span class="nt"&gt;amp-custom&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;/* LIGHT/DARK MODE STYLES */&lt;/span&gt;
  &lt;span class="nc"&gt;.lightStyles&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nc"&gt;.darkStyles&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#202124&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;6). Assign the &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; element (or the element that wraps your entire email content) with the &lt;code&gt;[class]&lt;/code&gt; property and bind it to the &lt;code&gt;&amp;lt;amp-state&amp;gt;&lt;/code&gt; element using the &lt;code&gt;id&lt;/code&gt; of &lt;code&gt;colorScheme&lt;/code&gt;. The &lt;code&gt;colorScheme[mode].style&lt;/code&gt; expression updates the &lt;code&gt;class&lt;/code&gt; property&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;body&lt;/span&gt; &lt;span class="na"&gt;[class]=&lt;/span&gt;&lt;span class="s"&gt;"colorScheme[mode].style || ''"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Through these steps, we can create a CSS class for light mode and a CSS class for dark mode. When the user selects a color scheme, the specific CSS class, properties, and values are immediately applied to the AMP email template ⬇️&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx3s98rrbkdf5e8rmt99x.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx3s98rrbkdf5e8rmt99x.gif" alt="Dark mode simple demo"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🌙 AMP Email Dark Mode Demo
&lt;/h2&gt;

&lt;p&gt;Below is a demo featuring light/dark mode options. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;&lt;em&gt;NOTE: Copy &amp;amp; paste the HTML tab code into the &lt;a href="https://amp.gmail.dev/playground/" rel="noopener noreferrer"&gt;Gmail AMP Playground&lt;/a&gt; or the &lt;a href="https://playground.amp.dev/?mode=Responsive&amp;amp;runtime=amp4email#" rel="noopener noreferrer"&gt;amp.dev Playground&lt;/a&gt; for a more accurate demo experience!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/bdjang/embed/VwxgVKW?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  🚧 Areas for Improvement
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;In this specific use case, users must select the dark mode color scheme each time they receive an AMP email. &lt;strong&gt;An improved experience would allow users to select their preferred color scheme once and then apply it to future AMP emails.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;In the Gmail app for iOS, there is a noticeable white border when dark mode styles are applied.
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flggh8egp2iagsisk96q4.jpg" alt="AMP email displayed in Gmail app with unsightly white borders in dark mode"&gt;
I have not found a way to target and remove these white borders or expand the template's width to cover this area.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  🌗 Beyond Light and Dark Modes
&lt;/h3&gt;

&lt;p&gt;Since we have the freedom and control over defining the &lt;code&gt;background-color&lt;/code&gt; and &lt;code&gt;color&lt;/code&gt; values in each CSS class, this opens the door to creating color schemes that go beyond light and dark modes.&lt;/p&gt;

&lt;p&gt;Let's add a &lt;a href="https://randoma11y.com/" rel="noopener noreferrer"&gt;new color scheme&lt;/a&gt; called "Sunglow" that will apply &lt;code&gt;background-color: #032932&lt;/code&gt; and &lt;code&gt;color: #fbe707&lt;/code&gt; to the AMP template ⤵️&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;select&lt;/span&gt; &lt;span class="na"&gt;on=&lt;/span&gt;&lt;span class="s"&gt;"change:AMP.setState({ mode: event.value })"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"lightMode"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Light Mode&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"darkMode"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Dark Mode&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;option&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"sunMode"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Sunglow Mode&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;amp-state&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"colorScheme"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lightMode&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;style&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lightStyles&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;darkMode&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;style&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;darkStyles&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sunMode&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;style&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sunStyles&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/amp-state&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt; &lt;span class="nt"&gt;amp-custom&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="c"&gt;/* COLOR SCHEME STYLES */&lt;/span&gt;
  &lt;span class="nc"&gt;.lightStyles&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#1b1b1b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nc"&gt;.darkStyles&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#202124&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ffffff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nc"&gt;.sunStyles&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#032932&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fbe707&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsnt1cepxwyzvpb4avdv6.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsnt1cepxwyzvpb4avdv6.gif" alt="Sun mode AMP demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🔮 Looking Ahead
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Could providing multiple color schemes with varying contrasts help improve the user experience in AMP emails?&lt;/strong&gt; For example, the Twitter app currently provides &lt;a href="https://www.wired.com/story/twitter-dark-mode/" rel="noopener noreferrer"&gt;two versions of dark mode&lt;/a&gt;: "dim" vs "lights out".&lt;/p&gt;

&lt;p&gt;Through the &lt;code&gt;amp-bind&lt;/code&gt; method, AMP emails could provide different versions of dark mode as well. More research and work needs to be done on this front! ⚗️🔬&lt;/p&gt;




&lt;h3&gt;
  
  
  One Last (Important) Item: Logos in Dark Mode
&lt;/h3&gt;

&lt;p&gt;A common issue with dark mode involves images such as logos: &lt;strong&gt;when switching color schemes, logos can become obscured or can unintentionally stick out in dark mode&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2lfr8zysi3fd9t9lonfc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2lfr8zysi3fd9t9lonfc.png" alt="Logos in dark mode"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;❓ Is there a way to replace the original logo with a version that is more appropriate for dark mode in AMP email?&lt;br&gt;
✅ Yes, by &lt;strong&gt;using &lt;code&gt;[hidden]&lt;/code&gt; &lt;a href="https://amp.dev/documentation/components/amp-bind/?format=email#expressions" rel="noopener noreferrer"&gt;expressions&lt;/a&gt; and &lt;a href="https://amp.dev/documentation/components/amp-bind/?format=email#event-triggering-and-data" rel="noopener noreferrer"&gt;event triggering&lt;/a&gt;, the original logo can be replaced with a "dark mode" version&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Continuing off of the previous AMP email sample code:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;1). Add both a 🔳 light and 🔲 dark mode logo&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;header&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;amp-img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://YOUR-LIGHT-MODE-LOGO.png"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"48"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"40"&lt;/span&gt; &lt;span class="na"&gt;layout=&lt;/span&gt;&lt;span class="s"&gt;"fixed"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Light mode logo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/amp-img&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;amp-img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://YOUR-DARK-MODE-LOGO.png"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"48"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"40"&lt;/span&gt; &lt;span class="na"&gt;layout=&lt;/span&gt;&lt;span class="s"&gt;"fixed"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Dark mode logo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/amp-img&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;2). Create a &lt;code&gt;[hidden]&lt;/code&gt; &lt;a href="https://amp.dev/documentation/components/amp-bind/?format=email#binding-types" rel="noopener noreferrer"&gt;boolean expression&lt;/a&gt; comparing the value of &lt;code&gt;mode&lt;/code&gt; with the current AMP state value. When the expression evaluates to &lt;code&gt;false&lt;/code&gt;, the logo will no longer stay hidden and will become visible&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;header&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;amp-img&lt;/span&gt; &lt;span class="na"&gt;[hidden]=&lt;/span&gt;&lt;span class="s"&gt;"mode != 'lightMode'"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://YOUR-LIGHT-MODE-LOGO.png"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"48"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"40"&lt;/span&gt; &lt;span class="na"&gt;layout=&lt;/span&gt;&lt;span class="s"&gt;"fixed"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Light mode logo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/amp-img&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;amp-img&lt;/span&gt; &lt;span class="na"&gt;[hidden]=&lt;/span&gt;&lt;span class="s"&gt;"mode != 'darkMode'"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://YOUR-DARK-MODE-LOGO.png"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"48"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"40"&lt;/span&gt; &lt;span class="na"&gt;layout=&lt;/span&gt;&lt;span class="s"&gt;"fixed"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Dark mode logo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/amp-img&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;3). Add a separate &lt;code&gt;hidden&lt;/code&gt; attribute to the dark mode logo to prevent both logos from displaying upon initial email load&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;header&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;amp-img&lt;/span&gt; &lt;span class="na"&gt;[hidden]=&lt;/span&gt;&lt;span class="s"&gt;"mode != 'lightMode'"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://YOUR-LIGHT-MODE-LOGO.png"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"48"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"40"&lt;/span&gt; &lt;span class="na"&gt;layout=&lt;/span&gt;&lt;span class="s"&gt;"fixed"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Light mode logo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/amp-img&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;amp-img&lt;/span&gt; &lt;span class="na"&gt;hidden&lt;/span&gt; &lt;span class="na"&gt;[hidden]=&lt;/span&gt;&lt;span class="s"&gt;"mode != 'darkMode'"&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://YOUR-DARK-MODE-LOGO.png"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"48"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"40"&lt;/span&gt; &lt;span class="na"&gt;layout=&lt;/span&gt;&lt;span class="s"&gt;"fixed"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Dark mode logo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/amp-img&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now when the user selects dark mode, the appropriate logo will display:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4yy9r76fsakavur6cac8.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4yy9r76fsakavur6cac8.gif" alt="Replacing logos in dark mode"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🌃 Conclusion
&lt;/h2&gt;

&lt;p&gt;Through the use of &lt;code&gt;amp-bind&lt;/code&gt; and the &lt;code&gt;AMP.setState()&lt;/code&gt; action, users can select and apply a variety of color schemes to the AMP email template. Also, by leveraging &lt;code&gt;[hidden]&lt;/code&gt; expressions, images such as logos can be replaced with dark mode versions.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Although there is no support for the media feature &lt;code&gt;prefers-color-scheme&lt;/code&gt;, &lt;strong&gt;AMP email tools are available to help create customized color schemes experiences that can benefit email users&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>email</category>
      <category>ampforemail</category>
      <category>html</category>
      <category>css</category>
    </item>
  </channel>
</rss>
