Эмуляция <INPUT PLACEHOLDER> для <DIV CONTENTEDITABLE> на любой технологии HTML/CSS/JS? [РЕШЕНО]

Рейтинг: 0Ответов: 1Опубликовано: 17.06.2023

Пытаюсь сэмулировать заполнитель <input placeholder="..."> для <div contenteditable>.

Первое что приходит в голову: добавить ::before и после фокуса на редактируемом элементе <div ...> удалить содержащий его класс.

Проблема: Попробуйте запустить код и кликнуть на текст "Отредактируйте поле ...", как это делается с обычным <input type=text> - С фокусом все нормально, но текстовый курсор теряется. Предполагаю потому что клик был на ::before. Если же кликнуть в свободном месте(правее), все работает как ожидается - placeholder пропадает и курсор оказывается в поле, после чего можно сразу печатать.

Вопрос: Как достичь желаемого эффекта? Конечно без всяких дополнительных слоев. Может есть какой JS/API/CSS, позволяющий делать элемент ::before не перекрывающим своего родителя?

РЕШЕНО: Первым же комментарием от @Grundy CSS pointer-events: none;

const { createApp, ref } = Vue

const comp = {
  setup() {
    const showPh = ref(true)
    return {
      showPh
    }
  },
  template: `
   <div
      v-bind:class="['edit', {['edit-ph']: showPh}]"
      contenteditable="true"
      @focus="() => {showPh = false}"
      @blur="({target}) => {target.textContent = '';showPh = true}"
   ></div>

   <p>Для сброса надо кликнуть в любом месте.</p>`
}

createApp(comp).mount('#app')
body {
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  font-size: 24px;
}

.edit {
  border: solid 1px rgb(182, 182, 182);
  padding: 0.2em;
}

.edit-ph::before {
  position: relative;
  content: 'Отредактируйте поле ...';
  color: rgb(182, 182, 182);
  cursor: text;
  /* РЕШЕНИЕ */
  pointer-events: none;
}
<script src="https://unpkg.com/vue@next"></script>
<div id="app"></div>

Ответы

▲ 2Принят

можно выставить pointer-events: none у псевдо элемента, тогда клик по нему будет проигнорирован

const { createApp, ref } = Vue

const comp = {
  setup() {
    const showPh = ref(true)
    return {
      showPh
    }
  },
  template: `
   <div
      v-bind:class="['edit', {['edit-ph']: showPh}]"
      contenteditable="true"
      @focus="() => {showPh = false}"
      @blur="({target}) => {target.textContent = '';showPh = true}"
   ></div>

   <p>Для сброса надо кликнуть в любом месте.</p>`
}

createApp(comp).mount('#app')
body {
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  font-size: 24px;
}

.edit {
  border: solid 1px rgb(182, 182, 182);
  padding: 0.2em;
}

.edit-ph::before {
  pointer-events: none;
  position: relative;
  content: 'Отредактируйте поле ...';
  color: rgb(182, 182, 182);
  cursor: text;
}
<script src="https://unpkg.com/vue@next"></script>
<div id="app"></div>