Пока мы ждали новые продукты от Apple, новые продукты появились в стандартах веба. А это куда важнее: макбуки каждый раз примерно одинаковые, а возможности вашего браузера меняются существенно.
Сегодня говорим о новом элементе в спецификациях HTML — Dialog. Это новый нативный способ показывать диалоговые и модальные окна с корректной обработкой фокуса, управлением с клавиатуры и другими приятными вещами.
Какой такой диалог?
На сайтах есть два вида всплывающих окон — диалоговое и модальное.
- Диалоговое окно спрашивает что-то у пользователя, но не мешает ему пользоваться сайтом дальше.
- Модальное окно перетягивает на себя всё внимание и не даёт работать со страницей, пока ты не сделаешь то, что нужно этому окну, и не закроешь его.
Раньше, чтобы сделать такое окно, нужно было писать много кода: оформлять стили и прописывать в них поведение окна. Сейчас это можно сделать одним HTML-тегом и парой параметров.
Для наглядности возьмём настоящий код из нашего проекта с игрой «Найди пару». Сначала мы добавляли модальное окно на страницу и писали там замысловатую структуру из тегов:
<!-- модальное окно, которое появится после сбора всех пар -->
<div class="modal-overlay">
<div class="modal">
<!-- поздравительная надпись -->
<h2 class="winner">Победа!</h2>
<!-- кнопка перезапуска игры -->
<button class="restart">Сыграем ещё?</button>
</div>
</div>
Потом описывали характеристики и поведение каждого блока в стилях, чтобы они превратились в окно и работали так, как нам нужно:
/* настройки затемнения при выводе модального окна */
.modal-overlay {
/* затемняем экран */
background: rgba(0, 0, 0, 0.8);
/* располагаем окно по центру экрана */
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
/* настройки модального окна */
.modal {
position: relative;
width: 500px;
height: 300px;
max-height: 90%;
max-width: 90%;
min-height: 380px;
margin: 0 auto;
background: white;
top: 50%;
transform: translateY(-50%);
padding: 30px 10px;
}
/* настройки шрифта сообщения о победе */
.modal .winner {
font-size: 80px;
text-align: center;
color: #4d4d4d;
text-shadow: 0px 3px 0 black;
}
/* если ширина окна маленькая, делаем шрифт поменьше */
@media (max-width: 480px) {
.modal .winner {
font-size: 60px;
}
}
/* настройки кнопки перезапуска игры */
.modal .restart {
margin: 30px auto;
padding: 20px 30px;
display: block;
font-size: 30px;
border: none;
background: #4d4d4d;
background: linear-gradient(#4d4d4d, #222);
border: 1px solid #222;
border-radius: 5px;
color: white;
text-shadow: 0px 1px 0 black;
cursor: pointer;
}
/* меняем фон при наведении мышки на кнопку */
.modal .restart:hover {
background: linear-gradient(#222, black);
}
/* выравниваем надписи на модальном окне по центру */
.modal .message {
text-align: center;
}
В итоге получалось такое модальное окно с кнопкой, которое висит поверх всей страницы и предлагает сыграть ещё. Код рабочий, но очень громоздкий и сложный. Но модальные и диалоговые окна нужны всем, поэтому в HTML5 добавили поддержку нового тега — <dialog>.
Новое решение — использовать тег <dialog>
Тег <dialog> позволяет создавать диалоговые и модальные окна намного проще, чем раньше. Идея в том, что мы внутри этого тега прописываем сразу всё, что нам нужно на экране, а потом вызываем его, например, по нажатию на кнопку.
Допустим, мы хотим, чтобы у нас на странице было диалоговое окно с объяснением про типы данных. Для этого сначала добавим кнопку — окно появится, когда мы на неё нажмём:
<button id="open">Про типы данных</button>
Теперь ниже сразу напишем новый тег <dialog>, в котором сделаем объяснение про типы данных:
<dialog>
<p>
Когда начинаешь изучать JavaScript, сначала чувствуешь эйфорию: очень легко работать с переменными, не нужно следить за типами, просто назвал и пользуешься. Но с великой свободой приходит великая ответственность. Если вы только начинаете пользоваться этим языком, обратите внимание на нюанс с типами данных.
</p>
</dialog>
И теперь добавим простой скрипт в конец страницы, который покажет это диалоговое окно. Для этого будем использовать функцию document.querySelector() — это встроенная JavaScript-функция, которая не требует подключения внешних библиотек:
<script>
var dialog = document.querySelector('dialog')
// выводим диалоговое окно
document.querySelector('#open').onclick = function () {
dialog.showl()
}
</script>
Мы только что сделали модальное окно, не используя сложную систему блоков и вообще не используя CSS-код. Единственный минус этого окна — его невозможно закрыть. Исправим это и добавим внутрь тега <dialog> в самом конце кнопку закрытия:
<p>
<button id="close">Закрыть окно</button>
</p>
Теперь добавим в скрипт команду закрытия диалогового окна и привяжем её к новой кнопке:
// скрываем окно
document.querySelector('#close').onclick = function () {
dialog.close()
}
Настраиваем стили
Когда мы используем тег <dialog>, то стили нам нужны не для создания окна, а для обычной настройки его внешнего вида. Например, если мы хотим добавить скругления, отступы по краям и поменять фон и убрать рамку, достаточно добавить такой стиль:
<style type="text/css">
dialog {
margin: 10px;
background: lightblue;
border: none;
border-radius: 1rem;
}
</style>
Теперь диалоговое окно выглядит аккуратнее:
Модальное окно
Модальное окно не даёт работать со страницей до тех пор, пока его не закроешь (а диалоговое — даёт). Чтобы превратить обычное диалоговое окно в модальное, достаточно в скрипте изменить команду show() на showModal():
// выводим модальное окно
document.querySelector('#open').onclick = function () {
dialog.showModal()
}
Ещё немного поправим стили, чтобы модальное окно получилось по центру страницы:
<style type="text/css">
dialog {
margin: auto;
position: absolute;
top: 0; left: 0; bottom: 0; right: 0; background: lightblue;
border: none;
border-radius: 1rem;
}
</style>
Зачем это нужно
Новые команды в вёрстке — это способ сэкономить время и силы на написание и отладку кода. Чем проще код, тем проще с ним работать и поддерживать в дальнейшем. Можно писать всё по старинке, вручную, а можно освоить новые команды и делать всё проще и быстрее.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Диалоговое и модальное окно</title>
<style type="text/css">
dialog {
margin: auto;
position: absolute;
top: 0; left: 0; bottom: 0; right: 0; background: lightblue;
border: none;
border-radius: 1rem;
}
</style>
</head>
<body>
<button id="open">Про типы данных</button>
<dialog>
<p>
Когда начинаешь изучать JavaScript, сначала чувствуешь эйфорию: очень легко работать с переменными, не нужно следить за типами, просто назвал и пользуешься. Но с великой свободой приходит великая ответственность. Если вы только начинаете пользоваться этим языком, обратите внимание на нюанс с типами данных.
</p>
<p>
<button id="close">Закрыть окно</button>
</p>
</dialog>
<script>
var dialog = document.querySelector('dialog')
// выводим модальное окно
document.querySelector('#open').onclick = function () {
dialog.showModal()
}
// скрываем окно
document.querySelector('#close').onclick = function () {
dialog.close()
}
</script>
</body>
</html>