Красивые всплывающие диалоговые окна.
Вступление.
Нельзя представить полноценные динамические страницы без красивых всплывающих окон — pop-up. Поэтому в этой статье мы рассмотрим несколько вариантов создания и появления pop-up на странице сайта. Не будем подробно останавливаться на том, что представляет из себя всплывающее окно. Со всей уверенность скажу, что вы неоднократно сталкивались с ними и знаете, что это такое.
Не будем ходить вокруг да около, а сразу приступим к делу — поставим задачу, что же мы хотим получить на выходе.
Итак, давайте создадим красивые всплывающие окна с эффектами анимации: fade
и slide
, которые будет применяться как к подложке (overlay), так и к самому окну. Для создания эффектов анимации будем использовать исключительно CSS3.
Также я уверен, что вам приходилось сталкиваться с ситуациями, когда на одной странице могли выводиться разные всплывающие окна, содержащие, соответственно, разную информацию. Такое часто встречается в лендингах, когда в одном pop-up содержится форма заказа, а в другом предлагают ввести данные для связи с вами. Давайте и мы с вами сделаем точно также.
Теперь настал черёд поговорить об управлении, которое мы сделаем для всплывающего окна.
-
Открытие всплывающего окна. Один и тот же pop-up может открываться по клику на разные интерактивные элементы, расположенные в разных местах страницы.
-
Закрытие всплывающего окна. Pop-up мы будем закрывать тремя способами:
— во-первых, стандартным способом, кликом по крестику в правом верхнем углу всплывающего окна;
— во-вторых, по клику на любое место экрана вне всплывающего окна, т. е., по оверлею, который перекрывает и затеняет контент страницы и, при этом, занимает всю площадь экрана, имея ширину и высоту равные 100%;
— в-третьих, клавишейEsc
.
Итак, вроде со всем определились и давайте теперь перейдём к созданию непосредственно всплывающего окна.
HTML-разметка всплывающего окна.
Мы не будем создавать сложную вёрстку на HTML. Создадим overlay, два всплывающих окна и по две кнопки для каждого pop-up, которые их будут открывать. Вёрстка будет практически одинаковая для всех вариантов анимации открытия и закрытия всплывающих окон.
Начнём с интерактивных элементов — кнопок, которые будут открывать наши всплывающие окна:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<div class="wrap"> <h1>Всплывающие окна.</h1> <h2>Анимация CSS3 fadeIn и fadeOut.</h2> <div class="flex"> <button type="button" class="btn btn-default" data-modal="modal_1">Показать popup 1</button> <button type="button" class="btn btn-success" data-modal="modal_2">Показать popup 2</button> </div> <div class="overlay" data-close=""></div> <div id="modal_1" class="dlg-modal dlg-modal-fade"> <span class="closer" data-close=""></span> <h3>Всплывающее окно 1</h3> </div> <div id="modal_2" class="dlg-modal dlg-modal-fade"> <span class="closer" data-close=""></span> <h3>Всплывающее окно 2</h3> </div> </div> |
Обратите внимание на атрибут [data-modal]
, который прописан у каждой кнопки. В нём указывается id
всплывающего окна, которое эта кнопка открывает.
Вы, наверное, заметили, что у некоторых элементов (<div class="overlay">
и <span class="closer">
) присутствует атрибут [data-close]
. С помощью этого атрибута можно определить все элементы на странице, которые могут закрыть всплывающие окна. В частности, <span class="closer">
— это крестик в правом верхнем углу соответствующего pop-up.
Таблица стилей для всплывающих окон.
Приведём здесь только стили, относящиеся к анимации на CSS3, всё-такие наша основная задача — прокачать скилл владения JavaScript. Чтобы таблица стилей была короче и читабельнее, вендорные префиксы я использовать не буду.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
.dlg-modal { width: 100%; max-width: 570px; height: 300px; opacity: 0; visibility: hidden; text-align: center; position: fixed; left: 50%; z-index: 10; padding: 35px 36px; background: #fff; border-radius: 10px; box-shadow: 0 0 20px rgba(0,0,0,0.85); } .dlg-modal-fade { top: 50%; transform: translate(-50%, -50%); } .dlg-modal-slide { top: -20px; transform: translate(-50%, -100%); visibility: visible; opacity: 1; } .fadeIn, .fadeOut, .slideInDown, .slideOutUp { animation-duration: 0.4s; animation-timing-function: linear; } @keyframes fadeIn { from { opacity: 0; visibility: hidden; } to { opacity:1; visibility: visible; } } .fadeIn { animation-name: fadeIn; opacity: 1; visibility: visible; } @keyframes fadeOut { from { opacity: 1; visibility: visible; } to { opacity:0; visibility: hidden; } } .fadeOut { animation-name: fadeOut; opacity: 0; visibility: hidden; } @keyframes slideInDown { from { top: -20px; transform: translate(-50%, -100%); } to { top: 50%; transform: translate(-50%, -50%); } } .slideInDown { animation-name: slideInDown; top: 50%; transform: translate(-50%, -50%); } @keyframes slideOutUp { from { top: 50%; transform: translate(-50%, -50%); } to { top: -20px; transform: translate(-50%, -100%); } } .slideOutUp { animation-name: slideOutUp; } |
Полный код таблицы стилей вы можете взять из архива. Отметим здесь только некоторые особенности.
И подложке, и всплывающему окну задано position: fixed;
. Для чего это необходимо? Во-первых, их позиционирование будет осуществляться относительно границ экрана, а не документа. Во-вторых, при прокручивании колёсика мыши, позиционирование overlay и pop-up останется неизменным.
Начальное и конечное положение всплывающих окон.
Продолжая разговор о позиционировании, остановимся подробнее на положении всплывающего окна. Открытое диалоговое окно должно находится по центру экрана не зависимо от разрешения экрана и размеров самого окна.
Управлять положением диалогового окна будем используя свойства CSS left
, top
, transform
.
Возникает вопрос, а где должны находится всплывающие окна в закрытом состоянии?
Если окно будет управляться анимацией fade
, то его изначальное положение также будет по центру экрана. Ещё раз посмотрим стили для этого окна:
1 2 3 4 5 6 7 8 |
.dlg-modal-fade { /* это свойство прописано для селектора .dlg-modal */ left: 50%; top: 50%; transform: translate(-50%, -50%); } |
Модальное окно, использующее анимацию с эффектом slide
, должно находиться за верхней границей экрана. Чтобы обеспечить такое позиционирование, нам необходимо использовать следующие стили:
1 2 3 4 5 6 7 8 |
.dlg-modal-slide { /* это свойство прописано для селектора .dlg-modal */ left: 50%; top: 0; transform: translate(-50%, -100%); } |
При таких значениях свойств top
и transform
нижняя граница всплывающего окна будет совпадать с верхней границей экрана. Но этого оказывается недостаточно. К модальному окну с помощью свойства box-shadow
добавляется тень с радиусом размытия 20px. Эта тень будет вылезать из-под верхней границы экрана.
Чтобы устранить этот недостаток нужно изменить значения свойства top
на -20px. Теперь с верхней границей экрана будет совпадать нижняя граница тени.
1 2 3 4 5 6 7 8 |
.dlg-modal-slide { /* это свойство прописано для селектора .dlg-modal */ left: 50%; top: -20px; transform: translate(-50%, -100%); } |
Хочу напомнить ещё раз, что совместное использование свойств CSS left
, top
, transform
с такими значениями, позволяет позиционировать всплывающее окно независимо от его размеров, а также от размеров экрана. Это делает наш код более гибким, независимым и универсальным.
Пишем JavaScript для управления всплывающими окнами с помощью CSS3.
И вот теперь мы добрались до самого главного — написания скрипта на чистом JavaScript, который будет управлять появлением и исчезновением всплывающих окон. Начнём, как обычно с ограничения области видимости и разместим скрипт в анонимной самозапускающейся функции.
1 2 3 4 5 6 |
;(function() { 'use strict'; })(); |
Первым делом, что нам нужно сделать — это объявить несколько констант и переменных, очень важных для нормального функционирования скрипта и присвоить им значения.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// коллекция всех элементов на странице, которые могут открывать всплывающие окна // их отличительной особенность является наличие атрибута '[data-modal]' const mOpen = document.querySelectorAll('[data-modal]'); // если нет элементов управления всплывающими окнами, прекращаем работу скрипта if (mOpen.length == 0) return; // подложка под всплывающее окно const overlay = document.querySelector('.overlay'), // коллекция всплывающих окон modals = document.querySelectorAll('.dlg-modal'), // коллекция всех элементов на странице, которые могут // закрывать всплывающие окна // их отличительной особенность является наличие атрибута '[data-close]' mClose = document.querySelectorAll('[data-close]'); // флаг всплывающего окна: false - окно закрыто, true - открыто let mStatus = false; |
Открытие всплывающего окна.
Теперь необходимо на каждый элемент из коллекции mOpen
повесить обработчик события. После срабатывания обработчика, мы определяем, какое именно окно должно быть открыто и запускаем функцию modalShow
, которая и откроет нужный нам pop-up. Обход коллекции сделаем используя метод for...of
, а регистрацию обработчика сделаем с помощью метода addEventListener
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
for (let el of mOpen) { el.addEventListener('click', function(e) { // используюя атрибут [data-modal], определяем ID всплывающего окна, // которое требуется открыть // по значению ID получаем ссылку на элемент с таким идентификатором let modalId = el.dataset.modal, modal = document.getElementById(modalId); // вызываем функцию открытия всплывающего окна, аргументом // является объект всплывающего окна modalShow(modal); }); } |
Рассмотрим теперь по шагам работу функции modalShow
.
-
1
Добавляем оверлею класс
.fadeIn
. Этот класс создаёт анимацию — плавное появление подложки в течение 0.4 сек. Предварительно (если есть) удаляем класс.fadeOut
. -
2
Определяем тип анимации появления всплывающего окна. Этот тип прописан в переменой
typeAnimate
. На этапе вёрстки, необходимо в самом низу страницы, перед тегом</body>
, но выше кода подключения js-скрипта, который мы сейчас пишем, добавить одну из двух строк, которые определяют тип анимации появления всплывающего окна:12345<script>var typeAnimate = 'fade';</script>// или<script>var typeAnimate = 'slide';</script>Если
typeAnimate === 'fade'
, добавляем объекту всплывающего окнаmodal
класс.fadeIn
, предварительно удалив (если есть) класс.fadeOut
.
ЕслиtypeAnimate === 'slide'
, то добавляем класс.slideInDown
, а удаляем класс.slideOutUp
. -
3
Поднимаем флаг
mStatus
, присваивая ему значениеtrue
. Этот флаг сообщает, что всплывающее окно открыто.
Полный код функции modalShow
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
function modalShow(modal) { // показываем подложку всплывающего окна overlay.classList.remove('fadeOut'); overlay.classList.add('fadeIn'); // определяем тип анимации появления всплывающего окна // убираем и добавляем классы, соответствующие типу анимации if (typeAnimate === 'fade') { modal.classList.remove('fadeOut'); modal.classList.add('fadeIn'); } else if (typeAnimate === 'slide') { modal.classList.remove('slideOutUp'); modal.classList.add('slideInDown'); } // выставляем флаг, обозначающий, что всплывающее окно открыто mStatus = true; } |
Итак, в результате работы нашей функции мы видим оверлей во всей размер экрана, затеняющий основной контент, и по центру экрана всплывающее окно.
Закрытие всплывающего окна.
Теперь нам нужно написать функцию, которая закроет и подложку, и pop-up.
В самом начале скрипта мы создали коллекцию элементов mClose
, клики по которым закроют всплывающее окно. Для этого необходимо повесить обработчик события на каждый элемент. Мы опять воспользуемся методами for...of
и addEventListener
. Если событие click
наступило, то вызывается функция modalClose
.
1 2 3 4 5 |
for (let el of mClose) { el.addEventListener('click', modalClose); } |
Ранее мы решили, что будем закрывать всплывающее окно не только по клику на элементы страницы, но и нажатием на клавишу Esc
. Давайте тогда и на неё повесим обработчик события, используя всё тот же метод addEventListener
.
1 2 3 |
document.addEventListener('keydown', modalClose); |
Наконец настало время разобраться с работой функции modalClose
. Сама по себе функция не сложная и напоминает функцию modalShow
. Основное отличие между ними в том, что код функции modalClose
находится внутри условия:
1 2 3 |
if (mStatus && ( !event.keyCode || event.keyCode === 27 ) ) { ... } |
Код функции начнёт выполняться, если есть открытое всплывающее окно (вот зачем нам был нужен флаг mStatus
) и нет события нажатия клавиши или нажата клавиша Esc
(её код — 27).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
function modalClose(event) { if (mStatus && ( event.type != 'keydown' || event.keyCode === 27 ) ) { // обходим по очереди каждый элемент коллекции modals (каждое всплывающее окно) // и в зависимости от типа анимации, используемой на данной странице, // удаляем класс анимации открытия окна и добавляем класс анимации закрытия for (let modal of modals) { if (typeAnimate == 'fade') { modal.classList.remove('fadeIn'); modal.classList.add('fadeOut'); } else if (typeAnimate == 'slide') { modal.classList.remove('slideInDown'); modal.classList.add('slideOutUp'); } } // закрываем overlay overlay.classList.remove('fadeIn'); overlay.classList.add('fadeOut'); // сбрасываем флаг, устанавливая его значение в 'false' // это значение указывает нам, что на странице нет открытых // всплывающих окон mStatus = false; } } |
Мы разобрались как открыть и закрыть красивое всплывающее окно с помощью анимации основанной на CSS3. Хочу добавить только, что по такому же принципу можно сделать появления pop-up из-за нижней или боковой границы окна браузера.
Комментарии
-
Комментарии должны содержать вопросы и дополнения по статье, ответы на вопросы других пользователей.
Комментарии содержащие обсуждение политики, будут безжалостно удаляться. -
Для удобства чтения Вашего кода, не забываейте его форматировать. Вы его можете подсветить код с помощью тега
<pre>
:
—<pre class="lang:xhtml">
- HTML;
—<pre class="lang:css">
- CSS;
—<pre class="lang:javascript">
- JavaScript. - Если что-то не понятно в статье, постарайтесь указать более конкретно, что именно не понятно.
-
Благодарю за Ваши статьи! Очень помогли, всё понятно и доступно!
-
Спасибо)))
Значит не зря я время потратил )))
-
-
Спасибо!
-
Класс! Спасибо за подробный разбор!
Хорошая статья. Очень подробно и доступно написано.