<dialog> – діалоговий елемент
Елемент HTML <dialog>
представляє модальне або немодальне діалогове віконце або інший інтерактивний компонент, такий як віконце попередження, інспектор або підвікно.
Елемент HTML <dialog>
використовується для створення як модальних, так і немодальних діалогових віконець. Модальні діалогові віконця переривають взаємодію з іншою частиною сторінки, яка стає інертною, тоді як немодальні діалогові віконця дозволяють взаємодію з рештою сторінки.
Для виведення елемента <dialog>
повинен використовуватися JavaScript. Використовуйте метод .showModal()
, щоб показати модальне вікно, та метод .show()
, щоб показати немодальне вікно. Вікно можна закрити за допомогою методу .close()
або методу dialog
, коли подається елемент <form>
, вкладений в елемент <dialog>
. Модальні діалогові вікна також можна закрити, натиснувши клавішу Esc.
Атрибути
Цей елемент приймає глобальні атрибути.
[!WARNING] Атрибут
tabindex
не повинен використовуватися на елементі<dialog>
. Дивіться Примітки щодо застосування.
open
Вказує на те, що діалогове віконце – активне та доступне для взаємодії. Якщо атрибут
open
не задано, то це діалогове віконце не буде видимим для користувача. Рекомендовано використовувати для візуалізації діалогів методи.show()
або.showModal()
, а не атрибутopen
. Якщо<dialog>
відкрито за допомогою атрибутуopen
, то він буде немодальним.[!NOTE] Попри те, що можна перемикатися між відкритим і закритим станами немодальних діалогових віконець шляхом перемикання наявності атрибута
open
, цей підхід не рекомендується.
Примітки щодо застосування
- Елементи
<form>
можуть використовуватися для закривання діалогового віконця, якщо мають атрибутmethod="dialog"
або якщо кнопка, що використовується для подання такої форми, маєformmethod="dialog"
. Коли<form>
усередині<dialog>
подається за допомогою методуdialog
, діалогове віконце закривається, стани елементів керування форми зберігаються, але не подаються, а властивістьreturnValue
отримує значення кнопки, що була активована. - Псевдоелемент CSS
::backdrop
може використовуватися для оформлення задника модального діалогу, який виводиться під елементом<dialog>
, коли цей діалог виводиться за допомогою методаHTMLDialogElement.showModal()
. Наприклад, цей псевдоелемент можна використовувати для створення розмиття, затемнення чи ще якогось варіанту затуляння інертного вмісту під модальним діалогом. - Атрибут
autofocus
повинен бути доданий до елемента, щодо якого очікується, що користувач буде взаємодіяти з ним негайно після відкриття модального діалогу. Якщо жодний інший елемент не вимагає негайної взаємодії, то рекомендовано додатиautofocus
до кнопки закриття всередині діалогу, або самого діалогу, якщо очікується, що користувач клацне або натисне його, щоб закрити. - Не слід додавати до елемента
<dialog>
властивістьtabindex
, адже не очікується, що цей елемент може отримати фокус. Вміст діалогу, включно із кнопкою закриття, яка знаходиться всередині діалогу, може отримати фокус та бути інтерактивним.
Доступність
При реалізації діалогу важливо поміркувати про найкраще місце для перенесення фокуса користувача. Коли для відкриття <dialog>
використовується HTMLDialogElement.showModal()
, то фокус передається до першого вкладеного елемента, що приймає фокус. Явне задання розміщення початкового фокуса за допомогою атрибута autofocus
допомагає забезпечити те, що початковий фокус передається до елемента, що вважається найкращим положенням початкового фокуса в кожному конкретному діалозі. Коли є сумніви, оскільки не завжди відомо, де в діалозі можна розмістити початковий фокус, особливо в тих випадках, коли вміст діалогу візуалізується динамічно при його заклику, елемент <dialog>
сам може запропонувати найкраще положення початкового фокуса.
Слід забезпечити користувачів механізмом для закриття діалогу. Найнадійніший спосіб пересвідчитись, що всі користувачі можуть закрити діалог, – це додати явну кнопку для цього, наприклад, кнопку підтвердження, скасування чи закриття.
Усталено, діалог, закликаний методом showModal()
, може бути закритий шляхом натискання клавіші Esc. Немодальний діалог усталено не закривається клавішею Esc, і залежно від того, чим він фактично є, це може бути небажаним. Клавіатурні користувачі розраховують на те, що клавіша Esc закриває модальні діалоги; переконайтеся, що ця поведінка реалізована та підтримується. Якщо відкрито кілька модальних діалогів, то натискання клавіші Esc має закривати лише останній показаний діалог. Коли використовується <dialog>
, ця логіка надається браузером.
Попри те, що діалоги можна створювати за допомогою інших елементів, нативний елемент <dialog>
надає зручність і можливості доступності, які необхідно відтворювати, якщо для подібних потреб використовуються інші елементи. Якщо створюється власна реалізація діалогу, слід пересвідчитися, що всі очікувані усталені поведінки підтримуються, а також слід дотримуватися рекомендацій щодо правильних підписів.
Елемент <dialog>
видається браузерами у спосіб, подібний до саморобних діалогів, що використовують атрибут ARIA role="dialog". Елементи <dialog>
, закликані методом showModal()
, неявно мають aria-modal="true", а елементи <dialog>
, закликані методом show()
або виведені за допомогою атрибута open
або шляхом зміни усталеного display
<dialog>
, видається як [aria-modal="false"]
. При реалізації модальних діалогів усе, крім <dialog>
та його вмісту, повинно бути зроблено інертним за допомогою атрибута inert
. Коли використовується <dialog>
разом із методом HTMLDialogElement.showModal()
, ця поведінка надається браузером.
Приклади
Діалог з використанням лише HTML
Цей приклад демонструє створення немодального діалогу за допомогою лише HTML. У зв'язку з присутністю на елементі <dialog>
булевого атрибута open
, діалог відкривається при завантаженні сторінки. Його можна закрити, натиснувши кнопку "OK", оскільки атрибут method
на елементі <form>
має значення "dialog"
. У цьому випадку для закриття форми не потрібний JavaScript.
<dialog open>
<p>Вітання кожному та всім!</p>
<form method="dialog">
<button>OK</button>
</form>
</dialog>
Результат
[!NOTE] Перезавантажте сторінку, щоб скинути вивід.
Цей діалог зразу відкривається, завдяки присутності атрибута open
. Діалоги, виведені за допомогою атрибута open
, є немодальними. Коли клацнути "OK", цей діалог закривається, залишаючи фрейм Результату порожнім. Коли він закритий, вже немає методу його відкрити знову. З цієї причини, найкращим методом виведення немодальних діалогових віконець є використання методу HTMLDialogElement.show()
. Можна перемикати відображення діалогу, додаючи або видаляючи булевий атрибут open
, але це не рекомендований підхід.
Створення модального діалогу
Цей приклад демонструє модальний діалог з градієнтним задником. Метод .showModal()
відкриває цей модальний діалог, коли активується кнопка "Показати діалог". Його можна закрити, натиснувши клавішу Esc, або за допомогою методу close()
, коли активувати в діалозі кнопку "Закрити".
Коли діалог відкривається, усталено браузер передає фокус до першого елемента в діалозі, який може прийняти фокус. У цьому прикладі до кнопки "Закрити" застосовано атрибут <autofocus>
, щоб передати їй фокус, коли діалог відкривається, оскільки це елемент, з яким користувач буде взаємодіяти негайно після відкриття діалогу.
HTML
<dialog>
<button autofocus>Закрити</button>
<p>Цей модальний діалог має драйвовий задник!</p>
</dialog>
<button>Показати діалог</button>
CSS
Оформлювати задник можна за допомогою псевдоелемента ::backdrop
.
::backdrop {
background-image: linear-gradient(
45deg,
magenta,
rebeccapurple,
dodgerblue,
green
);
opacity: 0.75;
}
JavaScript
Цей діалог відкривається модально за допомогою методу .showModal()
і закривається за допомогою методу .close()
.
const dialog = document.querySelector("dialog");
const showButton = document.querySelector("dialog + button");
const closeButton = document.querySelector("dialog button");
// Кнопка "Показати діалог" відкриває діалог модально
showButton.addEventListener("click", () => {
dialog.showModal();
});
// Кнопка "Закрити" закриває діалог
closeButton.addEventListener("click", () => {
dialog.close();
});
Результат
Коли виводиться модальний діалог, він з'являється поверх усіх інших діалогів, що вже виведені. Все, що знаходиться поза цим модальним діалогом, стає інертним, а взаємодія поза діалогом блокується. Зверніть увагу, що коли діалог відкритий, то, за винятком самого діалогу, взаємодія з документом неможлива; кнопка "Показати діалог" здебільшого прихована майже непрозорим задником діалогу і є інертною.
Обробка поверненого значення з діалогу
Цей приклад демонструє returnValue
елемента <dialog>
і те, як закрити модальний діалог за допомогою форми. Усталено, returnValue
– це порожній рядок або значення кнопки, що подала форму в елементі <dialog>
, якщо така є.
Цей приклад відкриває модальний діалог, коли активується кнопка "Показати діалог". Цей діалог містить форму з елементом <select>
та двома елементами <button>
, які усталено мають type="submit"
. Слухач подій оновлює значення кнопки "Підтвердити", коли змінюється варіант вибору. Якщо кнопка "Підтвердити" активована для закриття діалогу, то поточне значення кнопки є значенням повернення. Якщо цей діалог закривається шляхом натискання кнопки "Скасувати", то returnValue
– це cancel
.
Коли діалог закривається, то повернене значення виводиться під кнопкою "Показати діалог". Якщо діалог закривається шляхом натискання клавіші Esc, то returnValue
не оновлюється, а подія close
не відбувається, тому текст в елементі <output>
не оновлюється.
HTML
<!-- Модальний діалог, що містить форму -->
<dialog id="favDialog">
<form>
<p>
<label
>Улюблена тварина:
<select>
<option value="default">Оберіть…</option>
<option>Артемія</option>
<option>Червона панда</option>
<option>Мавпа-павук</option>
</select>
</label>
</p>
<div>
<button value="cancel" formmethod="dialog">Скасувати</button>
<button id="confirmBtn" value="default">Підтвердити</button>
</div>
</form>
</dialog>
<p>
<button id="showDialog">Показати діалог</button>
</p>
<output></output>
JavaScript
const showButton = document.getElementById("showDialog");
const favDialog = document.getElementById("favDialog");
const outputBox = document.querySelector("output");
const selectEl = favDialog.querySelector("select");
const confirmBtn = favDialog.querySelector("#confirmBtn");
// Кнопка "Показати діалог" модально відкриває <dialog>
showButton.addEventListener("click", () => {
favDialog.showModal();
});
// Кнопка "Скасувати", оскільки є [formmethod="dialog"], закриває діалог без подання, запускаючи подію закриття.
favDialog.addEventListener("close", (e) => {
outputBox.value =
favDialog.returnValue === "default"
? "Немає поверненого значення."
: `Повернене значення: ${favDialog.returnValue}.`; // Необхідно перевіряти на "default", а не на порожній рядок
});
// Не дає кнопці "підтвердження" запустити усталену поведінку подання форми, а також закрити діалог методом `close()`, що запускає подію "close".
confirmBtn.addEventListener("click", (event) => {
event.preventDefault(); // Ми не хочемо подавати цю несправжню форму
favDialog.close(selectEl.value); // Тут необхідно надіслати значення віконця вибору.
});
Результат
Приклади вище демонструють наступні три методи закриття модальних діалогових віконець:
- Шляхом подавання форми всередині діалогу за допомогою методу
dialog
(як у прикладі діалогу з використанням лише HTML). - Шляхом натискання клавіші Esc.
- Шляхом виклику методу
HTMLDialogElement.close()
(як у прикладі модального діалогу). У цьому прикладі кнопка "Скасувати" закриває діалог за допомогою методу формиdialog
, а кнопка "Підтвердити" закриває діалог за допомогою методуHTMLDialogElement.close()
.
Кнопка "Скасувати" має атрибут formmethod="dialog"
, який перевизначає усталений метод GET
для тега <form>
. Коли метод форми – dialog
, стан форми зберігається, але не подається, а діалог закривається.
Коли action
немає, подання форми з усталеним методом GET
призводить до перезавантаження сторінки. Тут використовується JavaScript, щоб запобігти поданню та закрити діалог за допомогою методів event.preventDefault()
і HTMLDialogElement.close()
відповідно.
Важливо надавати механізм закриття в кожному елементі dialog
. Клавіша Esc усталено не закриває немодальні діалоги, і не можна виходити з того, що користувач взагалі має доступ до фізичної клавіатури (наприклад, це може бути користувач пристрою з сенсорним екраном, без доступу до клавіатури).
Закриття діалогу з обов'язковим полем форми
Коли форма всередині діалогу має обов'язкове поле, браузер дозволяє закрити такий діалог лише після введення значення для такого поля. Щоб закрити такий діалог, використовуйте або атрибут formnovalidate
на кнопці закриття, або викликайте метод close()
на об'єкті діалогу, коли клацають кнопку закриття.
<dialog id="dialog">
<form method="dialog">
<p>
<label>
Улюблена тварина:
<input type="text" required />
</label>
</p>
<div>
<input type="submit" id="normal-close" value="Закрити – нормально" />
<input
type="submit"
id="novalidate-close"
value="Закрити – novalidate"
formnovalidate />
<input type="submit" id="js-close" value="Закрити – JS" />
</div>
</form>
</dialog>
<p>
<button id="show-dialog">Показати діалог</button>
</p>
<output></output>
JavaScript
const showBtn = document.getElementById("show-dialog");
const dialog = document.getElementById("dialog");
const jsCloseBtn = dialog.querySelector("#js-close");
showBtn.addEventListener("click", () => {
dialog.showModal();
});
jsCloseBtn.addEventListener("click", (e) => {
e.preventDefault();
dialog.close();
});
Результат
Судячи з прикладу, неможливо закрити діалог за допомогою кнопки Закрити – нормально. Проте його можна закрити, якщо обійти валідацію форми за допомогою атрибута formnovalidate
на кнопці Скасувати. Програмно – dialog.close()
також закриває такий діалог.
Анімування діалогів
Елементи <dialog>
отримують display: none;
, коли приховані, і display: block;
, коли показані, а також вилучаються чи додаються до вищого шару та дерева доступності. Тому для анімування елементів <dialog>
властивість display
повинна бути придатною для анімування. Браузери, що це підтримують, анімують display
з варіацією на дискретному типі анімації. А саме, браузер перемикається між none
та іншим значенням display
так, щоб анімований вміст був видимим протягом усієї тривалості анімації.
Отже, наприклад:
- Коли
display
анімується відnone
доblock
(чи іншого видимого значенняdisplay
), значення перемикається наblock
на0%
тривалості анімації, щоб воно було видимим протягом усієї анімації. - Коли
display
анімується відblock
(чи іншого видимого значенняdisplay
) доnone
, значення перемикається наnone
на100%
тривалості анімації, щоб воно було видимим протягом усієї анімації.
[!NOTE] При анімуванні за допомогою Переходів CSS, для ввімкнення логіки, описаної вище, необхідно задати
transition-behavior: allow-discrete
. Ця поведінка усталено доступна при анімуванні за допомогою Анімацій CSS; іншого еквівалентного кроку не потрібно.
Переходи елементів діалогу
При анімуванні елементів <dialog>
за допомогою Переходів CSS необхідні такі речі:
- Директива
@starting-style
Задає набір стартових значень для властивостей, що задаються на
<dialog>
, від яких повинен відбуватись перехід щоразу, коли діалог відкривається. Це необхідно для уникання неочікуваної поведінки. Усталено переходи CSS відбуваються лише тоді, коли властивість змінюється з одного значення на інше на видимому елементі; вони не запускаються при першому оновленні стилю елементів, або коли типdisplay
змінюється зnone
на інший тип.- Властивість
display
Додайте
display
до списку переходу, щоб<dialog>
залишався якdisplay: block
(або інше видиме значенняdisplay
, задане на відкритому стані діалогу) протягом усієї тривалості переходу, забезпечуючи видимість інших переходів.- Властивість
overlay
Включіть до списку переходу
overlay
, щоб забезпечити відкладання вилучення<dialog>
з вищого шару до завершення переходу, що, знову таки, забезпечує видимість переходу.- Властивість
transition-behavior
Задайте на переходах
display
таoverlay
transition-behavior: allow-discrete
(або на скороченніtransition
), щоб увімкнути дискретні переходи на цих двох властивостях, які усталено не піддаються анімуванню.
Нижче – стислий приклад того, який вигляд це може мати.
HTML
HTML містить елемент <dialog>
, плюс кнопку для показу діалогу. Крім того, елемент <dialog>
містить іншу кнопку для закриття себе.
<dialog id="dialog">
Тут вміст
<button class="close">Закрити</button>
</dialog>
<button class="show">Показати модально</button>
CSS
У CSS додано блок @starting-style
, який визначає стартові стилі переходу для властивостей opacity
і transform
, кінцеві стилі переходу на стані dialog[open]
і усталені стилі на усталеному стані dialog
, до яких повертається перехід, як тільки <dialog>
з'являється. Зверніть увагу на те, що список transition
<dialog>
вміщає не тільки ці властивості, а й display
та overlay
, кожна з яких має allow-discrete
.
Також задано стартове значення стилю для властивості background-color
на ::backdrop
, який з'являється під <dialog>
, коли той відкривається, щоб забезпечити гарну анімацію затемнення. Селектор dialog[open]::backdrop
вибирає лише задники елементів <dialog>
, коли діалог відкритий.
/* Відкритий стан діалогу */
dialog[open] {
opacity: 1;
transform: scaleY(1);
}
/* Закритий стан діалогу */
dialog {
opacity: 0;
transform: scaleY(0);
transition:
opacity 0.7s ease-out,
transform 0.7s ease-out,
overlay 0.7s ease-out allow-discrete,
display 0.7s ease-out allow-discrete;
/* Рівносильно щодо
transition: all 0.7s allow-discrete; */
}
/* Стан перед відкриттям */
/* Цей блок повинен стояти після правила dialog[open], щоб подіяти,
оскільки специфічність однакова */
@starting-style {
dialog[open] {
opacity: 0;
transform: scaleY(0);
}
}
/* Перехід для :backdrop, коли діалогове модальне віконце виноситься на вищий шар */
dialog::backdrop {
background-color: rgb(0 0 0 / 0%);
transition:
display 0.7s allow-discrete,
overlay 0.7s allow-discrete,
background-color 0.7s;
/* Рівносильно щодо
transition: all 0.7s allow-discrete; */
}
dialog[open]::backdrop {
background-color: rgb(0 0 0 / 25%);
}
/* Це правило starting-style не може бути вкладено в селектор вище,
тому що вкладені селектори не можуть представляти псевдоелементи. */
@starting-style {
dialog[open]::backdrop {
background-color: rgb(0 0 0 / 0%);
}
}
JavaScript
JavaScript додає до кнопок показу та закриття слухачі подій, змушуючи ці кнопки показувати та закривати <dialog>
, коли по них клацають:
const dialogElem = document.getElementById("dialog");
const showBtn = document.querySelector(".show");
const closeBtn = document.querySelector(".close");
showBtn.addEventListener("click", () => {
dialogElem.showModal();
});
closeBtn.addEventListener("click", () => {
dialogElem.close();
});
Результат
Цей код візуалізується так:
[!NOTE] Оскільки елементи
<dialog>
змінюютьdisplay: none
наdisplay: block
щоразу, коли показуються, то<dialog>
переходять від їхніх стилів@starting-style
до їхніх стилівdialog[open]
щоразу, коли відбувається перехід появи. Коли<dialog>
закривається, він переходить від свого стануdialog[open]
до усталеного стануdialog
.У таких випадках переходи стилю при появі та зникненні можуть бути різними. Дивіться доказ цього в нашому прикладі Демонстрації того, коли вживаються стартові стилі.
Анімування діалогів за допомогою ключових кадрів
Коли <dialog>
анімується за допомогою ключових кадрів, є деякі відмінності від переходів, які слід зауважити:
- Не задається
@starting-style
. - Значення
display
задається для ключового кадру; це буде значенняdisplay
для всієї анімації, або поки не зустрінеться інше значення display, відмінне відnone
. - Немає потреби явно вмикати дискретні анімації; в ключових кадрах немає еквівалента
allow-discrete
. - Немає потреби задавати всередині ключових кадрів
overlay
; анімаціяdisplay
обробляє анімування<dialog>
від показу до прихованості.
Погляньмо на приклад, щоб побачити, як це виглядає.
HTML
По-перше, HTML містить елемент <dialog>
, плюс кнопку для показу діалогу. Крім того, елемент <dialog>
містить іншу кнопку для закриття себе.
<dialog id="dialog">
Вміст тут
<button class="close">закрити</button>
</dialog>
<button class="show">Показати модально</button>
CSS
CSS Визначає ключові кадри для анімації між закритим і показаним станами <dialog>
, плюс анімацію появи для задника елемента <dialog>
. Анімації <dialog>
включають анімування display
, щоб забезпечити видимість ефектів анімації протягом усієї її тривалості. Зверніть увагу, що не було можливості анімувати зникнення задника: задник негайно вилучається з DOM, коли <dialog>
закритий, тому немає нічого, що можна було б анімувати.
dialog {
animation: fade-out 0.7s ease-out;
}
dialog[open] {
animation: fade-in 0.7s ease-out;
}
dialog[open]::backdrop {
animation: backdrop-fade-in 0.7s ease-out forwards;
}
/* Ключові кадри анімації */
@keyframes fade-in {
0% {
opacity: 0;
transform: scaleY(0);
display: none;
}
100% {
opacity: 1;
transform: scaleY(1);
display: block;
}
}
@keyframes fade-out {
0% {
opacity: 1;
transform: scaleY(1);
display: block;
}
100% {
opacity: 0;
transform: scaleY(0);
display: none;
}
}
@keyframes backdrop-fade-in {
0% {
background-color: rgb(0 0 0 / 0%);
}
100% {
background-color: rgb(0 0 0 / 25%);
}
}
body,
button {
font-family: system-ui;
}
JavaScript
Врешті-решт, JavaScript додає до кнопок слухачі подій, щоб мати змогу показувати та закривати <dialog>
:
const dialogElem = document.getElementById("dialog");
const showBtn = document.querySelector(".show");
const closeBtn = document.querySelector(".close");
showBtn.addEventListener("click", () => {
dialogElem.showModal();
});
closeBtn.addEventListener("click", () => {
dialogElem.close();
});
Результат
Цей код візуалізується так:
Технічний підсумок
Категорії вмісту | Потоковий вміст, розділовий корінь |
---|---|
Дозволений вміст | Потоковий вміст |
Пропуск тега | Жодного; як початковий, так і кінцевий теги – обов'язкові. |
Дозволені батьківські елементи | Всі елементи, що приймають потоковий вміст |
Неявна роль ARIA | dialog |
Дозволені ролі ARIA | alertdialog |
Інтерфейс DOM | HTMLDialogElement |
Специфікації
Специфікація |
---|
HTML Standard (HTML) # the-dialog-element |
Сумісність із браузерами
desktop | mobile | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
dialog
|
Chrome Full support 37 | Edge Full support 79 | Firefox Full support 98 | Internet Explorer No support Ні | Opera Full support 24 | Safari Full support 15.4 | WebView Android Full support 37 | Chrome Android Full support 37 | Firefox for Android Full support 98 | Opera Android Full support 24 | Safari on iOS Full support 15.4 | Samsung Internet Full support 3.0 |
open
|
Chrome Full support 37 | Edge Full support 79 | Firefox Full support 98 | Internet Explorer No support Ні | Opera Full support 24 | Safari Full support 15.4 | WebView Android Full support 37 | Chrome Android Full support 37 | Firefox for Android Full support 98 | Opera Android Full support 24 | Safari on iOS Full support 15.4 | Samsung Internet Full support 3.0 |
Дивіться також
- Інтерфейс
HTMLDialogElement
interface - Подія
close
інтерфейсуHTMLDialogElement
- Подія
cancel
інтерфейсуHTMLDialogElement
- Властивість
open
інтерфейсуHTMLDialogElement
- Глобальний атрибут елементів HTML
inert
- Псевдоелемент CSS
::backdrop
- Вебформи в області Навчання