Всем привет! Я в веб-разработке не так давно. Сейчас я пишу свой сайт, который будет выступать в качестве моего портфолио и, возможно, даже целого проекта. При добавлении модального окна для авторизации на свой сайт, я подумал, а что будет, если публиковать подобные модульные вещи, чтобы любой человек мог их скопировать и не думать о них, а использовать в разработке. То есть создать готовый модуль для встраивания. Мне, как разработчику было бы удобно использовать готовое решение, тем более написанное мною, да и делиться опытом - дело приятное :)
Для тех, кому надо сразу код и вид окна.

NB
сам сайт скрыт для сохранения интеллектуальной собственности :)
А теперь пошаговое создание:
<div class="modalBackground"> <div class="modalActive"> <div class="modalClose"> <img src="modalCross.svg" /> </div> <div class="modalWindow"></div> </div> </div>
Здесь представлена несложная разметка для модального окна.
Перед разъяснением элементов и их стилей, мы укажем скрытие ползунка прокрутки для body, которое нам будет мешать:
/* убираем нижний ползунок прокрутки */ body { overflow-x: hidden; }
Давайте поясню, что есть что:
modalBackground - это фон, расположенный за модальным окном. Через него мы будем видеть наш сайт { background: rgba(0, 0, 0, 0.8); }, в то время как основной фокус будет на модальном окне. Для корректного расположения, чтобы наш фон покрывал весь сайт - мы делаем его с положением { position: fixed } и размерами на весь экран { width: 100%; height : 100%; }. А для наложения поверх других окон или элементов сайта - { z-index: 1 }. Стоит отметить, что изначально мы не можем видеть наше окно { display: none }. Для отображения возможности нажатия на фон - делаем указатель через { cursor: pointer; }
/* фон нашего модального окна */ .modalBackground { display: none; background: rgba(0, 0, 0, 0.8); position: fixed; width: 100%; height: 100%; cursor: pointer; /* указываем z-индекс для корректного наслаивания */ z-index: 1; }
modalActive - непосредственно наше модальное окно. Его размеры { width: 350px; height : 495px; } я подбирал исходя из удобства верстки для маленьких экранов, так что размеры можно указать свои. Мы позиционируем наше модальное окно по центру { position: absolute; top: calc(50% - 250px); left: calc(50% - 175px); }. Делаем рамки закругления в 10 пикселей { border-radius: 10px }. Курсор для удобства делаем стандартным { cursor: default }. Свойства background-color и padding в данном случае ни на что не влияют, они используются для фона нашего окошечка внутри и для внутренних отступов нашего окошечка соответственно. Поэтому их можно ставить на свой вкус и цвет :)
/* позиционирование самого модального окна */ .modalActive { position: absolute; width: 350px; height: 495px; top: calc(50% - 250px); left: calc(50% - 175px); border-radius: 10px; background-color: rgb(255, 255, 255); cursor: default; padding: 40px 20px; }
modalClose - это наш крестик. Я использовал два варианта выхода из модального окна, кому как удобнее - через нажатие на фон, либо через нажатие на крестик (этот вариант предпочтительнее для мобильных устройств из-за маленького экрана, по сравнению с монитором ноутбука/компьютера/планшета). Для крестика соответственно используется тег modalCross с указанием в img пути к картинке-крестика. Свойство font-family используется для выбора семейства шрифта, здесь оно не играет роли (на ваш вкус и цвет).
/* кнопочка закрытия модального окна */ .modalClose { font-family: var(--font-regular); position: absolute; right: 5px; top: 5px; width: 30px; height: 30px; cursor: pointer; } /* сама картинка кнопочки закрытия */ .modalClose img { margin: 3px; width: 24px; height: 24px; }
modalWindow - внутри него располагается содержимое нашего окна, для удобной верстки внутреннего содержимого устанавливаем относительное позиционирование относительно нашего модального окна { position: relative }. Какое оно будет - зависит только от вас :)
/* делаем позиционирование внутренних элементов относительно модального окна */ .modalWindow { position: relative; }
Теперь приступим к части оживления нашего окна с помощью жабаскрипта JS !
Прежде всего нам надо получить все элементы, с которыми нам предстоит работать:
// устанавливаем триггер для модального окна (название можно изменить) const modalTrigger = document.getElementsByClassName("trigger")[0]; // получаем ширину отображенного содержимого и толщину ползунка прокрутки const windowInnerWidth = document.documentElement.clientWidth; const scrollbarWidth = parseInt(window.innerWidth) - parseInt(document.documentElement.clientWidth); // привязываем необходимые элементы const bodyElementHTML = document.getElementsByTagName("body")[0]; const modalBackground = document.getElementsByClassName("modalBackground")[0]; const modalClose = document.getElementsByClassName("modalClose")[0]; const modalActive = document.getElementsByClassName("modalActive")[0];
Стоит отметить, что при использовании метода getElementsByClassName мы будем получать массив всех элементов. Поэтому для корректного обращения к конкретному элементу - мы указываем индекс получаемого элемента. А так как наши массивы состоят из одного элемента - индекс во всех случаях равен [0].
Переменная modalTrigger - содержит наш триггер, при нажатии на который у нас будет появляться наше модальное окно.
Если наш сайт длинный и у нас появляется ползунок прокрутки - мы получаем его длину и записываем в scrollbarWidth. Давайте тут поподробнее. Мы изначально получаем ширину видимой части сайта через свойство clientWidth. Ширина ползунка прокрутки - разность между шириной окна внутри и шириной отображаемого содержимого (то, что под ползунком - не является отображаемым содержимым). Для корректности мы преобразовываем полученные значения через функции parseInt.
Далее мы привязываем необходимые элементы к переменным в соответствии с названием их классов, для тега body мы используем метод getElementsByTagName с указанием индекса получаемого элемента, то есть [0]. Смысл такой же, как и при getElementsByClassName. Я заметил простую вещь - если читаешь название методов, то понимаешь что они тебе дают :). В нашем случаем мы получаем множество элементов (окончание s в слове Elements), поэтому мы и работаем с массивом. А в методе getElementById мы получаем один элемент (о чем свидетельствует отсутствие окончания s в слове Element).
После инициализации рабочих переменных - мы корректируем положение body при появлении ползунка прокрутки, то есть наш ползунок будет накладываться поверх нашего сайта, а не сдвигать его, как это обычно бывает (можете проверить сами):
// функция для корректировки положения body при появлении ползунка прокрутки function bodyMargin() { bodyElementHTML.style.marginRight = "-" + scrollbarWidth + "px"; } // при длинной странице - корректируем сразу bodyMargin();
Механизм корректировки прост: в случае появления ползунка прокрутки - мы делаем отступ body через свойство margin-right на отрицательную величину ширины ползунка прокрутки. При первой загрузки страницы мы вызываем эту функцию, чтобы наше содержимое сразу же позиционировалось корректно, несмотря на наличие ползунка прокрутки. Вообще, позиционирование с учетом ползунка прокрутки - дело каждого, мне не хотелось бы, чтобы мой сайт скакал влево вправо :)
Создадим обработчик события нажатия на наш триггер:
// событие нажатия на триггер открытия модального окна modalTrigger.addEventListener("click", function () { // делаем модальное окно видимым modalBackground.style.display = "block"; // если размер экрана больше 1366 пикселей (т.е. на мониторе может появиться ползунок) if (windowInnerWidth >= 1366) { bodyMargin(); } // позиционируем наше окно по середине, где 175 - половина ширины модального окна modalActive.style.left = "calc(50% - " + (175 - scrollbarWidth / 2) + "px)"; });
И в завершение создадим обработчик закрытия нашего окна при нажатии на крестик или на область за модальным окном:
// нажатие на крестик закрытия модального окна modalClose.addEventListener("click", function () { modalBackground.style.display = "none"; if (windowInnerWidth >= 1366) { bodyMargin(); } }); // закрытие модального окна на зону вне окна, т.е. на фон modalBackground.addEventListener("click", function (event) { if (event.target === modalBackground) { modalBackground.style.display = "none"; if (windowInnerWidth >= 1366) { bodyMargin(); } } });
Вот и всё модальное окно. Если у Вас есть какие-нибудь замечания, похвала, критика, советы, любой фидбек - буду рад прочитать и внести корректировки! Всех обнял-приподнял :)
