Kodokon kodokon.com

Современный интерактивный HTML: dialog, details, popover, contenteditable

Замени свои UI-библиотеки нативными примитивами современного HTML: модальные диалоги, эксклюзивные аккордеоны, поповеры и редактируемые области.

10 мин · 3 вопросов

Открыть этот урок в Kodokon

<dialog> нативно решает то, что годами костылили библиотеки модальных окон. showModal() выносит элемент в верхний слой (top layer) - выше любого z-index -, делает остальную часть документа инертной (ни фокуса, ни кликов) и открывает псевдоэлемент ::backdrop. show(), наоборот, показывает немодальный диалог, без инертности и без подложки. Недавний атрибут closedby=any добавляет закрытие по клику снаружи.

HTML
<dialog id="confirm-dlg">
  <form method="dialog">
    <p>Delete this item?</p>
    <button value="cancel">Cancel</button>
    <button value="ok">Confirm</button>
  </form>
</dialog>
Форма с method=dialog закрывает диалог без сетевого запроса.

<form method=dialog> закрывает диалог без сетевой отправки: value нажатой кнопки становится dialog.returnValue, который можно прочитать в событии close. Клавиша Escape закрывает модальный диалог, сначала испустив событие cancel, которое ты можешь отменить через preventDefault(), если ввод ещё не закончен.

JAVASCRIPT
const dlg = document.getElementById("confirm-dlg");
dlg.showModal();
dlg.addEventListener("close", () => {
  console.log(dlg.returnValue); // "ok" or "cancel"
});
Получение выбора пользователя при закрытии.

API Popover покрывает меню, богатые подсказки и всплывающие уведомления без JavaScript: ставь popover на элемент и popovertarget на кнопку, а браузер сам займётся верхним слоем, лёгким закрытием (light dismiss: клик снаружи, Escape) и взаимным закрытием поповеров auto. В отличие от showModal(), поповер не делает страницу инертной. События beforetoggle и toggle позволяют отменить или отследить каждый переход.

HTML
<button popovertarget="user-menu">Menu</button>
<div id="user-menu" popover>
  <button>Profile</button>
  <button>Log out</button>
</div>
Полноценное меню, без единой строчки JavaScript.

<details> даёт доступное сворачиваемое содержимое без скрипта, а общий атрибут name создаёт эксклюзивную группу: открытие одного закрывает остальные. Событие toggle срабатывает там при каждой смене состояния. Со стороны редактирования contenteditable превращает любой элемент в область богатого ввода; его вариант plaintext-only запрещает любую разметку, а событие beforeinput выгодно заменяет устаревший API document.execCommand.

HTML
<details name="faq" open>
  <summary>Delivery time?</summary>
  <p>Within 48 hours.</p>
</details>
<details name="faq">
  <summary>Return policy?</summary>
  <p>Within 30 days.</p>
</details>
Общее name даёт нативный эксклюзивный аккордеон.

Проверка знаний

Убедись, что запомнил ключевые моменты этого урока.

  1. Что даёт showModal() по сравнению с show()?
    • Он блокирует выполнение JavaScript до закрытия диалога
    • Он помещает диалог в верхний слой, делает остальную часть документа инертной и включает ::backdrop
    • Он лишь запрещает прокрутку страницы
  2. Что даёт одинаковый атрибут name у нескольких <details>?
    • Они отправляются вместе в родительской форме
    • Ничего: name не является допустимым атрибутом у details
    • Эксклюзивный аккордеон: открытие одного автоматически закрывает остальные
  3. В чём поведенческая разница между поповером auto и поповером manual?
    • auto получает лёгкое закрытие (клик снаружи, Escape) и закрывает другие поповеры auto; manual остаётся открытым, пока его не закроют явно
    • manual нельзя поместить в верхний слой
    • auto открывается сам при загрузке страницы