Как сделать кнопку «наверх» на сайте — просто и красиво
Кнопка «наверх» (back-to-top) — микроэлемент интерфейса, который заметно улучшает UX на длинных страницах, в блогах, каталогах и лендингах с большим объёмом контента. Когда пользователь пролистывает длинную страницу, ему не приходится скроллить обратно вручную или жать Home — кнопка делает это за одно нажатие. Несмотря на кажущуюся простоту, вокруг кнопки «наверх» сложилось множество приёмов, анимаций, вариаций дизайна и оптимизаций, которые мы разберём в этой статье.
Базовая реализация: HTML + CSS + JS
Начнём с минимального рабочего примера. Нам нужны: кнопка в HTML, стили для позиционирования и анимации появления, скрипт для отслеживания скролла и плавного подъёма.
HTML
<button id="backToTop" class="back-to-top" aria-label="Наверх страницы" title="Наверх"> <i class="fas fa-arrow-up"></i> </button>
Обратите внимание на aria-label — это важно для accessibility. Скринридеры зачитают «Наверх страницы» вместо бессмысленного «button». Атрибут title покажет подсказку при наведении.
CSS: базовая версия + анимация появления
.back-to-top {
position: fixed;
bottom: 30px;
right: 30px;
width: 48px;
height: 48px;
border: none;
border-radius: 50%;
background: var(--primary, #6c5ce7);
color: #fff;
font-size: 1.2rem;
cursor: pointer;
opacity: 0;
transform: translateY(20px);
transition: opacity 0.3s ease, transform 0.3s ease;
pointer-events: none;
z-index: 999;
box-shadow: 0 4px 15px rgba(108, 92, 231, 0.3);
display: flex;
align-items: center;
justify-content: center;
}
.back-to-top.visible {
opacity: 1;
transform: translateY(0);
pointer-events: auto;
}
.back-to-top:hover {
transform: translateY(-3px);
box-shadow: 0 6px 20px rgba(108, 92, 231, 0.5);
}
.back-to-top:focus-visible {
outline: 3px solid var(--primary);
outline-offset: 4px;
}
Ключевые моменты: pointer-events: none при скрытом состоянии — пользователь не может случайно кликнуть по невидимой кнопке. opacity + transform дают плавное появление с подъёмом. :focus-visible обеспечивает клавиатурную навигацию.
JS: с throttle для производительности
const btn = document.getElementById('backToTop');
function throttle(fn, delay) {
let last = 0;
return function(...args) {
const now = Date.now();
if (now - last >= delay) {
last = now;
fn.apply(this, args);
}
};
}
window.addEventListener('scroll', throttle(() => {
const threshold = window.innerHeight;
btn.classList.toggle('visible', window.scrollY > threshold);
}, 100));
btn.addEventListener('click', () => {
window.scrollTo({ top: 0, behavior: 'smooth' });
});
Без throttle событие scroll срабатывает десятки раз в секунду — это нагружает основной поток. С throttle в 100 мс проверка порога происходит максимум 10 раз в секунду. Порог window.innerHeight означает, что кнопка появляется, когда пользователь проскроллил хотя бы на высоту экрана.
Прогресс-бар вокруг кнопки (SVG circle)
Эффектный приём — отображать прогресс прочтения страницы по кругу вокруг кнопки. Реализуется через SVG circle с атрибутами stroke-dasharray и stroke-dashoffset:
<div class="back-to-top-wrapper">
<svg class="progress-ring" width="56" height="56">
<circle class="progress-ring__bg" cx="28" cy="28" r="24"
fill="none" stroke="var(--border)" stroke-width="3"/>
<circle class="progress-ring__fill" cx="28" cy="28" r="24"
fill="none" stroke="var(--primary)" stroke-width="3"
stroke-linecap="round"
stroke-dasharray="150.8"
stroke-dashoffset="150.8"/>
</svg>
<button class="back-to-top" id="backToTop" aria-label="Наверх">
<i class="fas fa-arrow-up"></i>
</button>
</div>
<style>
.back-to-top-wrapper {
position: fixed;
bottom: 30px;
right: 30px;
z-index: 999;
}
.back-to-top-wrapper .back-to-top {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 40px;
height: 40px;
}
.progress-ring {
transform: rotate(-90deg);
}
</style>
<script>
const circle = document.querySelector('.progress-ring__fill');
const circumference = 2 * Math.PI * 24;
window.addEventListener('scroll', () => {
const scrollPct = window.scrollY / (document.documentElement.scrollHeight - window.innerHeight);
const offset = circumference * (1 - Math.min(scrollPct, 1));
circle.style.strokeDashoffset = offset;
});
</script>
Длина окружности 2 × π × 24 = 150.8. При скролле stroke-dashoffset уменьшается от 150.8 до 0, создавая эффект заполнения. Оборачивающий div позиционируется как fixed, а кнопка и SVG абсолютно центрируются внутри.
CSS-вариации: дизайн под любой стиль
1. Круглая с тенью (база)
Стандарт — круг 48×48px, цвет акцента, полупрозрачная тень. Минималистично и привычно.
2. Квадратная с градиентом
.back-to-top.square {
border-radius: 12px;
background: linear-gradient(135deg, #667eea, #764ba2);
width: 44px;
height: 44px;
}
Квадратная форма со скруглёнными углами (12px) и градиентом смотрится современно, особенно на сайтах с тёмной темой.
3. Glassmorphism
.back-to-top.glass {
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.25);
box-shadow: none;
color: #fff;
}
Эффект стекла вписывается в современные нейморфные интерфейсы. Важно: backdrop-filter не работает в некоторых браузерах, проверяйте caniuse.
4. С подсветкой при наведении
.back-to-top.glowing {
box-shadow: 0 0 15px rgba(var(--primary-rgb), 0.4);
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% { box-shadow: 0 0 15px rgba(var(--primary-rgb), 0.4); }
50% { box-shadow: 0 0 25px rgba(var(--primary-rgb), 0.7); }
}
Intersection Observer вместо scroll
Современная альтернатива событию scroll — Intersection Observer. Он не нагружает основной поток и срабатывает только при пересечении указанного элемента с областью просмотра:
const sentinel = document.getElementById('scrollSentinel');
const btn = document.getElementById('backToTop');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
btn.classList.toggle('visible', !entry.isIntersecting);
});
}, { threshold: 0 });
observer.observe(sentinel);
Помещаем невидимый элемент высотой 1px в начало страницы. Пока он в области видимости — кнопка скрыта. Как только пользователь проскроллил дальше — появляется. Преимущество: Intersection Observer не вызывает reflow и работает в отдельном потоке браузера.
Когда показывать кнопку
| Логика | Код | Когда подходит |
|---|---|---|
| scrollY > высота экрана | window.scrollY > window.innerHeight | Стандартный вариант для всех страниц |
| scrollY > 30% страницы | window.scrollY / docHeight > 0.3 | Для коротких страниц, где нужно показать раньше |
| После определённого блока | Intersection Observer на целевой секции | Когда кнопка нужна только после конкретного раздела |
Доступность (Accessibility)
Кнопка «наверх» — интерактивный элемент, и она должна быть доступна всем пользователям:
— aria-label="Наверх страницы" — скринридер прочитает осмысленное описание
— role="button" — явно указывает роль (хотя для button это по умолчанию)
— :focus-visible — видимый фокус при навигации с клавиатуры
— tabindex="0" — кнопка фокусируется tab'ом (и так по умолчанию)
— При скрытом состоянии aria-hidden="true" — скринридер не видит невидимую кнопку
Мобильные устройства
На мобильных кнопка «наверх» требует особого подхода:
— Поднимите выше: bottom: 80px вместо 30px — чтобы не перекрывать панель навигации браузера и не мешать нажатию нижних элементов
— Увеличьте hit area: минимальная область нажатия 44×44px (стандарт Apple HIG). Наша кнопка 48px проходит, но можно сделать padding на wrapper'e
— На телефонах hover-эффекты бесполезны — уберите их через @media (hover: hover)
— Проверьте, что кнопка не перекрывает контент: на узких экранах можно сместить левее или уменьшить до 40px
Как добавить на WordPress
Способ 1. Плагин. Установите «WP Back to Top» или «Simple Back to Top» — настройте цвет, позицию, анимацию в админке. Минус: лишний плагин в системе.
Способ 2. Через кастомный код. Добавьте HTML в footer.php (перед </body>), CSS в style.css дочерней темы, JS — в отдельный файл и подключите через functions.php:
wp_enqueue_script('back-to-top', get_template_directory_uri() . '/js/back-to-top.js', [], null, true);
Параметр true в конце указывает, что скрипт грузится в footer — не блокирует рендеринг.
Как добавить на Tilda
В Tilda кнопку «наверх» можно сделать через Zero Block или через код на страницу:
— В настройках страницы → «HTML-код перед </body>» вставьте HTML кнопки и JS
— CSS добавьте в «HTML-код внутри <head>»
— Либо используйте готовый блок из Marketplace — есть несколько бесплатных вариантов
Кнопка «наверх» — это 30 строк кода, которые делают сайт удобнее. Добавьте её на все страницы с длинным контентом: статьи, каталоги, блоги, лендинги. Без неё пользователь устаёт скроллить и уходит.