Плавная прокрутка страницы к якорю с сохранением хеша на jQuery

Стандартное поведение браузеров при клике на якорную ссылку может сбить человека с толку. Потому что страница скроллится мгновенно, и человек не понимает, в какое место страницы он попал (вверх или вниз), да и вообще — остался ли он на данной странице, или перешёл на другую.

Чтобы это исправить, будем использовать плавную прокрутку на javascript или jquery. Плавная прокрутка до элемента ясно даёт понять, что мы остались на том же сайте, и куда именно прокрутилась страница.

План скрипта

Обычная функция типа scrollTo делает прокрутку, но это было бы слишком грубо и не учитывало все нюансы. А вот что требуется от правильного скрипта:

1) отменить стандартные действия браузера при клике по таким ссылкам;
2) определить расстояние до элемента, к которому нужно прокрутить;
3) плавно, то есть, без тормозов прокрутить страницу на это расстояние;
4) изменить window.location.hash — часть адреса страницы после решётки #.

Кроссбраузерность

Хочу обратить ваше внимание на трудности, с которыми я столкнулся в некоторых браузерах. Например, в Chrome есть проблема с определением расстояния от верхней части страницы до определённого элемента, в том случае, если этот элемент пустой. Например, если это элемент <а> без контента внутри, у которого явно не заданы ширина и высота, то браузер глючит и выдаёт случайные расстояния. Если же это <div> с каким-то содержимым, то в зависимости от этого содержимого, у него легко вычисляются размеры, и определить расстояние до данного блока — не проблема. Чтобы избежать данного глюка, скрипт вставляет внутрь каждой ссылки <а> очень маленький неразрывный пробел. Этого достаточно, чтобы у элемента появился какой-то размер.

Ещё одна проблема: визуальные редакторы кода вставляют якоря прямо внутрь тегов <p>, <h2>:

<h2><a name="podzagolovok"></a>Подзаголовок</h2>

Желательно вытащить якорь наружу, вне элемента h2, чтобы стало вот так:

<a name="podzagolovok"></a><h2>Подзаголовок</h2>

Логично располагать якорь перед всем тем контентом, который к нему относится.

И последняя проблема — это тормоза при скроллинге тяжёлых страниц. Чтобы уменьшить тормоза, я придумал такой лайфхак: сначала мгновенно (без анимации) перенести страницу поближе к элементу, а уже потом плавно докрутить до элемента.

Скрипт на jQuery

Вот скрипт, который заменяет стандартные действия браузера при клике по якорным ссылкам и изменении location.hash. Я использовал jQuery, потому что там очень удобно реализованы селекторы (поиск элементов в html документе). Например, a[name] означает «все элементы а, у которых прописан аттрибут name».


//внутрь якорей вставляем пробел мелким шрифтом
$('a[name]').html(' ').css('font-size','0.2em');

//вытаскиваем якоря и ставим выше родительских элементов H2
$('H2 a[name]').each(function() {
$(this).css('position','absolute').insertBefore($(this).parent());
});

//находим все якорные ссылки, в которых есть решётка
$('a[href^="#"]').click(function(e) {

//убираем стандартное действие браузера
e.preventDefault();

//по названию ссылки находим элемент, до которого надо докрутить
var scroll_el=$('a[name="'+$(this).attr('href').split('#')[1]+'"]');

//если элемент найден, то
if ($(scroll_el).length!=0) {

//мгновенно скроллим до (Y-300), где Y - расстояние до элемента от начала страницы
$('html,body').animate({scrollTop:$(scroll_el).offset().top-300},0);

//а затем плавно, в течение 0,5 с скроллим до элемента
$('html,body').animate({scrollTop:$(scroll_el).offset().top},500);

//добавляем хеш к URL страницы
window.location.hash=$(this).attr('href').split('#')[1];
}

//возвращаем false, чтобы отключить стандартное действие по данной ссылке
return false;
});

Скачать скрипт

Нужны хитрые user friendly скрипты для фронтэнда - обращайтесь.

📅 16 декабря 2018#javascript#jQuery#юзабилити

Благодарность автору

Перевод через Яндекс.Деньги:

Смотрите также

Спонсоры поста

Комментарии

Дальнейшие комментарии временно закрыты. По всем вопросам обращайтесь ко мне по почте, через Вотсап или Вконтакте, см. раздел Контакты

© 2018