Как создать всплывающее окно при входе на сайт с формой авторизации
Всплывающее окно при входе на сайт состоит из затемняющего слоя, панели и обработчиков событий. HTML задает поля формы, CSS размещает окно, а jQuery управляет открытием. Добавьте закрытие кнопкой, клавишей Escape и нажатием на фон. Адаптивная ширина и управление фокусом сделают форму удобнее на телефоне и с клавиатуры.
Пример собирает интерфейс окна. Проверку учетных данных выполняет серверный обработчик, который вы подключаете отдельно.
- Подготовьте файлы и подключите jQuery
- Добавьте HTML-код формы входа
- Создайте CSS-наложение и адаптивную панель
- Сделайте кнопки и поля доступными с клавиатуры
- Открывайте окно и управляйте фокусом через jQuery
- Подгружайте вход и регистрацию через AJAX
- Покажите всплывающее окно при входе на сайт
- Когда можно обойтись без jQuery
- Проверьте окно перед подключением к проекту
- Какой вариант окна выбрать для проекта
Подготовьте файлы и подключите jQuery
Создайте папку примера с файлами index.html, popup.css и popup.js. Разметку, стили и обработчики сохраните в соответствующие файлы. Это один комплект кода: повторно добавлять фрагменты не потребуется.
Пример использует полную сборку jQuery с поддержкой AJAX.
Если библиотека уже подключена в проекте, используйте существующее подключение. Вторую копию добавлять не нужно: она усложняет работу плагинов и обработчиков.
Для отдельного примера скачайте библиотеку с официального сайта jQuery. В разделе загрузки выберите полную сборку ветки 3.x: несжатую для изучения кода или сжатую production-сборку. Slim-сборка для AJAX-варианта не подходит.
- Откройте ссылку на выбранную сборку. Если браузер показывает JavaScript текстом, нажмите Ctrl+S в Windows или Linux либо Command+S в macOS.
- Создайте папку
assetsрядом сindex.html. Сохраните скачанный файл в эту папку под именемjquery.js. Если браузер уже скачал файл, перенесите его туда и переименуйте. - Проверьте имя файла: должно получиться
assets/jquery.js, без дополнительного расширения.txt. Итоговая разметка подключает библиотеку именно по этому локальному пути.
Назначение методов описывает документация jQuery.
Дополнительные веб-шрифты для работы окна не нужны. Пример использует системный шрифт и сохраняет видимую рамку фокуса.
Добавьте HTML-код формы входа
Сохраните разметку в index.html. Ссылка «Войти» открывает окно через JavaScript. Ее адрес login.php остается запасным переходом на отдельную страницу входа.
<!doctype html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Форма входа</title>
<link rel="stylesheet" href="popup.css">
<script src="assets/jquery.js" defer></script>
<script src="popup.js" defer></script>
</head>
<body>
<main id="pageContent">
<p>Содержимое страницы</p>
<a href="login.php" id="loginLink">Войти</a>
</main>
<div class="overlay" id="loginOverlay" hidden>
<div class="login-wrapper" role="dialog" aria-modal="true"
aria-labelledby="loginTitle" tabindex="-1">
<div class="login-content">
<button type="button" class="close" aria-label="Закрыть">×</button>
<div id="loginTarget">
<h2 id="loginTitle">Вход</h2>
<form method="post" action="login.php">
<label for="username">Имя пользователя</label>
<p id="usernameHelp">От 8 до 20 символов. Начните с латинской буквы;
дальше допустимы латинские буквы, цифры, точка, дефис и подчеркивание.</p>
<input type="text" name="username" id="username"
autocomplete="username" aria-describedby="usernameHelp"
pattern="[a-zA-Z][a-zA-Z0-9_.\-]{7,19}" required>
<label for="password">Пароль</label>
<input type="password" name="password" id="password"
autocomplete="current-password" required>
<button type="submit">Войти</button>
</form>
</div>
</div>
</div>
</div>
</body>
</html>Атрибут hidden скрывает наложение до открытия.
Атрибуты role="dialog" и aria-modal="true" обозначают модальное окно для вспомогательных технологий. Заголовок loginTitle задает его доступное название.
Шаблон логина проверяет 8–20 символов: первая буква плюс еще 7–19 знаков. Обратный слэш экранирует дефис внутри класса символов. Правила синтаксиса разобраны в документации атрибута pattern.
В форме входа пароль проверяется только на заполненность.
Требования к сложности задавайте при регистрации: новые правила не должны блокировать вход с существующим паролем. Если ваш сайт принимает другие логины, согласуйте шаблон с сервером.
Создайте CSS-наложение и адаптивную панель
Разместите панель входа внутри наложения, которое затемняет остальную страницу.
Сохраните стили в popup.css. Правило position: fixed закрепляет фон относительно области просмотра. Свойство z-index поднимает окно над обычными блоками страницы.
*, *::before, *::after {
box-sizing: border-box;
}
body {
margin: 0;
background: #f3f3f3;
color: #222;
font-family: Arial, sans-serif;
}
#pageContent { padding: 24px; }
body.modal-open { overflow: hidden; }
.overlay {
position: fixed;
inset: 0;
z-index: 1000;
display: flex;
justify-content: center;
align-items: center;
padding: 16px;
background: rgba(0, 0, 0, .5);
}
.overlay[hidden] { display: none; }
.login-wrapper {
width: 100%;
max-width: 450px;
max-height: 100%;
overflow-y: auto;
padding: 6px;
border-radius: 8px;
background: rgba(0, 0, 0, .25);
}
.login-content {
position: relative;
padding: 24px;
border-radius: 4px;
background: #fff;
}
#loginTitle {
margin: 0 48px 20px 0;
font-size: 1.5rem;
}
.close {
position: absolute;
top: 12px;
right: 12px;
width: 40px;
height: 40px;
border: 0;
border-radius: 50%;
background: #e5e5e5;
color: #222;
font-size: 24px;
cursor: pointer;
}
#loginTarget label {
display: block;
margin-top: 16px;
}
#loginTarget p {
font-size: .875rem;
line-height: 1.5;
}
#loginTarget input {
display: block;
width: 100%;
min-width: 0;
margin: 6px 0 16px;
padding: 12px;
border: 1px solid #777;
border-radius: 4px;
font: inherit;
font-size: 16px;
}
#loginTarget button[type="submit"] {
padding: 12px 20px;
border: 0;
border-radius: 4px;
background: #1459a6;
color: #fff;
font: inherit;
cursor: pointer;
}
#loginTarget button[type="submit"]:hover { background: #10477f; }
.close:hover { background: #ccc; }
:focus-visible {
outline: 3px solid #1459a6;
outline-offset: 3px;
}
#loginTarget input:invalid:focus { border-color: #b42318; }
@media (max-width: 480px) {
.overlay { padding: 8px; }
.login-content { padding: 20px 16px; }
}Панель занимает 100% доступной ширины, но ограничена значением 450px. На узком экране внешние отступы уменьшаются до 8px. Ограничение высоты и внутренняя прокрутка помогают добраться до кнопки при открытой экранной клавиатуре.
Flexbox центрирует панель по двум осям.
При стандартном flex-direction: row свойство justify-content управляет горизонтальным выравниванием. Свойства align-items и align-self работают по поперечной, то есть вертикальной оси.
Сделайте кнопки и поля доступными с клавиатуры
Кнопка закрытия использует элемент button, поэтому получает фокус клавишей Tab. Атрибут type="button" исключает случайную отправку формы. Название «Закрыть» озвучивается благодаря aria-label.
Свойство right: 12px отсчитывает отступ от правого края .login-content. Именно этот контейнер задает ближайшего позиционированного предка кнопки через position: relative.
Каждая подпись связывается с полем через for и id. Нажатие на подпись переводит курсор в соответствующее поле. Подсказки остаются видимыми после ввода, поскольку не спрятаны в placeholder.
Не удаляйте рамку фокуса глобальным правилом outline: none.
Селектор :focus-visible показывает текущее положение при навигации с клавиатуры.
Открывайте окно и управляйте фокусом через jQuery
Сохраните обработчики в popup.js. Сокращенная запись $(function () { ... }) запускает код после построения DOM. К этому моменту элементы страницы уже доступны скрипту.
$(function () {
const overlay = document.getElementById("loginOverlay");
const dialog = overlay.querySelector(".login-wrapper");
const page = document.getElementById("pageContent");
let returnFocus = null;
let pageWasInert = false;
let bodyWasLocked = false;
function focusables() {
return $(dialog).find(
'a[href], button, input, select, textarea, [tabindex]'
).filter(':visible').filter(function () {
return !this.disabled && this.tabIndex >= 0;
}).get();
}
function focusFirst() {
const input = $(dialog).find('input:visible:enabled').get(0);
(input || focusables()[0] || dialog).focus();
}
function openModal(trigger) {
if (!overlay.hidden) return;
returnFocus = trigger || document.activeElement;
pageWasInert = page.inert;
bodyWasLocked = document.body.classList.contains("modal-open");
overlay.hidden = false;
document.body.classList.add("modal-open");
focusFirst();
page.inert = true;
}
function closeModal() {
if (overlay.hidden) return;
overlay.hidden = true;
page.inert = pageWasInert;
if (!bodyWasLocked) document.body.classList.remove("modal-open");
if (returnFocus && returnFocus.isConnected) returnFocus.focus();
}
$("#loginLink").on("click", function (e) {
e.preventDefault();
openModal(this);
});
$(document).on("click", "#loginOverlay .close", closeModal);
$(overlay).on("click", function (e) {
if (e.target === e.currentTarget) closeModal();
});
$(document).on("keydown", function (e) {
if (overlay.hidden) return;
if (e.key === "Escape") {
e.preventDefault();
closeModal();
return;
}
if (e.key !== "Tab") return;
const items = focusables();
const first = items[0];
const last = items[items.length - 1];
if (!first) {
e.preventDefault();
dialog.focus();
} else if (e.shiftKey &&
(document.activeElement === first || document.activeElement === dialog)) {
e.preventDefault();
last.focus();
} else if (!e.shiftKey &&
(document.activeElement === last || document.activeElement === dialog)) {
e.preventDefault();
first.focus();
}
});
$(document).on("focusin", function (e) {
if (!overlay.hidden && !dialog.contains(e.target)) focusFirst();
});
// Дополнительные обработчики AJAX и автопоказа вставляйте здесь.
});Метод события preventDefault() отменяет обычный переход по ссылке.
Проверка e.key === "Escape" закрывает только открытое окно. Нажатие внутри формы не закрывает панель: обработчик фона сравнивает цель события с самим наложением.
Функция openModal() запоминает элемент, вызвавший окно. Она переводит фокус в первое поле и блокирует прокрутку страницы. Атрибут inert исключает основное содержимое из взаимодействия, пока форма открыта.
Обработчик Tab удерживает обход внутри панели, включая Shift+Tab в обратном направлении. При закрытии скрипт восстанавливает прежнее состояние страницы и возвращает фокус.
В реальном проекте поместите в pageContent весь фон, включая шапку и подвал.
Подгружайте вход и регистрацию через AJAX
AJAX позволяет менять содержимое формы без перезагрузки страницы. Общая оболочка, затемнение и кнопка закрытия остаются на месте. Ответ сервера попадает только в #loginTarget.
Подготовьте HTML-фрагменты
Создайте папку ajax рядом с index.html. Скопируйте заголовок h2 и всю форму входа из #loginTarget в ajax/login-form.html. Файл должен содержать только эти два элемента, без оболочки документа и контейнера #loginTarget.
В index.html удалите из #loginTarget только форму входа. Заголовок «Вход» оставьте как начальное доступное название окна. Контейнер и соседняя кнопка закрытия тоже остаются в странице:
<div class="login-content">
<button type="button" class="close" aria-label="Закрыть">×</button>
<div id="loginTarget">
<h2 id="loginTitle">Вход</h2>
</div>
</div>При загрузке скрипт заменит содержимое контейнера целиком, включая начальный заголовок. Поэтому после вставки фрагмента в документе останется один loginTitle.
Замените ссылку loginLink внутри pageContent двумя ссылками:
<a href="login.php" class="overlayLink" data-action="login">Войти</a>
<a href="register.php" class="overlayLink" data-action="register">Зарегистрироваться</a>В файл ajax/registration-form.html сохраните форму регистрации:
<h2 id="loginTitle">Регистрация</h2>
<form id="registrationForm" method="post" action="register.php">
<label for="regUsername">Имя пользователя</label>
<p id="regUsernameHelp">От 8 до 20 символов, первый – латинская буква.
Затем допустимы латинские буквы, цифры, точка, дефис и подчеркивание.</p>
<input id="regUsername" name="username" type="text" autocomplete="username"
aria-describedby="regUsernameHelp"
pattern="[a-zA-Z][a-zA-Z0-9_.\-]{7,19}" required>
<label for="regEmail">Электронная почта</label>
<input id="regEmail" name="email" type="email" autocomplete="email" required>
<label for="regPassword">Пароль</label>
<p id="regPasswordHelp">Минимум 8 символов, включая заглавную и строчную
латинские буквы, а также цифру или спецсимвол.</p>
<input id="regPassword" name="password" type="password"
autocomplete="new-password" aria-describedby="regPasswordHelp"
pattern="(?=.{8,}$)(?=.*[A-Z])(?=.*[a-z])(?=.*[\d\W]).*" required>
<label for="regConfirm">Повторите пароль</label>
<input id="regConfirm" name="password_confirmation" type="password"
autocomplete="new-password" required>
<button type="submit">Зарегистрироваться</button>
</form>Это учебная политика сложности, которую нужно согласовать с серверной проверкой.
В HTML-атрибуте обратные слэши записываются один раз. Класс [\d\W] допускает цифру или символ вне набора букв ASCII, цифр и подчеркивания.
Пароль Abc12345 соответствует этому шаблону. Сам атрибут pattern проверяет значение целиком. Пустую строку отдельно запрещает required.
Загрузите выбранную форму и обработайте ошибку
Вставьте обработчик внутрь $(function () { ... }), перед его закрытием. Объект forms ограничивает выбор двумя известными файлами. Атрибут ссылки не превращается в произвольный адрес запроса.
const forms = {
login: "ajax/login-form.html",
register: "ajax/registration-form.html"
};
let pending = null;
$(document).on("click", ".overlayLink", function (e) {
const kind = this.dataset.action;
if (!Object.prototype.hasOwnProperty.call(forms, kind)) return;
e.preventDefault();
const trigger = this;
if (pending) pending.abort();
$("#loginTarget").html(
'<h2 id="loginTitle">Загрузка формы</h2><p role="status">Подождите…</p>'
);
openModal(trigger);
dialog.focus();
pending = $.ajax({ url: forms[kind], dataType: "html" })
.done(function (html) {
$("#loginTarget").html(html);
if (!overlay.hidden) focusFirst();
})
.fail(function (xhr, status) {
if (status === "abort") return;
const fallback = kind === "register" ? "register.php" : "login.php";
$("#loginTarget").html(
'<h2 id="loginTitle">Форма недоступна</h2>' +
'<p role="alert">Не удалось загрузить форму.</p>' +
'<a href="' + fallback + '">Открыть отдельную страницу</a>'
);
if (!overlay.hidden) focusFirst();
});
});Загружайте таким способом только собственные доверенные HTML-фрагменты. Вставка чужого HTML способна добавить опасную разметку или скрипты.
После загрузки функция focusFirst() переводит курсор в новое поле.
Делегированный обработчик закрытия закреплен на document. Он продолжит работать, даже если кнопка появится динамически. В этом примере кнопка дополнительно вынесена за пределы заменяемого контейнера.
Сравните пароль с подтверждением
Добавьте эти обработчики в тот же блок готовности DOM. Делегирование охватывает форму, загруженную после открытия страницы.
function validateConfirmation(form) {
const password = form.querySelector('[name="password"]');
const confirmation = form.querySelector('[name="password_confirmation"]');
confirmation.setCustomValidity(
confirmation.value === password.value ? "" : "Пароли не совпадают"
);
}
$(document).on("input", "#registrationForm input", function () {
validateConfirmation(this.form);
});
$(document).on("submit", "#registrationForm", function (e) {
validateConfirmation(this);
if (!this.reportValidity()) e.preventDefault();
});Пустая строка в setCustomValidity() снимает ошибку после исправления. Клиентская валидация формы регистрации дополняет проверку на сервере.
Серверный обработчик register.php тоже должен сравнивать пароли и проверять остальные поля. Клиентскую проверку пользователь может обойти.
Покажите всплывающее окно при входе на сайт
Если вы создаете всплывающее окно при входе на сайт, ограничьте повторные показы. Запись в localStorage сохранит отметку между посещениями в этом браузере. Не сохраняйте там введенные пароли.
Для варианта с формой прямо в странице вставьте таймер в блок готовности DOM. Задержка в примере составляет 1500 мс. Отметка записывается только после открытия окна.
const storageKey = "login-popup-shown";
let alreadyShown = true;
try {
alreadyShown = localStorage.getItem(storageKey) === "yes";
} catch (error) {
// При запрете хранилища автоматический показ отключен.
}
if (!alreadyShown) {
setTimeout(function () {
if (!overlay.hidden) return;
openModal(document.getElementById("loginLink"));
try {
localStorage.setItem(storageKey, "yes");
} catch (error) {
// Окно продолжает работать без сохранения отметки.
}
}, 1500);
}Этот фрагмент рассчитан на базовую разметку с loginLink.
В AJAX-варианте вместо вызова openModal() используйте $('.overlayLink[data-action="login"]').trigger('click'). Этот обработчик сначала подготовит загрузку формы.
Для повторной проверки удалите отметку командой localStorage.removeItem('login-popup-shown') в консоли браузера. Очистка данных сайта тоже удалит ее. Для авторизованного посетителя сервер должен отключать автоматический показ.
Когда можно обойтись без jQuery
Для новой страницы с единственным модальным окном используйте нативный <dialog>. Метод showModal() открывает модальный режим и блокирует взаимодействие с фоном. Браузер поддерживает закрытие клавишей Escape и удерживает клавиатурный фокус внутри.
Вариант работает независимо от предыдущих файлов. Сохраните его отдельной HTML-страницей:
<!doctype html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Нативное окно входа</title>
<style>
dialog { box-sizing: border-box; width: 92%; max-width: 450px; }
dialog::backdrop { background: rgba(0, 0, 0, .5); }
</style>
</head>
<body>
<button type="button" id="openLogin">Войти</button>
<dialog id="nativeLogin" aria-labelledby="nativeTitle">
<button type="button" id="closeLogin" aria-label="Закрыть">×</button>
<h2 id="nativeTitle">Вход</h2>
<form action="login.php" method="post">
<p><label>Имя пользователя
<input name="username" autocomplete="username" required autofocus>
</label></p>
<p><label>Пароль
<input name="password" type="password" autocomplete="current-password" required>
</label></p>
<button type="submit">Войти</button>
</form>
</dialog>
<script>
const modal = document.getElementById("nativeLogin");
const opener = document.getElementById("openLogin");
opener.addEventListener("click", () => modal.showModal());
document.getElementById("closeLogin").addEventListener("click", () => modal.close());
modal.addEventListener("close", () => opener.focus());
</script>
</body>
</html>Псевдоэлемент ::backdrop оформляет затемнение.
В этом минимальном варианте окно закрывается кнопкой и Escape; закрытие по фону отдельно не добавлено. Поведение элемента описывает документация dialog.
Проверьте окно перед подключением к проекту
Откройте базовый index.html в браузере. Для AJAX запустите локальный веб-сервер: открытие через file:// не подходит для такого запроса. Встроенный сервер Python раздаст HTML-фрагменты из папки проекта.
Для этого способа понадобится установленный Python 3.
Откройте PowerShell в Windows или приложение терминала в macOS и Linux. В Windows окно PowerShell можно открыть через Win+R: введите powershell и нажмите Enter.
- Проверьте Python командой
py --versionв Windows илиpython3 --versionв macOS и Linux. Терминал должен вывести название Python и номер версии. Если команда не найдена, попробуйтеpython --version; используйте этот вариант дальше, только если он выводит Python 3. - Перейдите в папку, содержащую
index.html. Введитеcd, пробел и полный путь к папке в кавычках, затем нажмите Enter. Например, для папкиC:\login-popupкоманда выглядит так:cd "C:\login-popup". Подставьте путь к своему проекту. - Запустите сервер командой
py -m http.server 8000 --bind 127.0.0.1в Windows. В macOS и Linux используйтеpython3 -m http.server 8000 --bind 127.0.0.1. Если проверка сработала только сpython, замените первое слово команды наpython. Терминал выведет сообщение о запуске сервера на порту 8000. - Введите в адресной строке браузера
http://127.0.0.1:8000/index.html. Должна открыться страница со ссылками входа и регистрации. Оставьте терминал с сервером открытым. - Откройте
http://127.0.0.1:8000/ajax/login-form.htmlв отдельной вкладке. Браузер должен показать заголовок и поля входа без затемнения. Аналогично откройтеhttp://127.0.0.1:8000/ajax/registration-form.html: появится форма регистрации.
Если Python отсутствует, используйте уже работающий веб-сервер вашего проекта. Скопируйте файлы примера в отдельную папку внутри его каталога сайта. Откройте index.html по HTTP-адресу этой папки и проверьте оба HTML-фрагмента по относительным путям ajax/login-form.html и ajax/registration-form.html.
Если сервер сообщает, что порт занят, замените 8000 на 8001. В адресах браузера тоже укажите 8001. Ошибка 404 при открытии фрагмента означает неверный путь или имя файла: папка ajax должна находиться рядом с index.html.
Вернитесь на страницу index.html и проверьте поведение окна:
- Нажмите «Войти». Должно появиться затемнение, а курсор – оказаться в логине.
- Пройдите форму клавишами Tab и Shift+Tab. Фокус должен оставаться внутри панели, включая кнопку закрытия.
- Закройте окно кнопкой. Фокус должен вернуться на ссылку, прокрутка страницы – восстановиться.
- Откройте окно снова и нажмите Escape. Панель должна исчезнуть без перехода по ссылке.
- Нажмите на затемненный фон. Окно должно закрыться; нажатие внутри формы должно оставить его открытым.
- Уменьшите ширину области просмотра до 320px. Панель должна помещаться по ширине, а содержимое – прокручиваться по высоте.
- Введите логин
Abc12345. Проверка должна принять 8 символов; варианты длиной 7 и 21 символ должны отклоняться. - В регистрации введите пароль
Abc12345и другое подтверждение. Браузер должен запретить отправку до совпадения значений. - Переключите вход и регистрацию через AJAX. Новое поле должно получить фокус, а кнопка закрытия – сохранить работу.
- Временно переименуйте файл AJAX-формы. При открытии должна появиться ошибка со ссылкой на отдельную страницу.
Верните переименованный файл после проверки ошибки.
Если окно не открывается, посмотрите консоль браузера: сообщение $ is not defined указывает на проблему подключения jQuery. Проверьте наличие assets/jquery.js и порядок подключения скриптов.
После проверки остановите локальный сервер сочетанием Ctrl+C в его терминале. Сервер Python раздает статические файлы и не выполняет PHP. Не используйте его для публикации сайта или проверки серверной авторизации.
Файлы login.php и register.php в примере обозначают ваши серверные обработчики. Пока их нет, отправка формы не выполнит вход или регистрацию. Перед публикацией добавьте серверную валидацию, защиту от CSRF и перебора паролей, безопасное хранение паролей и HTTPS.
Какой вариант окна выбрать для проекта
Используйте jQuery-вариант, если библиотека уже обслуживает интерфейс вашего сайта. AJAX-подгрузка пригодится для переключения форм внутри общей оболочки. Для отдельного нового окна нативный dialog сократит объем собственного кода управления фокусом.
Совет от нашей редакции: перед публикацией пройдите весь вход без мыши. Если фокус теряется или кнопка недоступна, исправьте это до добавления анимации.
Популярное за неделю
- Как создать сайт самому в 2026: 4 способа + пошаговая инструкция 34 мин чтения
- Лучшие конструкторы для создания сайтов — плюсы, минусы и сравнения 22 мин чтения
- Как работает js задержка выполнения через setTimeout 4 мин чтения
- 15 таймеров обратного отсчёта на jQuery и CSS3 2 мин чтения
- 17 бесплатных jQuery‑скриптов для загрузки файлов 5 мин чтения
- Примеры AJAX-запросов с jQuery и PHP 2 мин чтения
Комментарии
Мне, как новичку в этих технологиях, статья показалась очень интересной и полезной, спасибо!
Но...
1. Если на главной странице разместить не одну, как представлено, а две разные формы, то не понятно как в ul-li-ссылках они различаются (на самом деле, они отображаются одновременно обе при клике на любую ссылку).
2. Если же не размещать их на странице вовсе (для ajax-загрузки), то как должно быть подготовлено для них место? В виде пустого элемента div class="login-content" ? Что-то не получается и так. При клике на любую ссылку отображается пустое окно без формы.
Правильно ли я понял, что в этом варианте нужно в корне сервера создать папку ajax и разместить в ней html-файлы этих двух форм? Тогда почему на эти файлы из главной страницы показаны ссылки без упоминания этой папки ajax?