Как остановить прокрутку веб-страницы до вершины при нажатии на ссылку, которая запускает JavaScript?


135

Когда у меня есть ссылка, связанная с событием jQuery или JavaScript, например:

<a href="#">My Link</a>

Как я могу предотвратить прокрутку страницы вверх? Когда я удаляю атрибут href из якоря, страница не прокручивается вверх, но, похоже, ссылка не доступна.

Ответы:


197

Необходимо предотвратить действие по умолчанию для события click (т. Е. Перейти к цели ссылки).

Есть два способа сделать это.

Опция 1: event.preventDefault()

Вызовите .preventDefault()метод объекта события, переданного вашему обработчику. Если вы используете jQuery для привязки ваших обработчиков, это событие будет экземпляром jQuery.Eventи будет версией jQuery .preventDefault(). Если вы используете addEventListenerдля привязки ваших обработчиков, это будет Eventверсия DOM .preventDefault(). В любом случае будет делать то, что вам нужно.

Примеры:

$('#ma_link').click(function($e) {
    $e.preventDefault();
    doSomething();
});

document.getElementById('#ma_link').addEventListener('click', function (e) {
    e.preventDefault();
    doSomething();
})

Вариант 2: return false;

В jQuery :

Возвращение false из обработчика событий автоматически вызовет event.stopPropagation () и event.preventDefault ()

Итак, с jQuery вы можете альтернативно использовать этот подход для предотвращения поведения ссылки по умолчанию:

$('#ma_link').click(function(e) {
     doSomething();
     return false;
});

Если вы используете необработанные события DOM, это также будет работать в современных браузерах, поскольку спецификация HTML 5 диктует такое поведение. Тем не менее, старые версии спецификации этого не сделали, поэтому, если вам нужна максимальная совместимость со старыми браузерами, вам следует .preventDefault()явно позвонить . См. Event.preventDefault () и return false (без jQuery) для подробностей спецификации.


9
Опубликовал решение (с опозданием на 3 года), которое не требует подключения обработчика кликов: stackoverflow.com/a/11246131/216941
Мэтт Кринкло-Фогт,

В этом случае Ахиллес просто делает это, потому что он хочет, чтобы ссылка отображалась как кликабельная, для чего ему вообще не нужно использовать href = "#". Смотрите мой ответ для получения дополнительной информации.
achecopar

164

Вы можете установить свой HREF #!вместо#

Например,

<a href="#!">Link</a>

не будет выполнять прокрутку при нажатии.

Осторожно! При нажатии по-прежнему будет добавлена ​​запись в историю браузера, а это означает, что после нажатия на вашу ссылку кнопка «Назад» пользователя не приведет к переходу на страницу, на которой он был ранее. По этой причине, вероятно, лучше использовать .preventDefault()подход или использовать оба в комбинации.

Вот Скрипка, иллюстрирующая это (просто включите браузер, пока не получите полосу прокрутки):
http://jsfiddle.net/9dEG7/


Для умников - почему это работает:

Это поведение указано в спецификации HTML5 в разделе « Переход к идентификатору фрагмента ». Причина, по которой ссылка с href "#"приводит к прокрутке документа до самого верха, заключается в том, что это поведение явно указывается как способ обработки пустого идентификатора фрагмента:

2. Если fragidпустая строка, указанная часть документа является верхней частью документа.

Использование href "#!"вместо этого работает просто потому, что оно избегает этого правила. В восклицательном знаке нет ничего волшебного - он просто делает удобный идентификатор фрагмента, поскольку он заметно отличается от типичного фрагмента и вряд ли когда- idлибо будет nameсоответствовать элементу или элементу на вашей странице. В самом деле, мы можем поместить почти все после хэша; единственные фрагменты, которых будет недостаточно, - это пустая строка, слово «top» или строки, которые соответствуют nameили idатрибуты элементов на странице.

Точнее, нам просто нужен идентификатор фрагмента, который заставит нас перейти к шагу 8 в следующем алгоритме для определения указанной части документа из фрагмента:

  1. Примените алгоритм URL-анализатора к URL-адресу, и пусть fragid будет компонентом фрагмента результирующего проанализированного URL-адреса.

  2. Если fragidпустая строка, то указанная часть документа является верхней частью документа; остановите алгоритм здесь.

  3. Позвольте fragid bytesбыть результатом процентного декодирования fragid.

  4. Позвольте decoded fragidбыть результатом применения алгоритма декодера UTF-8 к fragid bytes. Если декодер UTF-8 выдает ошибку декодера, прервите декодер и вместо этого перейдите к шагу, обозначенному no decoded fragid.

  5. Если в DOM есть элемент с идентификатором, точно равным decoded fragid, то первым таким элементом в древовидном порядке является указанная часть документа; остановите алгоритм здесь.

  6. Нет декодированного фрагмента : если в DOM есть элемент с атрибутом имени, значение которого точно равно fragid( неdecoded fragid ), то первым таким элементом в древовидной структуре является указанная часть документа; остановите алгоритм здесь.

  7. Если fragid является ASCII-нечувствительным к регистру соответствием для строки top, то указанная часть документа является верхней частью документа; остановите алгоритм здесь.

  8. В противном случае нет указанной части документа.

Пока мы нажимаем на шаге 8, и в нем нет указанной части документа , в игру вступает следующее правило:

Если нет указанной части ... то пользовательский агент не должен ничего делать.

Вот почему браузер не прокручивает.


4
Неважно, если вы поставите «!» или любое другое значение, если идентификатор не является частью DOM.
Гопинатх

3
После того, как я был сторонником этого метода, я сделал 180 и советую против него. Осторожно: подобные ссылки по-прежнему изменяют URL страницы, что приводит к дополнительной записи в истории браузера и заставляет кнопку «назад» просто удалить фрагмент из URL вместо того, чтобы делать то, что ожидает пользователь. Таким образом, это решение само по себе, отвечая на вопрос в том виде, в котором оно было задано, обычно не является желательной альтернативой использованию preventDefault()в обработчике кликов - довольно печально.
Марк Амери

1
Почему бы не использовать href = "javascript :;" вместо? Насколько я знаю, это не изменит историю браузера. Об этом написано в моем ответе.
achecopar

30

Простой подход заключается в использовании этого кода:

<a href="javascript:void(0);">Link Title</a>

Этот подход не требует обновления страницы, поэтому полоса прокрутки остается на месте. Кроме того, он позволяет программно изменять событие onclick и обрабатывать привязку событий на стороне клиента с помощью jQuery.

По этим причинам вышеупомянутое решение лучше чем:

<a href="javascript:myClickHandler();">Link Title</a>
<a href="#" onclick="myClickHandler(); return false;">Link Title</a>

где последнее решение позволит избежать проблемы с прокруткой, если и только если метод myClickHandler не потерпит неудачу.


12

Возврат false из кода, который вы вызываете, будет работать и в ряде случаев является предпочтительным методом, но вы также можете так

<a href="javascript:;">Link Title</a>

Когда дело доходит до SEO, это действительно зависит от того, для чего будет использоваться ваша ссылка. Если вы собираетесь использовать его для ссылки на какой-либо другой контент, то я бы в идеале согласился, что вы хотели бы что-то значимое здесь, но если вы используете ссылку для функциональных целей, например, переполнение стека для панели инструментов пост (жирный, курсив, гиперссылка) и т. д.) тогда это, вероятно, не имеет значения.


9

Вы должны изменить

<a href="#">My Link</a>

в

<a href="javascript:;">My Link</a>

Таким образом, при нажатии на ссылку страница не будет прокручиваться вверх. Это чище, чем использование href = "#" и предотвращение запуска события по умолчанию.

У меня есть веские причины для этого при первом ответе на этот вопрос , например, что return false;не будет выполняться, если вызываемая функция выдает ошибку, или вы можете добавить функцию return false;в doSomething()функцию и затем забыть использоватьreturn doSomething();



4

Если вы можете просто изменить hrefзначение, вы должны использовать:

<a href="javascript:void(0);">Link Title</a>

Еще одно изящное решение, которое я только что придумал, - это использование jQuery, чтобы остановить действие щелчка и вызвать прокрутку страницы, но только для href="#"ссылок.

<script type="text/javascript">
    /* Stop page jumping when links are pressed */
    $('a[href="#"]').live("click", function(e) {
         return false; // prevent default click action from happening!
         e.preventDefault(); // same thing as above
    });
</script>

Конечно, return falseдолжно быть после preventDefault()строки, иначе вы никогда не попадете на эту вторую строку?
Hobailey


2

Также вы можете использовать event.preventDefault внутри атрибута onclick .

<a href="#" onclick="event.preventDefault(); doSmth();">doSmth</a>

Не нужно писать событие клика exstra.


0

Вы можете просто написать так же:

<a href="#!" onclick="function()">Delete User</a>


0

Создайте страницу, которая содержит две ссылки - одну вверху и одну внизу. При нажатии на верхнюю ссылку страница должна прокручиваться вниз до нижней части страницы, где присутствует нижняя ссылка. При нажатии на нижнюю ссылку страница должна прокручиваться вверх до верхней части страницы.



0

Вы можете проверить свой CSS. В примере здесь: https://css-tricks.com/the-checkbox-hack/ есть position: absolute; top: -9999px;. Это особенно глупо в Chrome, так как onclick="whatever"все равно переходит в абсолютную позицию элемента, по которому щелкнули.

Удаление position: absolute; top: -9999px;, display: none;может помочь.


0

Для Bootstrap 3 для свертывания, если вы не укажете data-target на привязке и используете href для определения цели, событие будет предотвращено. Если вы используете data-target, вам нужно предотвратить событие самостоятельно.

<button type="button" class="btn btn-default" data-toggle="collapse" data-target="#demo">Collapse This</button>

<div id="demo" class="collapse"> 
<p>Lorem ipsum dolor sit amet</p>
</div>
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.