Какой href использовать для JavaScript-ссылок: "#" или "javascript:void(0)"?
Краткий ответ: используйте href="javascript:void(0)" или, что ещё лучше, отказывайтесь от href в пользу кнопок
Давайте разберём каждый вариант и выясним, какой из них действительно правильный с точки зрения современных стандартов, производительности и доступности.
Почему href="#" — плохой вариант
Это самый распространённый, но и самый проблемный подход. Проблемы:
- Прокрутка вверх: Даже с
return falseлегко забыть его добавить. Если обработчик выбросит исключение, прокрутка всё равно произойдёт. - Изменение URL: Добавляет
#в адресную строку, что ломает историю браузера. - Семантическая проблема:
#означает якорь (ссылку на фрагмент страницы), а не "ничего не делать".
Почему javascript:void(0) лучше, но не идеально
Этот вариант решает проблему прокрутки и не требует return false:
<a href="javascript:void(0)" onclick="myFunction();">Нажми меня</a>
Плюсы:
- Не происходит прокрутка
- Не меняется URL
- Работает даже если JavaScript отключён (просто ничего не происходит)
Минусы:
- Нарушение разделения контента и поведения: JavaScript в HTML — это антипаттерн. Если пользователь скопирует ссылку, в буфере окажется странный URL.
- Проблемы с доступностью: Скринридеры могут неправильно интерпретировать такую ссылку.
- Производительность: Браузер должен выполнить
void(0)как JavaScript-код, что добавляет микро-задержку (хотя на практике это незаметно).
Лучшая практика (современный подход)
Вариант A: Используйте <button> вместо <a>
Если элемент выполняет действие (открыть модалку, отправить форму, запустить анимацию) — это кнопка, а не ссылка. Ссылка нужна для навигации.
<button type="button" onclick="myFunction();">Нажми меня</button>
Плюсы:
- Семантически правильно (скринридеры скажут "кнопка")
- Не требует
href - Можно стилизовать как ссылку через CSS
- Работает с клавиатуры (Tab, Enter/Space)
Вариант B: Если обязательно нужна ссылка — используйте href="javascript:void(0)" + event.preventDefault()
<a href="javascript:void(0)" id="myLink">Нажми меня</a>
<script>
document.getElementById('myLink').addEventListener('click', function(e) {
e.preventDefault(); // На всякий случай
myFunction();
});
</script>
Этот подход:
- Сохраняет внешний вид ссылки
- Не требует
return falseв HTML - Разделяет HTML и JavaScript
Производительность и доступность
Производительность: Разница между # и javascript:void(0) настолько мала, что вы её никогда не заметите. Гораздо важнее правильно структурировать код.
Доступность:
<button>— лучший выбор для действий- Если используете
<a>, добавьтеrole="button"иtabindex="0"при необходимости - Всегда используйте
addEventListenerвместоonclickв HTML
Итоговая рекомендация
- Для действий (открыть/закрыть, отправить, выполнить JS): используйте
<button type="button"> - Для навигации (переход на другую страницу или якорь): используйте
<a href="..."> - Если нужна ссылка с JS-действием:
<a href="javascript:void(0)">+addEventListener - Никогда не используйте
href="#"для JavaScript-ссылок
Альтернативный подход: обработка события на уровне родителя (делегирование)
Вместо того чтобы вешать обработчики на каждую ссылку, можно использовать делегирование событий. Это особенно полезно, когда у вас много динамически создаваемых ссылок.
<div id="linksContainer">
<a href="javascript:void(0)" class="js-action" data-action="openModal">Открыть модалку</a>
<a href="javascript:void(0)" class="js-action" data-action="saveData">Сохранить</a>
<a href="javascript:void(0)" class="js-action" data-action="deleteItem">Удалить</a>
</div>
<script>
document.getElementById('linksContainer').addEventListener('click', function(e) {
const link = e.target.closest('.js-action');
if (!link) return;
e.preventDefault();
const action = link.dataset.action;
switch(action) {
case 'openModal': openModal(); break;
case 'saveData': saveData(); break;
case 'deleteItem': deleteItem(); break;
}
});
</script>
Преимущества этого подхода:
- Один обработчик вместо множества — экономия памяти
- Автоматически работает для новых ссылок, добавленных через JavaScript
- Код чище и легче поддерживать
- Можно легко добавить дополнительную логику (логирование, аналитику) в одном месте
Важный нюанс: Даже при делегировании href="javascript:void(0)" остаётся хорошим выбором, потому что:
- Ссылка визуально остаётся ссылкой
- При случайном клике (если JavaScript ещё не загрузился) ничего не произойдёт
- Не ломает историю браузера
Этот подход особенно рекомендуется, если вы используете современные фреймворки (React, Vue, Angular), где управление событиями часто происходит на уровне компонентов.