Навіщо взагалі писати редактор самому
Здавалося б, навіщо? Є TinyMCE, Quill, CKEditor — готові рішення, які підключаються за п'ять хвилин. Але у власноруч написаного редактора є своя цінність, і не лише навчальна. Наприклад, власний простий онлайн редактор може бути частиною певного проекту - його можна адаптувати під конкретні потреби користувача на певному робочому місці. Ну а для тих хто навчається теж корисно - можна побачити одразу результат зробивши щось корисне.
Крім того ви точно знаєте, що в ньому відбувається. Жодних зайвих залежностей, жодного раптового оновлення, яке зламає вам форму введення. По-друге, для невеликих проєктів — блогів, нотаток, внутрішніх інструментів — повноцінна бібліотека часто є надмірністю. І по-третє, це просто корисна вправа: ви торкаєтесь DOM, подій, localStorage, роботи з виділенням тексту — усього того, що є основою сучасного фронтенду. Як результат:
- розумієте, як браузер працює з редагованим вмістом;
- практикуєте роботу з подіями та DOM-маніпуляціями;
- отримуєте готовий інструмент, який можна вбудувати в будь-який проєкт;
- вчитеся налагоджувати та вдосконалювати власний код.
Що ми будуємо
Наш редактор матиме панель із кнопками форматування (жирний, курсив, підкреслення, заголовки), поле для введення тексту та кнопку збереження в localStorage. Нічого зайвого — лише те, що справді потрібне для роботи.
Що таке contenteditable і чому це важливо
Атрибутcontenteditable="true"— це вбудований механізм браузера, який дозволяє будь-якому HTML-елементу стати редагованим. Коли ви встановлюєте цей атрибут наdiv, користувач може клікнути в нього і почати вводити текст, як у звичайному текстовому полі. При цьому зберігається вся HTML-структура: теги, форматування, вкладені елементи. Саме на цьому механізмі побудовані більшість WYSIWYG-редакторів у браузері.
Крок 1. HTML-структура
Починаємо з розмітки. Нам потрібна панель інструментів і область редагування. Все просто:
<!DOCTYPE html> <html lang="uk"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Простий веб-редактор</title> <link rel="stylesheet" href="style.css"> </head> <body> <div class="editor-wrapper"> <div class="toolbar"> <button data-cmd="bold" title="Жирний">Ж</button> <button data-cmd="italic" title="Курсив">К</button> <button data-cmd="underline" title="Підкреслення">П</button> <button data-cmd="formatBlock" data-val="h2" title="Заголовок">H2</button> <button data-cmd="formatBlock" data-val="p" title="Звичайний текст">P</button> <button data-cmd="insertUnorderedList" title="Список">UL</button> <button id="saveBtn">Зберегти</button> </div> <div class="editor" id="editor" contenteditable="true"> <p>Почніть вводити текст тут...</p> </div> </div> <script src="editor.js"></script> </body> </html>
Зверніть увагу на атрибут data-cmd — він зберігає команду, яку ми передамо в JavaScript. Це дозволяє уникнути купи окремих обробників для кожної кнопки.
Крок 2. Стилі CSS
Редактор має виглядати як редактор, а не як порожній блок на сторінці. Мінімальні стилі, які вже дають відчуття інструменту:
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: Arial, sans-serif;
background: #f0f2f5;
display: flex;
justify-content: center;
padding: 40px 20px;
}
.editor-wrapper {
width: 100%;
max-width: 800px;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 12px rgba(0,0,0,0.1);
overflow: hidden;
}
.toolbar {
display: flex;
flex-wrap: wrap;
gap: 6px;
padding: 10px 14px;
background: #f8f9fa;
border-bottom: 1px solid #e0e0e0;
}
.toolbar button {
padding: 6px 12px;
border: 1px solid #ccc;
border-radius: 4px;
background: #fff;
cursor: pointer;
font-size: 14px;
transition: background 0.2s;
}
.toolbar button:hover {
background: #e8e8e8;
}
#saveBtn {
margin-left: auto;
background: #4a90e2;
color: #fff;
border-color: #4a90e2;
}
#saveBtn:hover {
background: #357abd;
}
.editor {
min-height: 400px;
padding: 20px 24px;
font-size: 16px;
line-height: 1.7;
outline: none;
color: #333;
}
.editor h2 {
margin: 16px 0 8px;
font-size: 22px;
}
.editor p {
margin-bottom: 10px;
}
.editor ul {
padding-left: 24px;
margin-bottom: 10px;
}
Крок 3. JavaScript — логіка редактора
Тепер найцікавіше. Браузер має вбудований метод document.execCommand(), який виконує команди форматування для редагованих елементів. Так, технічно він вважається застарілим, але досі чудово працює в усіх браузерах і є ідеальним для навчальних цілей.
const editor = document.getElementById('editor');
const saveBtn = document.getElementById('saveBtn');
const toolbarBtns = document.querySelectorAll('.toolbar button[data-cmd]');
// Обробка кнопок форматування
toolbarBtns.forEach(btn => {
btn.addEventListener('click', () => {
const cmd = btn.dataset.cmd;
const val = btn.dataset.val || null;
document.execCommand(cmd, false, val);
editor.focus();
});
});
// Збереження в localStorage
saveBtn.addEventListener('click', () => {
localStorage.setItem('editorContent', editor.innerHTML);
alert('Збережено.');
});
// Завантаження збереженого контенту
window.addEventListener('load', () => {
const saved = localStorage.getItem('editorContent');
if (saved) {
editor.innerHTML = saved;
}
});
Декілька речей, на які варто звернути увагу. Після виклику execCommand ми повертаємо фокус у поле редактора — без цього кнопки "заберуть" фокус і форматування не застосується. Метод localStorage.setItem зберігає HTML-рядок, тому після перезавантаження сторінки весь вміст із форматуванням відновлюється.
Найважливіше в написанні власних інструментів — не намагатися одразу зробити все ідеально. Спочатку зробіть щось, що просто працює. Потім покращуйте. Саме так і виглядає реальна розробка.
Крок 4. Збираємо все разом і перевіряємо
На цьому етапі у вас вже є три файли: index.html, style.css та editor.js. Відкрийте index.html у браузері — редактор повинен працювати. Введіть текст, виділіть частину і натисніть "Ж" — текст стане жирним. Натисніть "Зберегти", перезавантажте сторінку — текст залишиться.
Якщо щось не працює, перше, що варто зробити — відкрити консоль браузера (F12) і подивитися на помилки. Найчастіша причина — помилка в шляху до файлу скрипта або CSS.
Як покращити редактор і що можна додати
Базова версія готова, але це лише початок. Редактор можна розвивати в багатьох напрямках, залежно від того, які навички ви хочете прокачати.
Додаткові кнопки форматування
Легко додати вирівнювання тексту, колір шрифту або виділення фону. Наприклад, для вирівнювання по центру достатньо додати кнопку з data-cmd="justifyCenter". Для кольору шрифту — data-cmd="foreColor" із відповідним значенням кольору.
Лічильник символів
Корисна дрібниця, яку просто реалізувати. Додайте елемент під редактором і слухайте подію input:
editor.addEventListener('input', () => {
const text = editor.innerText;
document.getElementById('counter').textContent =
`Символів: ${text.length}`;
});
Експорт у текстовий файл
Ще одна зручна функція — можливість завантажити текст як файл:
document.getElementById('exportBtn').addEventListener('click', () => {
const blob = new Blob([editor.innerHTML], { type: 'text/html' });
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = 'document.html';
a.click();
});
Скасування та повтор дій
Браузер вже підтримує Ctrl+Z для скасування в contenteditable-елементах, але якщо ви хочете власну реалізацію — зберігайте стани редактора в масив і відновлюйте їх за потреби. Це трохи складніше, але дуже корисна вправа для розуміння роботи зі станом.
Серверне збереження
Якщо ви вже знайомі з базовим бекендом, можна додати збереження через fetch на сервер. Це відразу виводить редактор на новий рівень — вміст не зникне при очищенні браузера.
- Додайте кнопку "Зберегти на сервері".
- Відправляйте
editor.innerHTMLчерезfetchметодом POST. - На сервері збережіть у файл або базу даних.
- При завантаженні сторінки отримуйте збережений вміст через GET-запит.
Ось і весь шлях від порожнього файлу до працюючого редактора, який ви розумієте від першого рядка до останнього. Такий проєкт — чудовий старт для портфоліо початківця, бо він невеликий, але показує розуміння роботи з DOM, подіями і браузерним API. А якщо ви вирішите піти далі — вивчіть, як влаштовані бібліотеки Quill або Tiptap: там ті самі принципи, але реалізовані значно гнучкіше. Спробуйте додати до редактора хоча б одну нову функцію і розкажіть у коментарях, що у вас вийшло і з чим виникли труднощі.
Схожі публікації