<div class="wrapper flex">
  <div class="flex-center">
    <div id="question-box" class="flex-fixed question-box">
      <div class="answer-question">
        <h3>What is <span id="choice1"></span> + <span id="choice2"></span>?</h3>
      </div>
      <div class="flex answer-form">
        <div class="field">
          <input type="text" placeholder="Your choice here" id="answer" class="answer-input" pattern="\d*" />
          <img src="#" alt="" id="answer-image" class="answer-input__image"/>
        </div>
        <a href="#" id="answer-button" class="button button__submit">Submit</a>
      </div>
      <div id="answer-status" class="answer-status">
        <p class="mt-med answer-status__text">
          <small><em>Great Work! <a href="#" id="reset-question" class="answer-status__link">Try another?</a></em></small>
        </p>
      </div>
    </div>
  </div>
</div>
body {
  background: #eee;
  font-family: sans-serif;
  font: caption;
  color: #222;
  
  .ios & { font-family: "-apple-system", "HelveticaNeue", sans-serif }
}

h3 {
  font-weight: bold;
  font-size: 1.25em;
  margin-bottom: .5em;
}

small {
  // font-size: 90%;
}

em {
  font-style: italic;
}

.mt-med {
  margin-top: .5em;
}

.mr-sml {
  margin-right: .25em;
}

.wrapper {
  height: 100vh;
}

.flex {
  display: flex;
}

.flex-center {
  display: flex;
  box-align: center;
  align-items: center;
  justify-content: center;
  width: 100%;
}

.question-box {
  max-width: 300px;
  display: none;
  opacity: 0;
}

p {
  font-size: 1em;
}

input {
  border: 1px solid #999;
  padding: .75em;
  border-radius: 2px;
  transition: all .25s ease-in;
  box-shadow: inset 0 0 0;
  box-shadow: 0 0 2px #ddd;
  font-size: 1.1em;
  margin: 0 .5em 0 0;
  
  &:focus {
    outline: none;
    border: 1px solid #1CB4D9;
  }
}

.button {
  display: inline-block;
  text-decoration: none;
  padding: .75em 1em;
  border-radius: 2px;
  font-size: 1.1em;
  border: 0px;
  transition: all .1s ease-in;
  
  &:focus {
    outline: none;
  }
}

.button__submit {
  background-color: #15819C;
  color: #fff;
  
  &:hover {
    background-color: lighten(#15819C, 6%);
  }
  
  &:active,
  &.active {
    background-color: darken(#15819C, 6%);
    box-shadow: inset 0 0 2px darken(#15819C, 9%);
  }
}

.answer-form,
.answer-form:after {
  z-index: 10;
  position: relative;
}

.answer-question {
  opacity: 0;
}

.answer-status {
  opacity: 0;
  z-index: 5;
}

.answer-status__link {
  text-decoration: dotted;
  color: #1B9BBA;
}

.field {
  position: relative;
  
  .answer-input {
    position: relative;
  }
  
  .answer-input__image {
    position: absolute;
    display: none;
    opacity: 0;
    top: 7px;
    right: 12px;
  }
}

.input-correct input {
  border: 1px solid #44D24F;
}

.input-error input {
  border: 1px solid #D24444;
}
// set ios device for system font fallback
if (navigator.userAgent.match(/(ipad|iphone|ipod)/i) && !window.MSStream) {
  document.documentElement.className += " ios";
}

let question = {
  choice1: 0,
  choice2: 0,
  sum: 0
}

document.addEventListener("DOMContentLoaded", () => {
  // Cache all the document lookups
  const questionBox = document.getElementById('question-box');
  const answer = document.getElementById('answer');
  const answerButton = document.getElementById('answer-button');
  const resetQuestion = document.getElementById('reset-question');
  const choice1 = document.getElementById('choice1');
  const choice2 = document.getElementById('choice2');
  const field = document.querySelector('.field');
  const answerStatus = document.getElementById('answer-status');
  const answerImage = document.getElementById('answer-image');
  // Image SRCs for correct/incorrect
  const answerStatusImage = {
    correct: "https://s3-us-west-2.amazonaws.com/s.cdpn.io/48021/iconmonstr-check.svg",
    error: "https://s3-us-west-2.amazonaws.com/s.cdpn.io/48021/iconmonstr-x-mark.svg"
  }

  // Generate a random number given randRange
  const randomNumber = (randRange) => {
    return Math.floor(Math.random() * randRange) + 1;
  }
  
  // Reset the questions object with new values
  const setQuestionChoices = () => {
    question.choice1 = randomNumber(25);
    question.choice2 = randomNumber(25); 
    question.sum = question.choice1 + question.choice2;
  }

  // Change text on page using question object
  const setText = () => {
    choice1.textContent = question.choice1;
    choice2.textContent = question.choice2;
  }
  
  // Make a new quiz and make input value blank
  const newQuiz = () => {
    setQuestionChoices();
    setText();
    answer.value = '';
  }
  
  // Check to see if value is equal to question object sum
  const checkAnswer = (val) => {
    if (question.sum == val) {
      handleCorrect();
    } else {
      handleError();
    }
  };
  
  // handle correct answer
  const handleCorrect = () => {
    field.classList.add('input-correct');
    
    // animate the answer status
    answerStatus.classList.add('answer-status--show');
    animate({
      el: answerStatus,
      opacity: 1,
      translateY: [-30, 0],
      delay: 200
    });
    
    // animate the correct icon
    answerImageAnimation(answerStatusImage.correct);
  }
  
  // handle error answer
  const handleError = () => {
    field.classList.add('input-error');
    
    // animate the incorrect icon
    answerImageAnimation(answerStatusImage.error);
  }
  
  const answerImageAnimation = (img) => {
    answerImage.src = img;
    answerImage.style.display = "block";
    animate({
      el: answerImage,
      opacity: 1,
      scale: [0, 1],
      easing: "easeOutElastic 100",
      delay: 200
    });
  }
  
  // Finally! Let's make a new quiz.
  newQuiz();
  
  // animate the question box
  animate({
    el: questionBox,
    opacity: 1,
    scale: [0, 1],
    duration: 200,
    delay: 500,
    begin: show
  });
  
  // animate the question
  animate({
    el: document.querySelector('.answer-question'),
    opacity: 1,
    translateY: [30, 0],
    delay: 700
  });
  
  // initial change of question box to fade in
  const show = () => questionBox.style.display = "block";
  show();
  
  // Focus the input since it's the only on the page
  answer.focus();

  // Let's check the answer on click of the submit button
  answerButton.addEventListener('click', (event) => {
    checkAnswer(answer.value);
    event.preventDefault();
  });
  
  // Semi toggle submit button on enter keydown
  document.onkeydown = (e) => {
    e.keyCode == 13 ? answerButton.classList.add('active') : false;
  }
  
  // Untoggle submit active and check answer on enter
  document.onkeyup = (e) => {
    if(e.keyCode == 13) {
      answerButton.classList.remove('active');
      checkAnswer(answer.value)
    }
  }
  
  // Cleanup any state status of input
  const clearFieldStatus = () => {
    field.classList.remove('input-correct', 'input-error');
    animate({
      el: answerImage,
      scale: [1.25, 0],
      opacity: 0,
      delay: 100
    });
    
    // hide the answer status if in view
    if (answerStatus.classList.contains('answer-status--show')) {
      answerStatus.classList.remove('answer-status--show');
      animate({
        el: answerStatus,
        opacity: 0,
        translateY: [0, -30],
        delay: 500
      });
    }
    
  };
  
  // If the input is being changed & the field has a status
  answer.addEventListener('input', () => {
    if(answer.value.length && field.classList.contains('input-correct') || field.classList.contains('input-error')) {
      clearFieldStatus()
    } 
  });
  
  // make a new quiz!
  resetQuestion.addEventListener('click', () => {
    newQuiz();
    clearFieldStatus();
    answerStatus.classList.remove('answer-status--show');
    animate({
      el: answerStatus,
      opacity: 0,
      translateY: [0, -30],
      easing: "easeInElastic 100"
    });
  });
})
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://npmcdn.com/animateplus@1.3.2/animate.min.js