28 CSS Input Field Designs

Inline Edit

Click-to-edit text that swaps between a static value and an editable input. Saves on Enter, cancels on Escape, blurs to commit — the canonical pattern from Notion and Linear.

Light JS MIT licensed

Inline Edit the 23rd 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-edit">
  <span class="if-edit-label">Project name</span>
  <span class="if-edit-wrap" data-if-edit data-value="Aurora Dashboard">
    <span class="if-edit-display" tabindex="0" role="button" aria-label="Edit project name"
      >Aurora Dashboard</span
    >
    <input class="if-edit-input" type="text" value="Aurora Dashboard" hidden />
    <span class="if-edit-pencil" aria-hidden="true">✎</span>
  </span>
</label>
.if-edit {
  display: grid;
  gap: 6px;
  width: 100%;
  max-width: 280px;
}

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

.if-edit-wrap {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  background: transparent;
  border: 1px dashed transparent;
  border-radius: 8px;
  cursor: text;
  transition:
    background 0.15s,
    border-color 0.15s;
}

.if-edit-wrap:hover {
  background: rgba(124, 108, 255, 0.06);
  border-color: rgba(124, 108, 255, 0.2);
}

.if-edit-display,
.if-edit-input {
  font:
    600 14px/1.3 system-ui,
    sans-serif;
  color: #f0eeff;
  flex: 1;
  min-width: 0;
}

.if-edit-display {
  outline: none;
}

.if-edit-input {
  border: 0;
  outline: none;
  background: transparent;
  padding: 0;
}

.if-edit-pencil {
  font-size: 12px;
  color: #7a7899;
  opacity: 0;
  transition: opacity 0.15s;
}

.if-edit-wrap:hover .if-edit-pencil {
  opacity: 1;
}

.if-edit-wrap.is-editing {
  background: #1a1a22;
  border-color: #7c6cff;
  border-style: solid;
}

.if-edit-wrap.is-editing .if-edit-pencil {
  display: none;
}
// Inline Edit — click to edit, Enter saves, Escape cancels, blur commits
document.querySelectorAll("[data-if-edit]").forEach(function (wrap) {
  var display = wrap.querySelector(".if-edit-display");
  var input = wrap.querySelector(".if-edit-input");

  function enter() {
    wrap.classList.add("is-editing");
    display.hidden = true;
    input.hidden = false;
    input.value = display.textContent;
    input.focus();
    input.select();
  }
  function commit() {
    var v = input.value.trim();
    if (v) {
      display.textContent = v;
      wrap.dataset.value = v;
    } else {
      input.value = display.textContent;
    }
    exit();
  }
  function cancel() {
    input.value = display.textContent;
    exit();
  }
  function exit() {
    wrap.classList.remove("is-editing");
    input.hidden = true;
    display.hidden = false;
  }

  display.addEventListener("click", enter);
  display.addEventListener("keydown", function (e) {
    if (e.key === "Enter" || e.key === " ") {
      e.preventDefault();
      enter();
    }
  });
  input.addEventListener("blur", commit);
  input.addEventListener("keydown", function (e) {
    if (e.key === "Enter") {
      e.preventDefault();
      commit();
    }
    if (e.key === "Escape") {
      e.preventDefault();
      cancel();
    }
  });
});

Search CodeFronts

Loading…