Стильная страница ошибок для сайта.
Каждый сайт сталкивается с ошибками. Неважно, насколько тщательно вы его разрабатываете, пользователи иногда могут попасть на несуществующую страницу или столкнуться с техническими проблемами. Вместо того чтобы показывать стандартное, скучное сообщение об ошибке, почему бы не превратить это в возможность?
Стильная страница ошибок — это не просто красивый дизайн. Это ваш шанс:
- Удержать посетителя: Вместо того чтобы разочарованный пользователь ушел, вы можете предложить ему полезные ссылки, строку поиска или даже немного юмора.
- Улучшить пользовательский опыт: Покажите, что вы заботитесь о своих посетителях, предоставляя им понятную и дружелюбную информацию.
- Поддержать имидж бренда: Ваша страница ошибок — это еще одна точка контакта с вашим брендом. Сделайте ее такой, чтобы она соответствовала общему стилю вашего сайта.
Здесь я привожу готовое и быстрое решение от AI, которое во многом удовлетворит насущную задачу.

Что делает скрипт страницы ошибок:
Определяет текущую ошбку по коду и выводит расшифрованное сообщение пользователю. Вот какие ошибки транслирует скрипт:
- 400 - title: 'Неверный запрос',
description: 'Сервер не может обработать запрос из-за синтаксической ошибки. Проверьте правильность введённых данных и повторите попытку.',
status: 'Bad Request'. - 401 - title: 'Требуется авторизация',
description: 'Для доступа к этой странице необходимо войти в систему. Пожалуйста, авторизуйтесь или зарегистрируйтесь.',
status: 'Unauthorized'. - 403 - title: 'Доступ запрещён',
description: 'У вас нет прав для просмотра этой страницы. Если вы считаете это ошибкой, свяжитесь с администратором.',
status: 'Forbidden'. - 404 - title: 'Страница не найдена',
description: 'К сожалению, запрашиваемая страница не существует или была перемещена. Проверьте правильность адреса или вернитесь на главную страницу.',
status: 'Not Found'. - 408- title: 'Время ожидания истекло',
description: 'Сервер слишком долго ждал завершения запроса. Попробуйте обновить страницу или повторить действие позже.',
status: 'Request Timeout'. - 429 - title: 'Слишком много запросов',
description: 'Вы отправили слишком много запросов за короткое время. Пожалуйста, подождите несколько минут и попробуйте снова.',
status: 'Too Many Requests'. - 500 - title: 'Внутренняя ошибка сервера',
description: 'На сервере произошла непредвиденная ошибка. Наши специалисты уже работают над её устранением. Попробуйте позже.',
status: 'Internal Server Error'. - 502 - title: 'Ошибка шлюза',
description: 'Сервер получил недействительный ответ от вышестоящего сервера. Попробуйте обновить страницу через несколько минут.',
status: 'Bad Gateway'. - 503 - title: 'Сервис недоступен',
description: 'Сервер временно недоступен из-за технического обслуживания или перегрузки. Пожалуйста, попробуйте позже.',
status: 'Service Unavailable'. - 504 - title: 'Шлюз не отвечает',
description: 'Сервер не получил своевременного ответа от вышестоящего сервера. Проверьте подключение и попробуйте снова.',
status: 'Gateway Timeout'.
В дополнении к основной функии, страница показывает текущее время на клиентском устройстве. А внизу страницы пытается определить тип устройства с которого заходит на сайт клиент.
Скрипт довольно качественно стилизован и не требует дополнительных подключений и запросов к графике для своей работы.
Подключение скрипта страницы ошибок на сайт:
Чтобы настроить отображение страниц ошибок на вашем сайте, вам нужно выполнить несколько шагов. Это довольно просто.
- Нужно поместить файл скрипта "errors.php" - страницы ошибок, в корневую папку сайта.
- Проверить наличие файла .htaccess в той же корневой папке сайта и если его там нет, то создать файл и прописать в файле следующе строки:
htaccessВсё, файл ошибок готов к работе.ErrorDocument 400 /errors.php ErrorDocument 401 /errors.php ErrorDocument 403 /errors.php ErrorDocument 404 /errors.php ErrorDocument 408 /errors.php ErrorDocument 429 /errors.php ErrorDocument 500 /errors.php ErrorDocument 502 /errors.php ErrorDocument 502 /errors.php ErrorDocument 504 /errors.php
А теперь полный код самого файла "errors.php":
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Ошибка | Страница недоступна</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--primary-color: #6366f1;
--primary-dark: #4f46e5;
--error-red: #ef4444;
--warning-orange: #f59e0b;
--success-green: #10b981;
--info-blue: #3b82f6;
--bg-gradient-start: #f0f4ff;
--bg-gradient-end: #e0e7ff;
--card-bg: #ffffff;
--text-primary: #1e293b;
--text-secondary: #64748b;
--shadow-color: rgba(99, 102, 241, 0.15);
}
@media (prefers-color-scheme: dark) {
:root {
--bg-gradient-start: #1e1b4b;
--bg-gradient-end: #312e81;
--card-bg: #1e293b;
--text-primary: #f1f5f9;
--text-secondary: #94a3b8;
--shadow-color: rgba(0, 0, 0, 0.3);
}
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
min-height: 100vh;
background: linear-gradient(135deg, var(--bg-gradient-start) 0%, var(--bg-gradient-end) 100%);
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
color: var(--text-primary);
}
.error-container {
background: var(--card-bg);
border-radius: 24px;
padding: 40px;
max-width: 600px;
width: 100%;
box-shadow: 0 25px 50px -12px var(--shadow-color);
text-align: center;
animation: fadeInUp 0.6s ease-out;
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.error-icon {
width: 120px;
height: 120px;
margin: 0 auto 24px;
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
.error-code {
font-size: 72px;
font-weight: 800;
background: linear-gradient(135deg, var(--primary-color), var(--error-red));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 16px;
line-height: 1;
}
.error-title {
font-size: 24px;
font-weight: 600;
margin-bottom: 12px;
color: var(--text-primary);
}
.error-description {
font-size: 16px;
color: var(--text-secondary);
line-height: 1.6;
margin-bottom: 32px;
}
.time-display {
background: linear-gradient(135deg, var(--primary-color), var(--primary-dark));
color: white;
padding: 16px 24px;
border-radius: 16px;
margin-bottom: 24px;
display: inline-block;
}
.time-label {
font-size: 12px;
text-transform: uppercase;
letter-spacing: 1px;
opacity: 0.8;
margin-bottom: 4px;
}
.time-value {
font-size: 28px;
font-weight: 700;
font-variant-numeric: tabular-nums;
}
.date-value {
font-size: 14px;
opacity: 0.9;
margin-top: 4px;
}
.error-details {
background: rgba(99, 102, 241, 0.08);
border-radius: 12px;
padding: 16px;
margin-bottom: 24px;
text-align: left;
}
.detail-row {
display: flex;
justify-content: space-between;
padding: 8px 0;
border-bottom: 1px solid rgba(99, 102, 241, 0.1);
font-size: 14px;
}
.detail-row:last-child {
border-bottom: none;
}
.detail-label {
color: var(--text-secondary);
}
.detail-value {
font-weight: 500;
color: var(--text-primary);
}
.action-buttons {
display: flex;
gap: 12px;
justify-content: center;
flex-wrap: wrap;
}
.btn {
padding: 14px 28px;
border-radius: 12px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
border: none;
text-decoration: none;
display: inline-flex;
align-items: center;
gap: 8px;
}
.btn-primary {
background: linear-gradient(135deg, var(--primary-color), var(--primary-dark));
color: white;
box-shadow: 0 4px 14px rgba(99, 102, 241, 0.4);
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(99, 102, 241, 0.5);
}
.btn-secondary {
background: transparent;
color: var(--primary-color);
border: 2px solid var(--primary-color);
}
.btn-secondary:hover {
background: var(--primary-color);
color: white;
}
.browser-info {
margin-top: 24px;
padding-top: 24px;
border-top: 1px solid rgba(99, 102, 241, 0.1);
font-size: 12px;
color: var(--text-secondary);
}
/* Tablet */
@media (max-width: 768px) {
.error-container {
padding: 32px 24px;
}
.error-code {
font-size: 56px;
}
.error-title {
font-size: 20px;
}
.error-icon {
width: 100px;
height: 100px;
}
}
/* Mobile */
@media (max-width: 480px) {
.error-container {
padding: 24px 16px;
border-radius: 16px;
}
.error-code {
font-size: 48px;
}
.error-title {
font-size: 18px;
}
.error-description {
font-size: 14px;
}
.time-value {
font-size: 24px;
}
.action-buttons {
flex-direction: column;
}
.btn {
width: 100%;
justify-content: center;
}
.detail-row {
flex-direction: column;
gap: 4px;
}
}
/* High contrast mode */
@media (prefers-contrast: high) {
.error-container {
border: 2px solid var(--text-primary);
}
.btn {
border: 2px solid currentColor;
}
}
/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
.error-icon {
animation: none;
}
.error-container {
animation: none;
}
.btn {
transition: none;
}
}
</style>
</head>
<body>
<div class="error-container">
<svg
class="error-icon"
viewBox="0 0 120 120"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="60" cy="60" r="55" fill="url(#gradient1)" opacity="0.1" />
<circle
cx="60"
cy="60"
r="45"
stroke="url(#gradient2)"
stroke-width="4"
fill="none"
/>
<path
d="M60 35V65"
stroke="#ef4444"
stroke-width="6"
stroke-linecap="round"
/>
<circle cx="60" cy="80" r="4" fill="#ef4444" />
<defs>
<linearGradient id="gradient1" x1="0" y1="0" x2="120" y2="120">
<stop offset="0%" stop-color="#6366f1" />
<stop offset="100%" stop-color="#ef4444" />
</linearGradient>
<linearGradient id="gradient2" x1="0" y1="0" x2="120" y2="120">
<stop offset="0%" stop-color="#6366f1" />
<stop offset="100%" stop-color="#ef4444" />
</linearGradient>
</defs>
</svg>
<div class="error-code" id="errorCode">404</div>
<h1 class="error-title" id="errorTitle">Страница не найдена</h1>
<p class="error-description" id="errorDescription">
К сожалению, запрашиваемая страница не существует или была перемещена.
Проверьте правильность адреса или вернитесь на главную страницу.
</p>
<div class="time-display">
<div class="time-label">Текущее время</div>
<div class="time-value" id="currentTime">--:--:--</div>
<div class="date-value" id="currentDate">-- -- ----</div>
</div>
<div class="error-details">
<div class="detail-row">
<span class="detail-label">Код ошибки:</span>
<span class="detail-value" id="detailCode">404</span>
</div>
<div class="detail-row">
<span class="detail-label">Статус:</span>
<span class="detail-value" id="detailStatus">Not Found</span>
</div>
<div class="detail-row">
<span class="detail-label">URL:</span>
<span class="detail-value" id="detailUrl">-</span>
</div>
<div class="detail-row">
<span class="detail-label">Timestamp:</span>
<span class="detail-value" id="detailTimestamp">-</span>
</div>
</div>
<div class="action-buttons">
<a href="/" class="btn btn-primary">
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
<polyline points="9,22 9,12 15,12 15,22" />
</svg>
На главную
</a>
<button class="btn btn-secondary" onclick="window.history.back()">
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<line x1="19" y1="12" x2="5" y2="12" />
<polyline points="12,19 5,12 12,5" />
</svg>
Назад
</button>
</div>
<div class="browser-info" id="browserInfo"></div>
</div>
<script>
const errorMessages = {
400: {
title: 'Неверный запрос',
description: 'Сервер не может обработать запрос из-за синтаксической ошибки. Проверьте правильность введённых данных и повторите попытку.',
status: 'Bad Request'
},
401: {
title: 'Требуется авторизация',
description: 'Для доступа к этой странице необходимо войти в систему. Пожалуйста, авторизуйтесь или зарегистрируйтесь.',
status: 'Unauthorized'
},
403: {
title: 'Доступ запрещён',
description: 'У вас нет прав для просмотра этой страницы. Если вы считаете это ошибкой, свяжитесь с администратором.',
status: 'Forbidden'
},
404: {
title: 'Страница не найдена',
description: 'К сожалению, запрашиваемая страница не существует или была перемещена. Проверьте правильность адреса или вернитесь на главную страницу.',
status: 'Not Found'
},
408: {
title: 'Время ожидания истекло',
description: 'Сервер слишком долго ждал завершения запроса. Попробуйте обновить страницу или повторить действие позже.',
status: 'Request Timeout'
},
429: {
title: 'Слишком много запросов',
description: 'Вы отправили слишком много запросов за короткое время. Пожалуйста, подождите несколько минут и попробуйте снова.',
status: 'Too Many Requests'
},
500: {
title: 'Внутренняя ошибка сервера',
description: 'На сервере произошла непредвиденная ошибка. Наши специалисты уже работают над её устранением. Попробуйте позже.',
status: 'Internal Server Error'
},
502: {
title: 'Ошибка шлюза',
description: 'Сервер получил недействительный ответ от вышестоящего сервера. Попробуйте обновить страницу через несколько минут.',
status: 'Bad Gateway'
},
503: {
title: 'Сервис недоступен',
description: 'Сервер временно недоступен из-за технического обслуживания или перегрузки. Пожалуйста, попробуйте позже.',
status: 'Service Unavailable'
},
504: {
title: 'Шлюз не отвечает',
description: 'Сервер не получил своевременного ответа от вышестоящего сервера. Проверьте подключение и попробуйте снова.',
status: 'Gateway Timeout'
}
};
function getErrorCode() {
const urlParams = new URLSearchParams(window.location.search);
const code = parseInt(urlParams.get('code')) || 404;
return errorMessages[code] ? code : 404;
}
function updateErrorDisplay(code) {
const error = errorMessages[code];
document.getElementById('errorCode').textContent = code;
document.getElementById('errorTitle').textContent = error.title;
document.getElementById('errorDescription').textContent = error.description;
document.getElementById('detailCode').textContent = code;
document.getElementById('detailStatus').textContent = error.status;
document.getElementById('detailUrl').textContent = window.location.pathname || '/';
document.getElementById('detailTimestamp').textContent = new Date().toISOString();
document.title = `Ошибка ${code} | ${error.title}`;
}
function updateTime() {
const now = new Date();
const timeOptions = { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false };
const timeString = now.toLocaleTimeString('ru-RU', timeOptions);
document.getElementById('currentTime').textContent = timeString;
const dateOptions = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
const dateString = now.toLocaleDateString('ru-RU', dateOptions);
document.getElementById('currentDate').textContent = dateString;
}
function getBrowserInfo() {
const ua = navigator.userAgent;
let browser = 'Неизвестный браузер';
let os = 'Неизвестная ОС';
if (ua.includes('Firefox')) browser = 'Mozilla Firefox';
else if (ua.includes('SamsungBrowser')) browser = 'Samsung Browser';
else if (ua.includes('Opera') || ua.includes('OPR')) browser = 'Opera';
else if (ua.includes('Edge')) browser = 'Microsoft Edge';
else if (ua.includes('Chrome')) browser = 'Google Chrome';
else if (ua.includes('Safari')) browser = 'Apple Safari';
if (ua.includes('Windows')) os = 'Windows';
else if (ua.includes('Mac')) os = 'macOS';
else if (ua.includes('Linux')) os = 'Linux';
else if (ua.includes('Android')) os = 'Android';
else if (ua.includes('iOS') || ua.includes('iPhone') || ua.includes('iPad')) os = 'iOS';
const screenInfo = `${window.screen.width}×${window.screen.height}`;
const deviceType = window.innerWidth < 768 ? 'Мобильное' : (window.innerWidth < 1024 ? 'Планшет' : 'Десктоп');
return `${browser} • ${os} • ${screenInfo} • ${deviceType} устройство`;
}
function init() {
const errorCode = getErrorCode();
updateErrorDisplay(errorCode);
updateTime();
setInterval(updateTime, 1000);
document.getElementById('browserInfo').textContent = getBrowserInfo();
}
document.addEventListener('DOMContentLoaded', init);
</script>
</body>
</html>
