Задача. Добавить к текстовому полю функционал очистки значения. Если инпут не заполнен, то инпут отображается как обычно. Если заполнен, то добавляем к нему крестик, клик по которому приводит к очистке поля. Получиться должно что-то типа такого.

текстовое поле на котором есть кнопка очистки значения

Идея взята в одном из ответов на stackoverflow и немного доработана. А сама идея заключается в том, чтобы не усложнять разметку, не добавлять лишних элементов, а обойтись только самим инпутом.

Сам крестик добавляется к инпуту с помощью фоновой картинки. А кликабельность картинки имитируем с помощью небольшого скрипта. Зная координаты курсора в момент клика и позицию крестика внутри инпута, можно определить произошел клик по крестику либо вне его.

Итак, html разметка (функционал будет добавляться инпутам с классом zbz-input-clearable):

<input type="text" value="тест" class="zbz-input-clearable" />

Добавляем крестик

.zbz-input-clearable {
  /* ставим инпуту фоновую картинку, но отображаем ее за пределами инпута - 150% в background-position */
  background-image: url("input-clearable-x.png");
  background-position: 150% 50%;
  background-repeat: no-repeat;
  transition: background 0.4s;
  /* добавляем справа небольшой padding, чтоб текст не залазил поверх крестика */
  padding-right: 27px;
}
.zbz-input-clearable--x {
  /* когда нужно отобразить крестик, перемещаем в правый конец инпута */
  background-position: 100% 50%;
}
.zbz-input-clearable--x-over {
  /* и подготовим стиль для ховера по крестику */
  background-image: url("input-clearable-x-hover.png");
  cursor: pointer;
}
.zbz-input-clearable::-ms-clear {
  /* убираем родной крестик очистки в IE */
  display: none;
}

И потом немного скриптовой магии

(function ($) {
  var input_class = "zbz-input-clearable",
    input_class_x = input_class + "--x",
    input_class_x_over = input_class + "--x-over",
    input_selector = "." + input_class,
    input_selector_x = "." + input_class_x,
    input_selector_x_over = "." + input_class_x_over,
    event_main = input_class + "-init",
    event_names = [
      event_main,
      "focus drop paste keydown keypress input change",
    ].join(" "),
    btn_width = 13,
    btn_height = 13,
    btn_margin = 7;

  function tog(v) {
    return v ? "addClass" : "removeClass";
  }

  $(document).on(event_names, input_selector, function () {
    $(this)[tog(this.value)](input_class_x);
  });

  $(document).on("mousemove", input_selector_x, function (e) {
    var input = $(this),
      input_width = this.offsetWidth,
      input_height = this.offsetHeight,
      input_border_bottom = parseFloat(input.css("borderBottomWidth")),
      input_border_right = parseFloat(input.css("borderRightWidth")),
      input_border_left = parseFloat(input.css("borderLeftWidth")),
      input_border_top = parseFloat(input.css("borderTopWidth")),
      input_border_hr = input_border_left + input_border_right,
      input_border_vr = input_border_top + input_border_bottom,
      client_rect = this.getBoundingClientRect(),
      input_cursor_pos_x = e.clientX - client_rect.left,
      input_cursor_pos_y = e.clientY - client_rect.top,
      is_over_cross = true;

    is_over_cross =
      is_over_cross &&
      input_cursor_pos_x >=
        input_width - input_border_hr - btn_margin - btn_width;
    is_over_cross =
      is_over_cross &&
      input_cursor_pos_x <= input_width - input_border_hr - btn_margin;
    is_over_cross =
      is_over_cross &&
      input_cursor_pos_y >= (input_height - input_border_vr - btn_height) / 2;
    is_over_cross =
      is_over_cross &&
      input_cursor_pos_y <=
        (input_height - input_border_vr - btn_height) / 2 + btn_height;

    $(this)[tog(is_over_cross)](input_class_x_over);
  });

  $(document).on("click", input_selector_x_over, function () {
    $(this)
      .removeClass([input_class_x, input_class_x_over].join(" "))
      .val("")
      .trigger("input");
  });

  $(function () {
    $(input_selector).trigger(event_main);
  });
})(jQuery);

Пример