Make Your Inputs Pop with the Typewriter Effect

Hi everyone - below is some code that shows off a typewriter effect to make an input more appealing/informative for someone to use :slight_smile:

Example with video here:

Full HTML, CSS, and JavaScript:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Foodoogle</title>
  <style>
    body {
      background-color: gold;
      display: grid;
      align-items: center;
      justify-items: center;
      height: 100vh;
      width: 100vw;

      margin: 0;
      padding: 0;
    }

    body {
      background-image: url("https://www.kirupa.com/images/yellowblob.svg");
      background-repeat: no-repeat;
      background-size: cover;
    }

    h1 {
      font-family: sans-serif;
      font-size: 72px;
      font-weight: bold;
      text-align: center;
      color: #5d4e00;
      margin-bottom: 60px;
    }

    #search {
      font-family: sans-serif;
      font-size: 20px;
      font-weight: bold;
      padding: 30px;
      padding-left: 70px;
      background-image: url(https://www.kirupa.com/icon/1f50d.svg);
      background-repeat: no-repeat;
      background-size: 30px;
      background-position: 20px center;
      border: none;
      box-shadow: #c5c5c5 0px 0px 10px;
      width: 300px;

      transition: box-shadow .2s ease-out;
    }

    #search:hover {
      box-shadow: #858585 0px 0px 20px;
    }

    #search:focus {
      box-shadow: #858585 0px 0px 40px;
    }

    #search::placeholder {
      color: #8c8c8c;
      font-weight: lighter;
    }

    .orange img {
      width: 50px;
      display: block;
      margin: 0 auto;
      margin-top: 100px;
    }
  </style>
</head>

<body>
  <div>
    <h1>Foodoogle</h1>
    <form id="infoForm">
      <input id="search" autocomplete="off" type="text">
    </form>
    <a class="orange" href="https://www.kirupa.com">
      <img src="https://www.kirupa.com/images/orange.png">
    </a>
  </div>

  <script>
    let words = ["pizza", "cheeseburger", "salad", "fried rice", "burrito", "spaghetti", "pho"];
    let wordToPrint = "";
    let letter = 0;
    let count = 0;
    let direction = "forward";

    let intervalID = null;
    let timeoutID = null;

    let placeholder = "Looking for something?";

    let inputField = document.querySelector("#search");

    inputField.addEventListener("focus", checkFocus, false);
    inputField.addEventListener("blur", checkFocus, false);

    function checkFocus(e) {
      if (e.type == "focus") {
        stopCycle();
      } else if (e.type == "blur") {
        startCycle();
      }
    }

    function cycle() {
      let word = words[count];

      if (direction == "forward") {
        if (letter < word.length) {
          wordToPrint += word[letter];
          updatePlaceholder(wordToPrint);

          letter++;
        } else {
          direction = "backward";

          clearInterval(intervalID);
          intervalID = setInterval(cycle, 100);
        }
      } else {
        if (wordToPrint.length > 0) {
          wordToPrint = wordToPrint.slice(0, -1);
          updatePlaceholder(wordToPrint);
        } else {
          startOver();
        }
      }
    }

    function startOver() {
      resetState();

      // start from the beginning of array if at the end
      if (count < words.length - 1) {
        count++;
      } else {
        count = 0;
      }

      intervalID = setInterval(cycle, 200);
    }

    function resetState() {
      letter = 0;
      wordToPrint = "";
      direction = "forward";

      clearTimeout(timeoutID);
      clearInterval(intervalID);
    }

    function startCycle() {
      if (inputField.value === "") {
        resetState();
        
        updatePlaceholder(placeholder);

        timeoutID = setTimeout(() => {
          intervalID = setInterval(cycle, 200);
        }, 3000);
      }
    }

    function stopCycle() {
      resetState();

      updatePlaceholder(placeholder);
    }

    function updatePlaceholder(text) {
      inputField.setAttribute("placeholder", text);
    }

    startCycle();
  </script>
</body>

</html> 

There will be a more detailed tutorial on this in the future, but until then, consider this a temporary placeholder :stuck_out_tongue:

Cheers,
Kirupa

1 Like