Исправляем contenteditable в Chrome: с <div> на <br>

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Если вам требуется предотвратить автоматическую вставку тегов <div> при нажатии на клавишу Enter внутри элемента contenteditable, примените следующий код на JavaScript:

JS
Скопировать код
document.addEventListener('keydown', function(e) {
  if (e.key === 'Enter' && !e.shiftKey) { // Обрабатываем нажатие клавиши Enter без Shift, чтобы не ломать создание нового абзаца
    document.execCommand('insertLineBreak'); // Заменяет div на br
    e.preventDefault(); // Нежелательные div больше не образуются
  }
});

Таким образом, вы предотвратите автоматическое создание тегов <div> при нажатии на Enter, заменив их на операцию insertLineBreak. Вот так вот программирование работает!

Кинга Идем в IT: пошаговый план для смены профессии

Улучшаем пользовательский опыт

Чтобы поведение contenteditable было прогнозируемо для пользователя, необходимо переопределить реакцию на клавишу Enter. По умолчанию этот ответ разный в разных браузерах, но мы можем оказать на это влияние. Вот как это сделать:

Вставляем <br>, а не блоковые элементы

Отключаем автоматическое создание блоков при формировании новой строки:

JS
Скопировать код
document.execCommand('insertHTML', false, '<br><br>');

Вместо использования insertLineBreak мы применяем insertHTML, вставляя два тега <br> и тем самым имитируя двойной перевод строки без лишнего блочного элемента.

Блокируем стандартное поведение

Препятствуем созданию ненужных элементов:

JS
Скопировать код
if (e.key === 'Enter') {
  e.preventDefault(); // Так div-элементы нам больше не помешают!
}

Вызов event.preventDefault() заставляет клавишу Enter подчиниться новым правилам и не создавать ненужных элементов.

Визуализация

Демонстрация процесса вставки <div> в contenteditable при нажатии на ENTER в браузере Chrome и способа его предотвращения:

Markdown
Скопировать код
До:
[✍️] -> [🔨 добавление <div>]

После:
[✍️] -> [🛑] -> [✏️ Продолжение без <div>]

Особенность: Мы установили стоп-сигнал 🛑, который блокирует автоматическое создание тега <div> в Chrome и заменяет его на операцию нажатия Enter.

JS
Скопировать код
document.execCommand('defaultParagraphSeparator', false, 'p');
// Меняем автоматическую вставку тега <div> на <p> в Chrome при нажатии клавиши Enter

Применение стилей CSS

Можно изменить поведение contenteditable, воспользовавшись несколькими способами оформления CSS:

Использование Inline-block

Для предотвращения автоматического создания тегов применим стиль:

CSS
Скопировать код
[contenteditable] {
  display: inline-block; /* Использование inline-block помогает нам в борьбе с автоматическими div */
}

Работа с пробелами и переносами

Используем CSS для корректного отображения пробелов и переводов строк:

CSS
Скопировать код
[contenteditable] {
  white-space: pre-wrap; /* Учитывает и переводы строк, и пробелы */
}

Управление курсором и устранение лишних <br>

Для контроля над положением курсора используем window.getSelection(). Для работы с тегами <br> обращаемся к JavaScript, чтобы поддерживать чистоту кода.

Проверка совместимости и особые случаи

Хоть и Chrome зачастую является предметом нашего внимания, не стоит забывать и о других браузерах. Ниже приведены несколько дополнительных примеров работы с DOM и CSS:

Совместимость с различными браузерами

Обязательно проверьте работу решения во всех ведущих браузерах, включая Firefox, Safari и Edge. Интерпретация contenteditable может отличаться в разных браузерах.

Работа с DocumentFragment и Range

Продвинутые методы управления DOM, такие как document.createDocumentFragment() и range.deleteContents(), в сочетании с range.insertNode(), обеспечивают точное позиционирование нового контента.

Настройка поведения контейнеров

С помощью свойств CSS, таких как background, margin и padding, можно настроить взаимодействие элемента contenteditable с окружающими элементами.

Полезные материалы

  1. contenteditable – HTML: HyperText Markup Language | MDN – Всё, что вы хотели знать о contenteditable.
  2. Dealing with Line Breaks on contentEditable DIV – Stack Overflow – Обсуждение удаления нежелательных тегов <div> на Stack Overflow.
  3. HTML Global contenteditable Attribute – Краткий обзор и примеры использования contenteditable.
  4. The contenteditable attribute | HTML5 Doctor – Глубокий анализ contenteditable.
  5. Medium – Анализ преимуществ и недостатков contenteditable.