Атрибут contenteditable в HTML: редактируемые элементы

Атрибут contenteditable превращает любой элемент в поле для редактирования прямо в браузере: текст внутри него можно кликнуть и печатать, как в текстовом редакторе, без формы и без поля ввода. Это глобальный атрибут - его можно прописать ссылке, параграфу, ячейке таблицы или любому другому тегу.

HTML
<div contenteditable="true">Этот текст можно редактировать</div>

Атрибут contenteditable: что делает и какие у него значения

contenteditable - не булевый, а перечислимый атрибут: у него несколько допустимых значений, а не просто «есть» или «нет».

ЗначениеЧто происходит
trueЭлемент редактируется, форматирование при вставке сохраняется
"" (пустое значение)То же самое, что true - атрибут без значения и contenteditable="" равнозначны
falseЭлемент нередактируемый - значение по умолчанию для большинства тегов
plaintext-onlyТекст редактируется, но форматирование отключено: команды вроде «жирный» не действуют, а при вставке стили обрезаются

Короткую запись contenteditable без значения браузеры понимают как contenteditable="true" - писать значение явно не обязательно.

Пример: true и plaintext-only рядом

Результат

В режиме true форматирование применяется, в plaintext-only кнопка «жирный» не действует вовсе.

Наследование: вложенный элемент берёт поведение родителя

Если у элемента нет своего contenteditable или в нём записано что-то некорректное, он берёт поведение ближайшего предка: редактируемый родитель делает редактируемым и всё содержимое внутри. Но это можно переопределить в обратную сторону - вложенный элемент с contenteditable="false" остаётся нередактируемым, даже если находится внутри редактируемого родителя. Этим пользуются, когда часть блока должна остаться неприкосновенной - например, бейдж статуса или кнопка внутри редактируемой карточки.

Пример: защищённый фрагмент внутри редактируемого блока

HTML
<div contenteditable="true">
  Этот текст можно редактировать
  <span contenteditable="false">статус: черновик</span>
</div>
Результат

Текст редактируется, а бейдж с contenteditable="false" печать игнорирует - он не наследует true от родителя.

Как узнать, что текст изменился - событие input

У редактируемых элементов нет своего значения и события change, как у поля формы - вместо этого на любое изменение текста (набор, вставку, удаление) срабатывает обычное событие input. На нём удобно вешать счётчик символов, индикатор несохранённых правок или автосохранение черновика.

Пример: счётчик символов на событии input

HTML + JavaScript
<div id="box" contenteditable="true">Правьте меня</div>

box.addEventListener("input", function () {
  счётчик.textContent = box.textContent.length;
});
Результат

Каждое изменение текста - новое срабатывание input, счётчик обновляется сразу, без отдельной кнопки «Сохранить».

contenteditable и переход по Tab

Редактируемый элемент верхнего уровня сам попадает в очередь Tab без всякого tabindex - у него есть собственный фокус по умолчанию. А вот вложенный редактируемый элемент внутри другого редактируемого элемента в эту очередь не попадает: Tab останавливается только на внешнем блоке. Чтобы добраться клавиатурой и до вложенного, ему нужно явно прописать tabindex="0" - подробнее о том, как устроен порядок Tab, в статье про атрибут tabindex.

HTML
<div contenteditable="true">
  Внешний блок - есть фокус по Tab
  <div contenteditable="true">Вложенный блок - без tabindex="0" Tab его пропустит</div>
</div>

Частые ошибки с атрибутом contenteditable

С contenteditable чаще путают не сам атрибут, а то, что вокруг него приходится достраивать вручную.

ОшибкаЧто происходитКак исправить
Считают contenteditable булевым атрибутомУ него четыре разных значения (true, "", false, plaintext-only), а не просто присутствие или отсутствиеУказывать нужное значение явно, когда это не очевидный true по умолчанию
Ждут событие change, как у поля формыУ contenteditable его нет - изменения текста ловит событие input, оно и срабатывает на каждый набор символаПодписываться на input, а не на change
Думают, что текст из contenteditable сам отправится с формойТекст внутри contenteditable не становится значением поля - форма его не увидит без отдельного кодаКопировать содержимое в скрытое поле формы перед отправкой через JavaScript
Прописывают contenteditable без plaintext-only там, где нужен только обычный текстПользователь может вставить форматированный текст из буфера, и в разметке появятся чужие тегиИспользовать contenteditable="plaintext-only", если форматирование не нужно
Ожидают, что вложенный редактируемый блок попадёт в Tab-очередь самВложенные contenteditable-элементы Tab пропускает по умолчаниюДобавлять им tabindex="0" вручную

Шпаргалка по атрибуту contenteditable

ПравилоЧто запомнить
Где работаетНа любом теге (глобальный атрибут)
true / "" (без значения)Элемент редактируется, форматирование сохраняется
falseЭлемент нередактируемый (значение по умолчанию)
plaintext-onlyРедактируется только обычный текст, форматирование отключено
НаследованиеЭлемент без своего значения берёт поведение ближайшего предка
Защита фрагментаВложенный contenteditable="false" не наследует true от родителя
Событие при измененииinput - срабатывает на каждое изменение текста
Данные формыВ форму не попадают сами по себе, нужен отдельный код
Tab-очередьВерхний редактируемый элемент - в очереди по умолчанию, вложенный - только с tabindex="0"
Категория
Поделиться в социальных сетях

Отправить комментарий

0 Комментарии

Отправить комментарий (0)

#buttons=(Хорошо) #days=(20)

Мы используем файлы cookie для улучшения работы сайта. Подробнее
Хорошо
×