28 CSS Input Field Designs

Email with Suggestions

When the user types `@`, common email domains are suggested in a keyboard-navigable dropdown. `aria-controls` + `aria-expanded` + `role="listbox"` make it a proper combobox.

Light JS MIT licensed

Email with Suggestions the 21st of 28 designs in the 28 CSS Input Field Designs collection. The design pairs CSS styling with a small amount of JavaScript for interactivity. Copy the HTML, CSS and JavaScript panels below into your project — the JS is self-contained, has zero dependencies, and is safe to drop into any framework (React, Vue, Svelte, plain HTML). The design honours prefers-reduced-motion and uses real semantic markup, so it ships accessibility-ready out of the box.

Live preview

Open in playground

The code

<label class="if-mail">
  <span class="if-mail-label">Work email</span>
  <span class="if-mail-wrap">
    <input
      id="if-mail-input"
      type="email"
      name="email"
      autocomplete="email"
      placeholder="[email protected]"
      aria-controls="if-mail-list"
      aria-expanded="false"
      aria-autocomplete="list"
    />
    <ul id="if-mail-list" class="if-mail-list" role="listbox" hidden></ul>
  </span>
</label>
.if-mail {
  display: grid;
  gap: 6px;
  width: 100%;
  max-width: 280px;
}

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

.if-mail-wrap {
  position: relative;
  display: block;
}

.if-mail 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.2s,
    border-radius 0.15s;
}

.if-mail input:focus {
  border-color: #2eb88a;
}

.if-mail input[aria-expanded="true"] {
  border-radius: 10px 10px 0 0;
  border-bottom-color: transparent;
}

.if-mail-list {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  margin: 0;
  padding: 4px;
  list-style: none;
  background: #1a1a22;
  border: 1px solid #2eb88a;
  border-top: 0;
  border-radius: 0 0 10px 10px;
  z-index: 10;
  max-height: 180px;
  overflow-y: auto;
}

.if-mail-list li {
  padding: 7px 10px;
  font:
    500 13px/1.2 system-ui,
    sans-serif;
  color: #cbd5e1;
  cursor: pointer;
  border-radius: 6px;
}

.if-mail-list li[aria-selected="true"],
.if-mail-list li:hover {
  background: rgba(46, 184, 138, 0.15);
  color: #fff;
}

.if-mail-list li b {
  color: #2eb88a;
  font-weight: 600;
}
// Email Suggestions — show common domains after the user types '@'
(function () {
  var input = document.getElementById("if-mail-input");
  var list = document.getElementById("if-mail-list");
  if (!input || !list) return;
  var DOMAINS = ["gmail.com", "outlook.com", "icloud.com", "protonmail.com", "fastmail.com"];
  var idx = -1;

  function close() {
    list.hidden = true;
    input.setAttribute("aria-expanded", "false");
    idx = -1;
  }
  function render(local) {
    list.innerHTML = "";
    DOMAINS.forEach(function (d) {
      var li = document.createElement("li");
      li.setAttribute("role", "option");
      li.innerHTML = (local || "") + "<b>@" + d + "</b>";
      list.appendChild(li);
    });
  }
  function open(local) {
    render(local);
    list.hidden = false;
    input.setAttribute("aria-expanded", "true");
  }
  function select(n) {
    var items = list.querySelectorAll("li");
    items.forEach(function (li) {
      li.removeAttribute("aria-selected");
    });
    idx = (n + items.length) % items.length;
    items[idx].setAttribute("aria-selected", "true");
  }

  input.addEventListener("input", function () {
    var v = input.value,
      at = v.indexOf("@");
    if (at >= 0) open(v.substring(0, at + 1));
    else close();
  });
  input.addEventListener("blur", function () {
    setTimeout(close, 150);
  });
  input.addEventListener("keydown", function (e) {
    if (list.hidden) return;
    var items = list.querySelectorAll("li");
    if (e.key === "ArrowDown") {
      e.preventDefault();
      select(idx + 1);
    } else if (e.key === "ArrowUp") {
      e.preventDefault();
      select(idx - 1);
    } else if (e.key === "Escape") {
      close();
    } else if (e.key === "Enter" && idx >= 0) {
      e.preventDefault();
      input.value = items[idx].textContent;
      close();
    }
  });
  list.addEventListener("mousedown", function (e) {
    var li = e.target.closest('li[role="option"]');
    if (li) {
      input.value = li.textContent;
      close();
    }
  });
})();

Search CodeFronts

Loading…