Back to CSS Input Fields Rotating Placeholder Light JS
Share
HTML
<label class="if-anim">
  <span class="if-anim-cap">Search</span>
  <input
    type="search"
    name="q"
    inputmode="search"
    placeholder="Search products…"
    aria-label="Search"
    data-if-rotate='["Search products…","Search docs…","Search people…","Search settings…"]'
  />
</label>
CSS
.if-anim {
  display: grid;
  gap: 6px;
  width: 100%;
  max-width: 280px;
}

.if-anim-cap {
  font-family: "JetBrains Mono", monospace;
  font-size: 10px;
  letter-spacing: 0.12em;
  color: #b8b6d4;
  text-transform: uppercase;
}

.if-anim input {
  width: 100%;
  box-sizing: border-box;
  padding: 12px 14px;
  background: #1a1a22;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 10px;
  color: #f0eeff;
  font:
    500 14px/1 system-ui,
    sans-serif;
  outline: none;
  transition:
    border-color 0.25s,
    background 0.2s;
}

.if-anim input:focus {
  border-color: #c084fc;
  background: #1f1f2a;
}

.if-anim input::placeholder {
  color: #b8b6d4;
  transition: opacity 0.25s ease;
}

.if-anim input.is-fading::placeholder {
  opacity: 0;
}
JS
// Rotating Placeholder — swap the input's placeholder attribute on a 2.5s loop
document.querySelectorAll("[data-if-rotate]").forEach(function (input) {
  var phrases;
  try {
    phrases = JSON.parse(input.getAttribute("data-if-rotate") || "[]");
  } catch (e) {
    phrases = [];
  }
  if (!phrases.length) return;
  var i = 0,
    paused = false;
  function tick() {
    if (paused || document.activeElement === input || input.value) return;
    input.classList.add("is-fading");
    setTimeout(function () {
      i = (i + 1) % phrases.length;
      input.setAttribute("placeholder", phrases[i]);
      input.classList.remove("is-fading");
    }, 250);
  }
  setInterval(tick, 2500);
  input.addEventListener("focus", function () {
    paused = true;
  });
  input.addEventListener("blur", function () {
    paused = !!input.value;
  });
});