Модальное окно на чистом CSS и JS

от автора

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

Для тех, кому надо сразу код и вид окна.

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() {     if ((bodyElementHTML.style.overflowY = "hidden")) {         bodyElementHTML.style.overflowY = "visible";         bodyElementHTML.style.marginRight = "-" + scrollbarWidth + "px";     } else {         bodyElementHTML.style.overflowY = "hidden";         bodyElementHTML.style.marginRight = 0;     } }  // при длинной странице - корректируем сразу bodyMargin();

Механизм корректировки прост: мы проверяем длину нашего сайта через свойство overflowY, которое говорит нам о том, есть ли у нас содержимое за видимой частью или нет (зависит от его значения, по умолчанию — visible). Если содержимого нет — нет и ползунка, следовательно стабилизация не нужна. В случаем наличия содержимого — мы делаем отступ 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();         }     } });

Вот и всё модальное окно. Если у Вас есть какие-нибудь замечания, похвала, критика, советы, любой фидбек — буду рад прочитать и внести корректировки! Всех обнял-приподнял 🙂


ссылка на оригинал статьи https://habr.com/ru/post/716142/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *