20 CSS Tags & Chips Designs

Tag Input

Type to add a chip; Backspace on empty input removes the last chip. Real autocomplete dropdown filtered live by input — the full filter-input pattern with aria-controls/expanded.

Light JS MIT licensed

Tag Input the 14th of 20 designs in the 20 CSS Tags & Chips 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

<div class="ctc-input">
  <ul class="ctc-input-chips" role="list"></ul>
  <input
    type="text"
    class="ctc-input-field"
    placeholder="Type a language…"
    aria-label="Add a language tag"
    aria-controls="ctc-input-list"
    aria-expanded="false"
    autocomplete="off"
  />
  <ul class="ctc-input-list" id="ctc-input-list" role="listbox" hidden></ul>
</div>
.ctc-input {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  padding: 6px 8px;
  width: 280px;
  background: #15151d;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 8px;
}

.ctc-input:focus-within {
  border-color: #7c6cff;
}

.ctc-input-chips {
  display: contents;
  list-style: none;
  margin: 0;
  padding: 0;
}

.ctc-input-chips li {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 6px 3px 10px;
  background: rgba(124, 108, 255, 0.18);
  color: #c4b5fd;
  border-radius: 4px;
  font:
    600 11px/1 system-ui,
    sans-serif;
}

.ctc-input-chips button {
  background: transparent;
  border: 0;
  padding: 0;
  width: 16px;
  height: 16px;
  color: inherit;
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
}

.ctc-input-field {
  flex: 1;
  min-width: 60px;
  background: transparent;
  border: 0;
  outline: none;
  color: #f0eeff;
  font:
    500 12px/1 system-ui,
    sans-serif;
  padding: 4px 0;
}

.ctc-input-field::placeholder {
  color: #b8b6d4;
}

.ctc-input-list {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  margin: 0;
  padding: 4px;
  list-style: none;
  background: #15151d;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 8px;
  z-index: 5;
  max-height: 160px;
  overflow: auto;
}

.ctc-input-list[hidden] {
  display: none;
}

.ctc-input-list li {
  padding: 6px 10px;
  border-radius: 4px;
  font:
    500 12px/1 system-ui,
    sans-serif;
  color: #c4b5fd;
  cursor: pointer;
}

.ctc-input-list li:hover,
.ctc-input-list li[aria-selected="true"] {
  background: rgba(124, 108, 255, 0.18);
  color: #fff;
}
(function () {
  var SUGGESTIONS = [
    "JavaScript",
    "TypeScript",
    "Python",
    "Go",
    "Rust",
    "Ruby",
    "Swift",
    "Kotlin",
    "Java",
    "C++",
    "Elixir",
    "Haskell",
  ];
  document.querySelectorAll(".ctc-input").forEach(function (root) {
    var chipsEl = root.querySelector(".ctc-input-chips");
    var input = root.querySelector(".ctc-input-field");
    var listEl = root.querySelector(".ctc-input-list");
    var chips = [];
    function render() {
      chipsEl.innerHTML = "";
      chips.forEach(function (c, i) {
        var li = document.createElement("li");
        var txt = document.createElement("span");
        txt.textContent = c;
        var btn = document.createElement("button");
        btn.type = "button";
        btn.setAttribute("aria-label", "Remove " + c);
        btn.textContent = "×";
        btn.addEventListener("click", function () {
          chips.splice(i, 1);
          render();
        });
        li.appendChild(txt);
        li.appendChild(btn);
        chipsEl.appendChild(li);
      });
    }
    function showList(items) {
      if (!items.length) {
        listEl.setAttribute("hidden", "");
        input.setAttribute("aria-expanded", "false");
        return;
      }
      listEl.innerHTML = "";
      items.forEach(function (s) {
        var li = document.createElement("li");
        li.setAttribute("role", "option");
        li.textContent = s;
        li.addEventListener("mousedown", function (e) {
          e.preventDefault();
          if (chips.indexOf(s) === -1) chips.push(s);
          input.value = "";
          render();
          showList([]);
        });
        listEl.appendChild(li);
      });
      listEl.removeAttribute("hidden");
      input.setAttribute("aria-expanded", "true");
    }
    input.addEventListener("input", function () {
      var q = input.value.trim().toLowerCase();
      if (!q) {
        showList([]);
        return;
      }
      var matches = SUGGESTIONS.filter(function (s) {
        return s.toLowerCase().includes(q) && chips.indexOf(s) === -1;
      }).slice(0, 6);
      showList(matches);
    });
    input.addEventListener("keydown", function (e) {
      if (e.key === "Enter") {
        e.preventDefault();
        var v = input.value.trim();
        if (v && chips.indexOf(v) === -1) {
          chips.push(v);
          input.value = "";
          render();
          showList([]);
        }
      } else if (e.key === "Backspace" && !input.value && chips.length) {
        chips.pop();
        render();
      } else if (e.key === "Escape") {
        showList([]);
      }
    });
    input.addEventListener("blur", function () {
      setTimeout(function () {
        showList([]);
      }, 150);
    });
  });
})();

Search CodeFronts

Loading…